From 36c6ce46a1abdb08eb9193704b9fce6bc7f3646b Mon Sep 17 00:00:00 2001 From: Aleksi Lindeman Date: Sat, 25 May 2019 02:17:15 +0200 Subject: Initial commit --- src/XpathParser.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/XpathParser.c (limited to 'src/XpathParser.c') diff --git a/src/XpathParser.c b/src/XpathParser.c new file mode 100644 index 0000000..24e1d6e --- /dev/null +++ b/src/XpathParser.c @@ -0,0 +1,88 @@ +#include "../include/quickmedia/XpathParser.h" +#include "../include/quickmedia/XpathTokenizer.h" +#include + +typedef struct { + QuickMediaXpathTokenizer tokenizer; +} QuickMediaXpathParser; + +static void quickmedia_xpath_parser_init(QuickMediaXpathParser *self, const char *xpath) { + quickmedia_xpath_tokenizer_init(&self->tokenizer, xpath); +} + +/* ('[' IDENTIFIER '=' '"' STRING '"' ']')? */ +static int xpath_parse_param(QuickMediaXpathParser *self, QuickMediaNodeSearchParam *result) { + if(quickmedia_xpath_tokenizer_next_if(&self->tokenizer, QUICKMEDIA_XPATH_TOKEN_OPEN_BRACKET) != 0) + return 1; + + QuickMediaXpathToken token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + if(token != QUICKMEDIA_XPATH_TOKEN_IDENTIFIER) + return -1; + + result->name = quickmedia_xpath_tokenizer_copy_identifier(&self->tokenizer); + + token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + if(token != QUICKMEDIA_XPATH_TOKEN_EQUAL) + return -2; + + token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + if(token != QUICKMEDIA_XPATH_TOKEN_STRING) + return -3; + + result->value = quickmedia_xpath_tokenizer_copy_string(&self->tokenizer); + + token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + if(token != QUICKMEDIA_XPATH_TOKEN_CLOSING_BRACKET) + return -4; + + return 0; +} + +static int xpath_parse_node(QuickMediaXpathParser *self, QuickMediaNodeSearch *result) { + quickmedia_node_search_init(result); + QuickMediaXpathToken token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + /* // or / */ + if(token == QUICKMEDIA_XPATH_TOKEN_CHILD || token == QUICKMEDIA_XPATH_TOKEN_CHILD_RECURSIVE) { + result->recursive = (token == QUICKMEDIA_XPATH_TOKEN_CHILD_RECURSIVE); + + token = quickmedia_xpath_tokenizer_next(&self->tokenizer); + if(token != QUICKMEDIA_XPATH_TOKEN_IDENTIFIER) + return -1; + + result->name = quickmedia_xpath_tokenizer_copy_identifier(&self->tokenizer); + + int param_result = xpath_parse_param(self, &result->param); + if(param_result < 0) { + quickmedia_node_search_deinit(result); + return param_result; + } else if(param_result == 0) { + result->param_defined = 1; + } + + result->child = malloc(sizeof(QuickMediaNodeSearch)); + int node_result = xpath_parse_node(self, result->child); + if(node_result > 0) { + node_result = 0; + /* Didn't have child, remove child */ + free(result->child); + result->child = NULL; + } else if(node_result < 0) { + quickmedia_node_search_deinit(result); + } + + return node_result; + } else if(token == QUICKMEDIA_XPATH_TOKEN_END_OF_FILE) { + return 1; + } else { + return -2; + } +} + +int quickmedia_parse_xpath(const char *xpath, QuickMediaNodeSearch *result) { + QuickMediaXpathParser parser; + quickmedia_xpath_parser_init(&parser, xpath); + int parse_result = xpath_parse_node(&parser, result); + if(parse_result > 0) + parse_result = -1; + return parse_result; +} -- cgit v1.2.3