2 * Copyright (c) 2015, Vsevolod Stakhov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "ucl_internal.h"
34 #define NEXT_STATE do { \
36 if (state != read_ebrace) { \
37 ucl_create_err (&parser->err,\
45 state = read_obrace; \
48 state = read_ebrace; \
53 state = read_length; \
60 ucl_parse_csexp (struct ucl_parser *parser)
62 const unsigned char *p, *end;
65 uint64_t len = 0, mult = 1;
73 } state = start_parse;
75 assert (parser != NULL);
76 assert (parser->chunks != NULL);
77 assert (parser->chunks->begin != NULL);
78 assert (parser->chunks->remain != 0);
80 p = parser->chunks->begin;
81 end = p + parser->chunks->remain;
86 /* At this point we expect open brace */
91 ucl_create_err (&parser->err, "bad starting character for "
92 "sexp block: %x", (int)*p);
98 st = calloc (1, sizeof (*st));
101 ucl_create_err (&parser->err, "no memory");
106 st->obj = ucl_object_typed_new (UCL_ARRAY);
108 if (st->obj == NULL) {
109 ucl_create_err (&parser->err, "no memory");
115 if (parser->stack == NULL) {
116 /* We have no stack */
119 if (parser->top_obj == NULL) {
120 parser->top_obj = st->obj;
124 /* Prepend new element to the stack */
125 LL_PREPEND (parser->stack, st);
136 ucl_create_err (&parser->err, "zero length element");
143 else if (*p >= '0' && *p <= '9') {
144 len += (*p - '0') * mult;
147 if (len > UINT32_MAX) {
148 ucl_create_err (&parser->err, "too big length of an "
155 ucl_create_err (&parser->err, "bad length character: %x",
165 if ((uint64_t)(end - p) > len || len == 0) {
166 ucl_create_err (&parser->err, "invalid length: %llu, %ld "
167 "remain", (long long unsigned)len, (long)(end - p));
171 obj = ucl_object_typed_new (UCL_STRING);
173 obj->value.sv = (const char*)p;
175 obj->flags |= UCL_OBJECT_BINARY;
177 if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
178 ucl_copy_value_trash (obj);
181 ucl_array_append (parser->stack->obj, obj);
187 if (parser->stack == NULL) {
188 /* We have an extra end brace */
189 ucl_create_err (&parser->err, "invalid length: %llu, %ld "
190 "remain", (long long unsigned)len, (long)(end - p));
194 /* Pop the container */
196 parser->stack = st->next;
198 if (parser->stack->obj->type == UCL_ARRAY) {
199 ucl_array_append (parser->stack->obj, st->obj);
202 ucl_create_err (&parser->err, "bad container object, array "
220 if (state != read_ebrace) {
221 ucl_create_err (&parser->err, "invalid finishing state: %d", state);