ssize_t parse_config_file(const char *buff, size_t bufflen, char sep, int (*handler)(char *key, char *value, void *data), void *data) { const char *buff_tmp, *buff_end = buff + bufflen; while (buff < buff_end) { int ret; char key[64]; char value[4096]; char *p, *p_bak, *p_end; buff_tmp = buff; while (buff_tmp < buff_end && *buff_tmp != '\n') { buff_tmp++; } while (buff < buff_tmp && byte_is_space_or_lf(*buff)) { buff++; } if (*buff == '#') { goto label_goto_next_line; } p_bak = p = key; p_end = p + sizeof(key) - 1; while (buff < buff_tmp && *buff != sep && p < p_end) { *p++ = *buff++; } if (p == p_bak) { goto label_goto_next_line; } while (--p >= p_bak && byte_is_space_or_lf(*p)); p[1] = 0; buff++; while (buff < buff_tmp && byte_is_space_or_lf(*buff)) { buff++; } p_bak = p = value; p_end = p + sizeof(value) - 1; while (buff < buff_tmp && *buff != '\n') { *p++ = *buff++; } if (p == p_bak) { goto label_goto_next_line; } while (--p >= p_bak && byte_is_space_or_lf(*p)); p[1] = 0; ret = handler(key, value, data); if (ret <= 0) { if (ret < 0) { return ret; } break; } label_goto_next_line: buff = buff_tmp + 1; } return 0; }
static int cavan_xml_document_get_next_token(struct cavan_xml_parser *parser, bool verbose) { char c; int ret; int lineno; char *p, *p_end; char *head, *tail, *value; struct cavan_xml_attribute *attr; parser->prev_token = parser->token; if (parser->next_token != CAVAN_XML_TOKEN_NONE) { parser->token = parser->next_token; parser->next_token = CAVAN_XML_TOKEN_NONE; return 0; } lineno = parser->lineno;; parser->name = NULL; parser->attr = NULL; parser->content = NULL; parser->comment = NULL; parser->token = CAVAN_XML_TOKEN_NONE; p = parser->pos; p_end = parser->pos_end; head = tail = p; while (p < p_end) { switch (*p) { case 0: case '\\': break; case '\n': lineno++; #if CONFIG_CAVAN_XML_DEBUG pr_green_info("lineno = %d", lineno); #endif case ' ': case '\t': case '\f': case '\r': p++; if (parser->token == CAVAN_XML_TOKEN_NONE) { head = p; } else { if (byte_is_space_or_lf(*head)) { head = p; } *tail = 0; } tail = p; break; case '<': if (parser->token != CAVAN_XML_TOKEN_NONE) { if (verbose) { pr_parser_error_info(lineno, "token = %d", parser->token); } ret = -EFAULT; goto out_cavan_xml_token_error; } switch (p[1]) { case '/': p++; parser->token = CAVAN_XML_TOKEN_TAG_END; break; case '?': p++; parser->token = CAVAN_XML_TOKEN_TAG_ATTR; break; case '!': if (text_lhcmp("--", p + 2) == 0) { p += 4; parser->comment = p; ret = cavan_xml_document_parse_comment(&p, p_end); if (ret < 0) { if (verbose) { pr_parser_error_info(lineno, "cavan_xml_document_parse_comment"); } ret = -EFAULT; goto out_cavan_xml_token_error; } parser->token = CAVAN_XML_TOKEN_COMMENT; parser->pos = p + 1; parser->lineno = lineno + ret; return 0; } default: parser->token = CAVAN_XML_TOKEN_TAG_BEGIN; } if (byte_is_named(*++p) == false) { if (verbose) { pr_parser_error_info(lineno, "tag name is empty"); } ret = -EFAULT; goto out_cavan_xml_token_error; } parser->name = p; p = text_skip_name(p, p_end); if (parser->name == p) { if (verbose) { pr_parser_error_info(lineno, "tag name is empty"); } ret = -EFAULT; goto out_cavan_xml_token_error; } head = tail = p; break; case '?': if (parser->token == CAVAN_XML_TOKEN_NONE) { if (verbose) { pr_parser_error_info(lineno, "invalid '?'"); } ret = -EFAULT; goto out_cavan_xml_token_error; } parser->token = CAVAN_XML_TOKEN_TAG_ATTR; goto label_tag_single; case '/': if (parser->token == CAVAN_XML_TOKEN_NONE) { if (verbose) { pr_parser_error_info(lineno, "invalid '/'"); } ret = -EFAULT; goto out_cavan_xml_token_error; } parser->token = CAVAN_XML_TOKEN_TAG_SINGLE; label_tag_single: if (*++p != '>') { if (verbose) { pr_parser_error_info(lineno, "need '>' by has '%c'", *p); } ret = -EFAULT; goto out_cavan_xml_token_error; } goto label_tag_end; case '>': if (parser->token == CAVAN_XML_TOKEN_NONE) { if (verbose) { pr_parser_error_info(lineno, "invalid '>'"); } ret = -EFAULT; goto out_cavan_xml_token_error; } label_tag_end: *tail = 0; if (cavan_xml_tag_is_content(parser->name)) { *tail = '>'; parser->token = CAVAN_XML_TOKEN_COTENT; } else { parser->pos = ++p; parser->lineno = lineno; } return 0; case '=': p = text_skip_space_and_lf(p + 1, p_end); c = *p; if (c != '"' && c != '\'') { if (verbose) { pr_parser_error_info(lineno, "need a '\"' or '"); } ret = -EFAULT; goto out_cavan_xml_token_error; } value = ++p; ret = cavan_xml_attribute_parse_value(c, &p, p_end); if (ret < 0) { if (verbose) { pr_parser_error_info(lineno, "cavan_xml_attribute_parse_value"); } ret = -EFAULT; goto out_cavan_xml_token_error; } lineno += ret; *tail = 0; if (cavan_xml_attribute_set(&parser->attr, head, value, 0) == false) { if (verbose) { pr_parser_error_info(lineno, "cavan_xml_attribute_alloc"); } ret = -EFAULT; goto out_cavan_xml_token_error; } head = tail = ++p; break; default: if (parser->token == CAVAN_XML_TOKEN_NONE) { if (verbose) { pr_parser_error_info(lineno, "invalid content"); } ret = -EFAULT; goto out_cavan_xml_token_error; } tail++, p++; } } ret = 0; parser->token = CAVAN_XML_TOKEN_EOF; out_cavan_xml_token_error: attr = parser->attr; while (attr) { struct cavan_xml_attribute *next = attr->next; cavan_xml_attribute_free(attr); attr = next; } return ret; }