#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; }