diff options
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/Makefile.am | 4 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 15 | ||||
-rw-r--r-- | libglusterfs/src/parse-utils.c | 178 | ||||
-rw-r--r-- | libglusterfs/src/parse-utils.h | 50 |
4 files changed, 245 insertions, 2 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index b403f2c3bf7..181babe85b0 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -28,7 +28,7 @@ libglusterfs_la_SOURCES = dict.c xlator.c logging.c \ event-history.c gidcache.c ctx.c client_t.c event-poll.c event-epoll.c \ syncop-utils.c \ $(CONTRIBDIR)/libgen/basename_r.c $(CONTRIBDIR)/libgen/dirname_r.c \ - $(CONTRIBDIR)/stdlib/gf_mkostemp.c strfd.c \ + $(CONTRIBDIR)/stdlib/gf_mkostemp.c strfd.c parse-utils.c \ $(CONTRIBDIR)/mount/mntent.c $(CONTRIBDIR)/libexecinfo/execinfo.c nodist_libglusterfs_la_SOURCES = y.tab.c graph.lex.c @@ -45,7 +45,7 @@ noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h timespec. $(CONTRIB_BUILDDIR)/uuid/uuid_types.h syncop.h graph-utils.h trie.h \ run.h options.h lkowner.h fd-lk.h circ-buff.h event-history.h \ gidcache.h client_t.h glusterfs-acl.h glfs-message-id.h \ - template-component-messages.h strfd.h syncop-utils.h \ + template-component-messages.h strfd.h syncop-utils.h parse-utils.h \ $(CONTRIBDIR)/mount/mntent_compat.h lvm-defaults.h \ $(CONTRIBDIR)/libexecinfo/execinfo_compat.h diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 6e1669912cd..71ff9eab5de 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -166,6 +166,21 @@ int gf_set_log_ident (cmd_args_t *cmd_args); } \ }while (0) +#define GF_CHECK_ALLOC(arg, retval, label) do { \ + if (!(arg)) { \ + retval = -ENOMEM; \ + goto label; \ + } \ + } while (0) \ + +#define GF_CHECK_ALLOC_AND_LOG(name, item, retval, msg, errlabel) do { \ + if (!(item)) { \ + (retval) = -ENOMEM; \ + gf_log (name, GF_LOG_CRITICAL, (msg)); \ + goto errlabel; \ + } \ + } while (0) + #define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error) do { \ if (!arg) { \ GF_ASSERT (0); \ diff --git a/libglusterfs/src/parse-utils.c b/libglusterfs/src/parse-utils.c new file mode 100644 index 00000000000..3934586aa32 --- /dev/null +++ b/libglusterfs/src/parse-utils.c @@ -0,0 +1,178 @@ +/* + Copyright 2014-present Facebook. All Rights Reserved + + This file is part of GlusterFS. + + Author : + Shreyas Siravara <shreyas.siravara@gmail.com> + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <regex.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "parse-utils.h" +#include "mem-pool.h" +#include "common-utils.h" + +/** + * parser_init: Initialize a parser with the a string to parse and + * the regex we want to use to parse it. + * + * @complete_str: the string to parse + * @regex : the regex to use + * + * Notes : It is up to the caller to call the parser_deinit () function + * to free the allocated parser. + * + * @return : success: parser ptr (on successful compilation and allocation) + * : failure: NULL (on failure to compile regex or allocate memory) + */ +struct parser * +parser_init (const char *regex) +{ + int rc = 0; + struct parser *parser = NULL; + + parser = MALLOC (sizeof(*parser)); + if (!parser) + goto out; + + parser->regex = gf_strdup (regex); + if (!parser->regex) { + gf_log (GF_PARSE, GF_LOG_INFO, + "Failed to duplicate regex string!"); + FREE (parser); + parser = NULL; + goto out; + } + + rc = regcomp (&parser->preg, parser->regex, REG_EXTENDED); + if (rc != 0) { + gf_log (GF_PARSE, GF_LOG_INFO, + "Failed to compile regex pattern."); + parser_deinit (parser); + parser = NULL; + goto out; + } + parser->complete_str = NULL; +out: + return parser; +} + +/** + * parser_set_string -- Set the string in the parser that we want to parse. + * Subsequent calls to get_next_match () will use this + * string along with the regex that the parser was + * initialized with. + * + * @parser : The parser to use + * @complete_str: The string to set in the parser (what we are going parse) + * + * @return: success: 0 + * failure: -EINVAL for NULL args, -ENOMEM for allocation errors + */ +int +parser_set_string (struct parser *parser, const char *complete_str) +{ + int ret = -EINVAL; + + GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out); + GF_VALIDATE_OR_GOTO (GF_PARSE, complete_str, out); + + parser->complete_str = gf_strdup (complete_str); + GF_CHECK_ALLOC_AND_LOG (GF_PARSE, parser, ret, + "Failed to duplicate string!", out); + + /* Point the temp internal string to what we just dup'ed */ + parser->_rstr = (char *)parser->complete_str; + ret = 0; +out: + return ret; +} + +/** + * parser_unset_string -- Free the string that was set to be parsed. + * This function needs to be called after + * parser_set_string and parser_get_next_match + * in order to free memory used by the string. + * + * @parser : The parser to free memory in + * @return : success: 0 + * : failure: -EINVAL on NULL args + */ +int +parser_unset_string (struct parser *parser) +{ + int ret = -EINVAL; + + GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out); + + GF_FREE (parser->complete_str); + parser->complete_str = NULL; /* Avoid double frees in parser_deinit */ + ret = 0; +out: + return ret; +} + +/** + * parser_deinit: Free the parser and all the memory allocated by it + * + * @parser : Parser to free + * + * @return : nothing + */ +void +parser_deinit (struct parser *ptr) +{ + if (!ptr) + return; + + regfree (&ptr->preg); + FREE (ptr->complete_str); + GF_FREE (ptr->regex); + FREE (ptr); +} + +/** + * parser_get_match: Given the parser that is configured with a compiled regex, + * return the next match in the string. + * + * @parser : Parser to use + * + * @return : success: Pointer to matched character + * : failure: NULL + */ +char * +parser_get_next_match (struct parser *parser) +{ + int rc = -EINVAL; + size_t copy_len = 0; + char *match = NULL; + + GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out); + + rc = regexec (&parser->preg, parser->_rstr, 1, parser->pmatch, 0); + if (rc != 0) { + gf_log (GF_PARSE, GF_LOG_DEBUG, + "Could not match %s with regex %s", + parser->_rstr, parser->regex); + goto out; + } + + copy_len = parser->pmatch[0].rm_eo - parser->pmatch[0].rm_so; + + match = gf_strndup (parser->_rstr + parser->pmatch[0].rm_so, copy_len); + GF_CHECK_ALLOC_AND_LOG (GF_PARSE, match, rc, + "Duplicating match failed!", out); + + parser->_rstr = &parser->_rstr[parser->pmatch[0].rm_eo]; +out: + return match; +} diff --git a/libglusterfs/src/parse-utils.h b/libglusterfs/src/parse-utils.h new file mode 100644 index 00000000000..275ccf3153b --- /dev/null +++ b/libglusterfs/src/parse-utils.h @@ -0,0 +1,50 @@ +/* + Copyright 2014-present Facebook. All Rights Reserved + + This file is part of GlusterFS. + + Author : + Shreyas Siravara <shreyas.siravara@gmail.com> + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _PARSE_UTILS_H +#define _PARSE_UTILS_H + +#include <regex.h> + +#define GF_PARSE "parse-utils" + +struct parser { + regex_t preg; /* Compiled regex */ + regmatch_t pmatch[1]; /* The match */ + char *complete_str; /* The string we are parsing */ + char *regex; /* Regex used to parse the string */ + char *_rstr; /* Temp string to hold offsets */ +}; + +/* Initializes some of the parsers variables */ +struct parser * +parser_init (const char *regex); + +/* Sets the string to parse */ +int +parser_set_string (struct parser *parser, const char *complete_str); + +/* Frees memory used by the string after all matches are found */ +int +parser_unset_string (struct parser *parser); + +/* Free memory used by the parser */ +void +parser_deinit (struct parser *ptr); + +/* Get the next matching string */ +char * +parser_get_next_match (struct parser *parser); + +#endif /* _PARSE_UTILS_H */ |