Beispiel #1
0
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;
}
Beispiel #2
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;
}