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");
114 if (parser->stack == NULL) {
115 /* We have no stack */
118 if (parser->top_obj == NULL) {
119 parser->top_obj = st->obj;
123 /* Prepend new element to the stack */
124 LL_PREPEND (parser->stack, st);
135 ucl_create_err (&parser->err, "zero length element");
142 else if (*p >= '0' && *p <= '9') {
143 len += (*p - '0') * mult;
146 if (len > UINT32_MAX) {
147 ucl_create_err (&parser->err, "too big length of an "
154 ucl_create_err (&parser->err, "bad length character: %x",
164 if ((uint64_t)(end - p) > len || len == 0) {
165 ucl_create_err (&parser->err, "invalid length: %llu, %ld "
166 "remain", (long long unsigned)len, (long)(end - p));
170 obj = ucl_object_typed_new (UCL_STRING);
172 obj->value.sv = (const char*)p;
174 obj->flags |= UCL_OBJECT_BINARY;
176 if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
177 ucl_copy_value_trash (obj);
180 ucl_array_append (parser->stack->obj, obj);
186 if (parser->stack == NULL) {
187 /* We have an extra end brace */
188 ucl_create_err (&parser->err, "invalid length: %llu, %ld "
189 "remain", (long long unsigned)len, (long)(end - p));
193 /* Pop the container */
195 parser->stack = st->next;
197 if (parser->stack->obj->type == UCL_ARRAY) {
198 ucl_array_append (parser->stack->obj, st->obj);
201 ucl_create_err (&parser->err, "bad container object, array "
218 if (state != read_ebrace) {
219 ucl_create_err (&parser->err, "invalid finishing state: %d", state);