summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/parse-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/parse-utils.c')
-rw-r--r--libglusterfs/src/parse-utils.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/libglusterfs/src/parse-utils.c b/libglusterfs/src/parse-utils.c
new file mode 100644
index 00000000000..4531d5f0170
--- /dev/null
+++ b/libglusterfs/src/parse-utils.c
@@ -0,0 +1,174 @@
+/*
+ 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 "glusterfs/parse-utils.h"
+#include "glusterfs/mem-pool.h"
+#include "glusterfs/common-utils.h"
+#include "glusterfs/libglusterfs-messages.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 = GF_MALLOC(sizeof(*parser), gf_common_mt_parser_t);
+ if (!parser)
+ goto out;
+
+ parser->regex = gf_strdup(regex);
+ if (!parser->regex) {
+ GF_FREE(parser);
+ parser = NULL;
+ goto out;
+ }
+
+ rc = regcomp(&parser->preg, parser->regex, REG_EXTENDED);
+ if (rc != 0) {
+ gf_msg(GF_PARSE, GF_LOG_INFO, 0, LG_MSG_REGEX_OP_FAILED,
+ "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);
+ GF_FREE(ptr->complete_str);
+ GF_FREE(ptr->regex);
+ GF_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_msg_debug(GF_PARSE, 0, "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;
+}