diff options
| author | Niels de Vos <ndevos@redhat.com> | 2015-01-01 13:15:45 +0100 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2015-03-03 12:31:38 -0800 | 
| commit | 95d5e60afb29aedc29909340e7564d54a6a247c2 (patch) | |
| tree | 9d0c2b2963e0b74add7109b5952c1252d868c3cf | |
| parent | 2acfbcf34ed77985905b2d122adbfd541eb01db1 (diff) | |
core: add generic parser utility
This generic parser will get used for parsing the netgroups and exports
files for the Gluster/NFS server. The parsing of netgroups shows how the
parser can be used (see Change-Id Ie04800d4).
BUG: 1143880
Change-Id: Id4cf2b0189ef5799c06868d211d3fcd9c8608c08
Original-author: Shreyas Siravara <shreyas.siravara@gmail.com>
CC: Richard Wareing <rwareing@fb.com>
CC: Jiffin Tony Thottan <jthottan@redhat.com>
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/9359
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
| -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 */  | 
