diff options
Diffstat (limited to 'libglusterfs/src/parse-utils.c')
-rw-r--r-- | libglusterfs/src/parse-utils.c | 178 |
1 files changed, 178 insertions, 0 deletions
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; +} |