JSON parsing library by Andrii Mamchur https://github.com/amamchur/jsonlite

Dependents:   M2X_dev MTS_M2x_Example1 MTS_M2x_Example m2x-demo-all ... more

Committer:
citrusbyte
Date:
Thu Oct 24 12:20:56 2013 +0000
Revision:
0:01a2f8de46c8
Child:
1:807034181e02
Initial commit of jsonlite library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
citrusbyte 0:01a2f8de46c8 1 #define JSONLITE_AMALGAMATED
citrusbyte 0:01a2f8de46c8 2 #include "jsonlite.h"
citrusbyte 0:01a2f8de46c8 3 //
citrusbyte 0:01a2f8de46c8 4 // Copyright 2012-2013, Andrii Mamchur
citrusbyte 0:01a2f8de46c8 5 //
citrusbyte 0:01a2f8de46c8 6 // Licensed under the Apache License, Version 2.0 (the "License");
citrusbyte 0:01a2f8de46c8 7 // you may not use this file except in compliance with the License.
citrusbyte 0:01a2f8de46c8 8 // You may obtain a copy of the License at
citrusbyte 0:01a2f8de46c8 9 //
citrusbyte 0:01a2f8de46c8 10 // http://www.apache.org/licenses/LICENSE-2.0
citrusbyte 0:01a2f8de46c8 11 //
citrusbyte 0:01a2f8de46c8 12 // Unless required by applicable law or agreed to in writing, software
citrusbyte 0:01a2f8de46c8 13 // distributed under the License is distributed on an "AS IS" BASIS,
citrusbyte 0:01a2f8de46c8 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
citrusbyte 0:01a2f8de46c8 15 // See the License for the specific language governing permissions and
citrusbyte 0:01a2f8de46c8 16 // limitations under the License
citrusbyte 0:01a2f8de46c8 17
citrusbyte 0:01a2f8de46c8 18 #ifndef JSONLITE_AMALGAMATED
citrusbyte 0:01a2f8de46c8 19 #include "jsonlite_parser.h"
citrusbyte 0:01a2f8de46c8 20 #endif
citrusbyte 0:01a2f8de46c8 21
citrusbyte 0:01a2f8de46c8 22 #include <stdlib.h>
citrusbyte 0:01a2f8de46c8 23 #include <string.h>
citrusbyte 0:01a2f8de46c8 24
citrusbyte 0:01a2f8de46c8 25 #ifdef _MSC_VER
citrusbyte 0:01a2f8de46c8 26
citrusbyte 0:01a2f8de46c8 27 #include <intrin.h>
citrusbyte 0:01a2f8de46c8 28
citrusbyte 0:01a2f8de46c8 29 static uint32_t __inline jsonlite_clz(uint32_t x) {
citrusbyte 0:01a2f8de46c8 30 unsigned long r = 0;
citrusbyte 0:01a2f8de46c8 31 _BitScanForward(&r, x);
citrusbyte 0:01a2f8de46c8 32 return r;
citrusbyte 0:01a2f8de46c8 33 }
citrusbyte 0:01a2f8de46c8 34
citrusbyte 0:01a2f8de46c8 35 #else
citrusbyte 0:01a2f8de46c8 36
citrusbyte 0:01a2f8de46c8 37 #define jsonlite_clz(x) __builtin_clz((x))
citrusbyte 0:01a2f8de46c8 38
citrusbyte 0:01a2f8de46c8 39 #endif
citrusbyte 0:01a2f8de46c8 40
citrusbyte 0:01a2f8de46c8 41 #define CALL_VALUE_CALLBACK(cbs, type, token) (cbs.type(&cbs.context, token))
citrusbyte 0:01a2f8de46c8 42 #define CALL_STATE_CALLBACK(cbs, type) (cbs.type(&cbs.context))
citrusbyte 0:01a2f8de46c8 43
citrusbyte 0:01a2f8de46c8 44 #define CHECK_HEX(c) \
citrusbyte 0:01a2f8de46c8 45 if ((c) < 48) goto error_escape; \
citrusbyte 0:01a2f8de46c8 46 if ((c) > 102) goto error_escape; \
citrusbyte 0:01a2f8de46c8 47 if (57 < (c) && (c) < 65) goto error_escape; \
citrusbyte 0:01a2f8de46c8 48 if (70 < (c) && (c) < 97) goto error_escape
citrusbyte 0:01a2f8de46c8 49
citrusbyte 0:01a2f8de46c8 50 #define CASE_NUMBER_TOKEN_END \
citrusbyte 0:01a2f8de46c8 51 case 9: goto found_token; \
citrusbyte 0:01a2f8de46c8 52 case 10: goto found_token; \
citrusbyte 0:01a2f8de46c8 53 case 13: goto found_token; \
citrusbyte 0:01a2f8de46c8 54 case 32: goto found_token; \
citrusbyte 0:01a2f8de46c8 55 case 44: goto found_token; \
citrusbyte 0:01a2f8de46c8 56 case 93: goto found_token; \
citrusbyte 0:01a2f8de46c8 57 case 125: goto found_token
citrusbyte 0:01a2f8de46c8 58
citrusbyte 0:01a2f8de46c8 59 enum {
citrusbyte 0:01a2f8de46c8 60 state_start,
citrusbyte 0:01a2f8de46c8 61 state_object_key,
citrusbyte 0:01a2f8de46c8 62 state_object_key_end,
citrusbyte 0:01a2f8de46c8 63 state_colon,
citrusbyte 0:01a2f8de46c8 64 state_object_comma_end,
citrusbyte 0:01a2f8de46c8 65 state_array_value_end,
citrusbyte 0:01a2f8de46c8 66 state_array_comma_end,
citrusbyte 0:01a2f8de46c8 67 state_key,
citrusbyte 0:01a2f8de46c8 68 state_value,
citrusbyte 0:01a2f8de46c8 69 state_end,
citrusbyte 0:01a2f8de46c8 70
citrusbyte 0:01a2f8de46c8 71 state_suspend = 1 << 7
citrusbyte 0:01a2f8de46c8 72 };
citrusbyte 0:01a2f8de46c8 73
citrusbyte 0:01a2f8de46c8 74 typedef uint8_t parse_state;
citrusbyte 0:01a2f8de46c8 75 struct jsonlite_parser_struct {
citrusbyte 0:01a2f8de46c8 76 const uint8_t *cursor;
citrusbyte 0:01a2f8de46c8 77 const uint8_t *limit;
citrusbyte 0:01a2f8de46c8 78 const uint8_t *token_start;
citrusbyte 0:01a2f8de46c8 79 const uint8_t *buffer;
citrusbyte 0:01a2f8de46c8 80
citrusbyte 0:01a2f8de46c8 81 uint8_t *buffer_own;
citrusbyte 0:01a2f8de46c8 82 uint8_t *rest;
citrusbyte 0:01a2f8de46c8 83 size_t rest_size;
citrusbyte 0:01a2f8de46c8 84
citrusbyte 0:01a2f8de46c8 85 parse_state *current;
citrusbyte 0:01a2f8de46c8 86 const parse_state *last;
citrusbyte 0:01a2f8de46c8 87
citrusbyte 0:01a2f8de46c8 88 jsonlite_result result;
citrusbyte 0:01a2f8de46c8 89 jsonlite_parser_callbacks callbacks;
citrusbyte 0:01a2f8de46c8 90 } jsonlite_parser_struct;
citrusbyte 0:01a2f8de46c8 91
citrusbyte 0:01a2f8de46c8 92 static void jsonlite_do_parse(jsonlite_parser parser);
citrusbyte 0:01a2f8de46c8 93 static void jsonlite_finish_parse(jsonlite_parser parser);
citrusbyte 0:01a2f8de46c8 94 static void empty_value_callback(jsonlite_callback_context *ctx, jsonlite_token *t) {}
citrusbyte 0:01a2f8de46c8 95 static void empty_state_callback(jsonlite_callback_context *ctx) {}
citrusbyte 0:01a2f8de46c8 96
citrusbyte 0:01a2f8de46c8 97 const jsonlite_parser_callbacks jsonlite_default_callbacks = {
citrusbyte 0:01a2f8de46c8 98 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 99 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 100 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 101 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 102 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 103 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 104 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 105 &empty_state_callback,
citrusbyte 0:01a2f8de46c8 106 &empty_value_callback,
citrusbyte 0:01a2f8de46c8 107 &empty_value_callback,
citrusbyte 0:01a2f8de46c8 108 &empty_value_callback,
citrusbyte 0:01a2f8de46c8 109 {NULL, NULL}
citrusbyte 0:01a2f8de46c8 110 };
citrusbyte 0:01a2f8de46c8 111
citrusbyte 0:01a2f8de46c8 112 size_t jsonlite_parser_estimate_size(size_t depth) {
citrusbyte 0:01a2f8de46c8 113 depth = depth < 2 ? 32 : depth;
citrusbyte 0:01a2f8de46c8 114 return sizeof(jsonlite_parser_struct) + depth * sizeof(parse_state);
citrusbyte 0:01a2f8de46c8 115 }
citrusbyte 0:01a2f8de46c8 116
citrusbyte 0:01a2f8de46c8 117 jsonlite_parser jsonlite_parser_init(size_t depth) {
citrusbyte 0:01a2f8de46c8 118 depth = depth < 2 ? 32 : depth;
citrusbyte 0:01a2f8de46c8 119
citrusbyte 0:01a2f8de46c8 120 jsonlite_parser parser = (jsonlite_parser)calloc(1, jsonlite_parser_estimate_size(depth));
citrusbyte 0:01a2f8de46c8 121 parser->result = jsonlite_result_unknown;
citrusbyte 0:01a2f8de46c8 122 parser->callbacks = jsonlite_default_callbacks;
citrusbyte 0:01a2f8de46c8 123 parser->current = (parse_state *)((uint8_t *)parser + sizeof(jsonlite_parser_struct));
citrusbyte 0:01a2f8de46c8 124 parser->current[0] = state_end;
citrusbyte 0:01a2f8de46c8 125 parser->current[1] = state_start;
citrusbyte 0:01a2f8de46c8 126 parser->last = parser->current + depth;
citrusbyte 0:01a2f8de46c8 127 parser->current++;
citrusbyte 0:01a2f8de46c8 128 return parser;
citrusbyte 0:01a2f8de46c8 129 }
citrusbyte 0:01a2f8de46c8 130
citrusbyte 0:01a2f8de46c8 131 jsonlite_result jsonlite_parser_set_callback(jsonlite_parser parser, const jsonlite_parser_callbacks *cbs) {
citrusbyte 0:01a2f8de46c8 132 if (parser == NULL || cbs == NULL) {
citrusbyte 0:01a2f8de46c8 133 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 134 }
citrusbyte 0:01a2f8de46c8 135
citrusbyte 0:01a2f8de46c8 136 parser->callbacks = *cbs;
citrusbyte 0:01a2f8de46c8 137 parser->callbacks.context.parser = parser;
citrusbyte 0:01a2f8de46c8 138 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 139 }
citrusbyte 0:01a2f8de46c8 140
citrusbyte 0:01a2f8de46c8 141 jsonlite_result jsonlite_parser_get_result(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 142 if (parser == NULL) {
citrusbyte 0:01a2f8de46c8 143 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 144 }
citrusbyte 0:01a2f8de46c8 145
citrusbyte 0:01a2f8de46c8 146 return parser->result;
citrusbyte 0:01a2f8de46c8 147 }
citrusbyte 0:01a2f8de46c8 148
citrusbyte 0:01a2f8de46c8 149 jsonlite_result jsonlite_parser_tokenize(jsonlite_parser parser, const void *buffer, size_t size) {
citrusbyte 0:01a2f8de46c8 150 if (parser == NULL || buffer == NULL || size == 0) {
citrusbyte 0:01a2f8de46c8 151 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 152 }
citrusbyte 0:01a2f8de46c8 153
citrusbyte 0:01a2f8de46c8 154 if (parser->rest != NULL) {
citrusbyte 0:01a2f8de46c8 155 size_t total_size = size + parser->rest_size;
citrusbyte 0:01a2f8de46c8 156 uint8_t *b = (uint8_t *)malloc(total_size);
citrusbyte 0:01a2f8de46c8 157 memcpy(b, parser->rest, parser->rest_size); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 158 memcpy(b + parser->rest_size, buffer, size); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 159
citrusbyte 0:01a2f8de46c8 160 free(parser->buffer_own);
citrusbyte 0:01a2f8de46c8 161 free(parser->rest);
citrusbyte 0:01a2f8de46c8 162
citrusbyte 0:01a2f8de46c8 163 parser->buffer = b;
citrusbyte 0:01a2f8de46c8 164 parser->buffer_own = b;
citrusbyte 0:01a2f8de46c8 165 parser->cursor = parser->buffer;
citrusbyte 0:01a2f8de46c8 166 parser->limit = parser->buffer + total_size;
citrusbyte 0:01a2f8de46c8 167 parser->rest = NULL;
citrusbyte 0:01a2f8de46c8 168 parser->rest_size = 0;
citrusbyte 0:01a2f8de46c8 169 } else {
citrusbyte 0:01a2f8de46c8 170 parser->buffer = buffer;
citrusbyte 0:01a2f8de46c8 171 parser->cursor = parser->buffer;
citrusbyte 0:01a2f8de46c8 172 parser->limit = parser->buffer + size;
citrusbyte 0:01a2f8de46c8 173 }
citrusbyte 0:01a2f8de46c8 174
citrusbyte 0:01a2f8de46c8 175 jsonlite_do_parse(parser);
citrusbyte 0:01a2f8de46c8 176 jsonlite_finish_parse(parser);
citrusbyte 0:01a2f8de46c8 177 return parser->result;
citrusbyte 0:01a2f8de46c8 178 }
citrusbyte 0:01a2f8de46c8 179
citrusbyte 0:01a2f8de46c8 180 jsonlite_result jsonlite_parser_resume(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 181 if (parser == NULL) {
citrusbyte 0:01a2f8de46c8 182 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 183 }
citrusbyte 0:01a2f8de46c8 184
citrusbyte 0:01a2f8de46c8 185 if (parser->result != jsonlite_result_suspended) {
citrusbyte 0:01a2f8de46c8 186 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 187 }
citrusbyte 0:01a2f8de46c8 188
citrusbyte 0:01a2f8de46c8 189 jsonlite_do_parse(parser);
citrusbyte 0:01a2f8de46c8 190 jsonlite_finish_parse(parser);
citrusbyte 0:01a2f8de46c8 191 return parser->result;
citrusbyte 0:01a2f8de46c8 192 }
citrusbyte 0:01a2f8de46c8 193
citrusbyte 0:01a2f8de46c8 194 jsonlite_result jsonlite_parser_suspend(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 195 if (parser == NULL) {
citrusbyte 0:01a2f8de46c8 196 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 197 }
citrusbyte 0:01a2f8de46c8 198
citrusbyte 0:01a2f8de46c8 199 if (parser->result != jsonlite_result_unknown) {
citrusbyte 0:01a2f8de46c8 200 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 201 }
citrusbyte 0:01a2f8de46c8 202
citrusbyte 0:01a2f8de46c8 203 parser->result = jsonlite_result_suspended;
citrusbyte 0:01a2f8de46c8 204 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 205 }
citrusbyte 0:01a2f8de46c8 206
citrusbyte 0:01a2f8de46c8 207 void jsonlite_parser_release(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 208 if (parser == NULL) {
citrusbyte 0:01a2f8de46c8 209 return;
citrusbyte 0:01a2f8de46c8 210 }
citrusbyte 0:01a2f8de46c8 211
citrusbyte 0:01a2f8de46c8 212 free(parser->buffer_own);
citrusbyte 0:01a2f8de46c8 213 free(parser->rest);
citrusbyte 0:01a2f8de46c8 214 free(parser);
citrusbyte 0:01a2f8de46c8 215 }
citrusbyte 0:01a2f8de46c8 216
citrusbyte 0:01a2f8de46c8 217 static void jsonlite_do_parse(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 218 const uint8_t *c = parser->cursor;
citrusbyte 0:01a2f8de46c8 219 const uint8_t *l = parser->limit;
citrusbyte 0:01a2f8de46c8 220 const uint8_t *token_start = NULL;
citrusbyte 0:01a2f8de46c8 221 const parse_state *last = parser->last;
citrusbyte 0:01a2f8de46c8 222 parse_state *state = parser->current;
citrusbyte 0:01a2f8de46c8 223 jsonlite_token token;
citrusbyte 0:01a2f8de46c8 224 parser->result = jsonlite_result_unknown;
citrusbyte 0:01a2f8de46c8 225 goto state_selection;
citrusbyte 0:01a2f8de46c8 226
citrusbyte 0:01a2f8de46c8 227 structure_finished:
citrusbyte 0:01a2f8de46c8 228 if (*--state == state_end) goto success;
citrusbyte 0:01a2f8de46c8 229 skip_char_and_spaces:
citrusbyte 0:01a2f8de46c8 230 c++;
citrusbyte 0:01a2f8de46c8 231 state_selection:
citrusbyte 0:01a2f8de46c8 232 if (c == l) goto end_of_stream_space;
citrusbyte 0:01a2f8de46c8 233 if (*c == ' ') goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 234 if (*c == '\n') goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 235 if (*c == '\r') goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 236 if (*c == '\t') goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 237 token_start = c;
citrusbyte 0:01a2f8de46c8 238
citrusbyte 0:01a2f8de46c8 239 if (parser->result != jsonlite_result_unknown) goto end;
citrusbyte 0:01a2f8de46c8 240 switch (*state) {
citrusbyte 0:01a2f8de46c8 241 case state_value: goto value_type_detection;
citrusbyte 0:01a2f8de46c8 242 case state_key: goto string_token_parsing;
citrusbyte 0:01a2f8de46c8 243 case state_object_key: goto key_checking;
citrusbyte 0:01a2f8de46c8 244 case state_object_key_end: goto key_end_checking;
citrusbyte 0:01a2f8de46c8 245 case state_colon: goto colon_checking;
citrusbyte 0:01a2f8de46c8 246 case state_object_comma_end: goto object_comma_end_checking;
citrusbyte 0:01a2f8de46c8 247 case state_array_value_end: goto array_value_end_checking;
citrusbyte 0:01a2f8de46c8 248 case state_array_comma_end: goto array_comma_end_checking;
citrusbyte 0:01a2f8de46c8 249 case state_start:
citrusbyte 0:01a2f8de46c8 250 if (*c == '{') goto object_state_machine;
citrusbyte 0:01a2f8de46c8 251 if (*c == '[') goto array_state_machine;
citrusbyte 0:01a2f8de46c8 252 goto error_exp_ooa;
citrusbyte 0:01a2f8de46c8 253 default:
citrusbyte 0:01a2f8de46c8 254 goto suspend;
citrusbyte 0:01a2f8de46c8 255 }
citrusbyte 0:01a2f8de46c8 256
citrusbyte 0:01a2f8de46c8 257 object_state_machine:
citrusbyte 0:01a2f8de46c8 258 *state = state_object_key_end;
citrusbyte 0:01a2f8de46c8 259 CALL_STATE_CALLBACK(parser->callbacks, object_start);
citrusbyte 0:01a2f8de46c8 260 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 261
citrusbyte 0:01a2f8de46c8 262 array_state_machine:
citrusbyte 0:01a2f8de46c8 263 *state = state_array_value_end;
citrusbyte 0:01a2f8de46c8 264 CALL_STATE_CALLBACK(parser->callbacks, array_start);
citrusbyte 0:01a2f8de46c8 265 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 266
citrusbyte 0:01a2f8de46c8 267 key_checking:
citrusbyte 0:01a2f8de46c8 268 if (*c != '"') goto error_exp_key;
citrusbyte 0:01a2f8de46c8 269 *state = state_colon;
citrusbyte 0:01a2f8de46c8 270 *++state = state_key;
citrusbyte 0:01a2f8de46c8 271 goto string_token_parsing;
citrusbyte 0:01a2f8de46c8 272
citrusbyte 0:01a2f8de46c8 273 colon_checking:
citrusbyte 0:01a2f8de46c8 274 if (*c != ':') goto error_exp_colon;
citrusbyte 0:01a2f8de46c8 275 *state = state_object_comma_end;
citrusbyte 0:01a2f8de46c8 276 *++state = state_value;
citrusbyte 0:01a2f8de46c8 277 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 278
citrusbyte 0:01a2f8de46c8 279 key_end_checking:
citrusbyte 0:01a2f8de46c8 280 switch (*c) {
citrusbyte 0:01a2f8de46c8 281 case '"':
citrusbyte 0:01a2f8de46c8 282 *state = state_colon;
citrusbyte 0:01a2f8de46c8 283 if (++state == last) goto error_depth;
citrusbyte 0:01a2f8de46c8 284 *state = state_key;
citrusbyte 0:01a2f8de46c8 285 goto string_token_parsing;
citrusbyte 0:01a2f8de46c8 286 case '}':
citrusbyte 0:01a2f8de46c8 287 CALL_STATE_CALLBACK(parser->callbacks, object_end);
citrusbyte 0:01a2f8de46c8 288 goto structure_finished;
citrusbyte 0:01a2f8de46c8 289 }
citrusbyte 0:01a2f8de46c8 290 goto error_exp_koe;
citrusbyte 0:01a2f8de46c8 291
citrusbyte 0:01a2f8de46c8 292 object_comma_end_checking:
citrusbyte 0:01a2f8de46c8 293 switch (*c) {
citrusbyte 0:01a2f8de46c8 294 case ',':
citrusbyte 0:01a2f8de46c8 295 *state = state_object_key;
citrusbyte 0:01a2f8de46c8 296 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 297 case '}':
citrusbyte 0:01a2f8de46c8 298 CALL_STATE_CALLBACK(parser->callbacks, object_end);
citrusbyte 0:01a2f8de46c8 299 goto structure_finished;
citrusbyte 0:01a2f8de46c8 300 }
citrusbyte 0:01a2f8de46c8 301 goto error_exp_coe;
citrusbyte 0:01a2f8de46c8 302
citrusbyte 0:01a2f8de46c8 303 array_value_end_checking:
citrusbyte 0:01a2f8de46c8 304 switch (*c) {
citrusbyte 0:01a2f8de46c8 305 case ']':
citrusbyte 0:01a2f8de46c8 306 CALL_STATE_CALLBACK(parser->callbacks, array_end);
citrusbyte 0:01a2f8de46c8 307 goto structure_finished;
citrusbyte 0:01a2f8de46c8 308 default:
citrusbyte 0:01a2f8de46c8 309 *state = state_array_comma_end;
citrusbyte 0:01a2f8de46c8 310 if (++state == last) goto error_depth;
citrusbyte 0:01a2f8de46c8 311 *state = state_value;
citrusbyte 0:01a2f8de46c8 312 goto value_type_detection;
citrusbyte 0:01a2f8de46c8 313 }
citrusbyte 0:01a2f8de46c8 314
citrusbyte 0:01a2f8de46c8 315 array_comma_end_checking:
citrusbyte 0:01a2f8de46c8 316 switch (*c) {
citrusbyte 0:01a2f8de46c8 317 case ',':
citrusbyte 0:01a2f8de46c8 318 *++state = state_value;
citrusbyte 0:01a2f8de46c8 319 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 320 case ']':
citrusbyte 0:01a2f8de46c8 321 CALL_STATE_CALLBACK(parser->callbacks, array_end);
citrusbyte 0:01a2f8de46c8 322 goto structure_finished;
citrusbyte 0:01a2f8de46c8 323 }
citrusbyte 0:01a2f8de46c8 324 goto error_exp_coe;
citrusbyte 0:01a2f8de46c8 325
citrusbyte 0:01a2f8de46c8 326 value_type_detection:
citrusbyte 0:01a2f8de46c8 327 if (*c == '-' || ('0' <= *c && *c <= '9')) goto number_parsing;
citrusbyte 0:01a2f8de46c8 328 if (*c == '"') goto string_token_parsing;
citrusbyte 0:01a2f8de46c8 329 if (*c == 't') goto true_token_parsing;
citrusbyte 0:01a2f8de46c8 330 if (*c == 'f') goto false_token_paring;
citrusbyte 0:01a2f8de46c8 331 if (*c == 'n') goto null_token_parsing;
citrusbyte 0:01a2f8de46c8 332 if (*c == '{') goto object_state_machine;
citrusbyte 0:01a2f8de46c8 333 if (*c == '[') goto array_state_machine;
citrusbyte 0:01a2f8de46c8 334 goto error_exp_value;
citrusbyte 0:01a2f8de46c8 335
citrusbyte 0:01a2f8de46c8 336 // State machine for number token parsing.
citrusbyte 0:01a2f8de46c8 337 number_parsing:
citrusbyte 0:01a2f8de46c8 338 {
citrusbyte 0:01a2f8de46c8 339 jsonlite_number_type type = jsonlite_number_int;
citrusbyte 0:01a2f8de46c8 340 token.start = c;
citrusbyte 0:01a2f8de46c8 341 switch (*c) {
citrusbyte 0:01a2f8de46c8 342 case 45: type |= jsonlite_number_negative; goto test_zero_leading;
citrusbyte 0:01a2f8de46c8 343 case 48: type |= jsonlite_number_zero_leading; goto take_exp_frac;
citrusbyte 0:01a2f8de46c8 344 default: type |= jsonlite_number_digit_leading; goto take_digits;
citrusbyte 0:01a2f8de46c8 345 }
citrusbyte 0:01a2f8de46c8 346
citrusbyte 0:01a2f8de46c8 347 test_zero_leading:
citrusbyte 0:01a2f8de46c8 348 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 349 if (49 <= *c && *c <= 57) goto take_digits;
citrusbyte 0:01a2f8de46c8 350 if (*c == 48) goto take_exp_frac;
citrusbyte 0:01a2f8de46c8 351 goto error_number;
citrusbyte 0:01a2f8de46c8 352 take_exp_frac:
citrusbyte 0:01a2f8de46c8 353 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 354 switch (*c) {
citrusbyte 0:01a2f8de46c8 355 CASE_NUMBER_TOKEN_END;
citrusbyte 0:01a2f8de46c8 356 case 46: goto found_fraction;
citrusbyte 0:01a2f8de46c8 357 case 69: goto take_exponent;
citrusbyte 0:01a2f8de46c8 358 case 101: goto take_exponent;
citrusbyte 0:01a2f8de46c8 359 default: goto error_number;
citrusbyte 0:01a2f8de46c8 360 }
citrusbyte 0:01a2f8de46c8 361 found_fraction:
citrusbyte 0:01a2f8de46c8 362 type |= jsonlite_number_frac;
citrusbyte 0:01a2f8de46c8 363 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 364 if (48 <= *c && *c <= 57) goto take_frac_number;
citrusbyte 0:01a2f8de46c8 365 goto error_number;
citrusbyte 0:01a2f8de46c8 366 take_frac_number:
citrusbyte 0:01a2f8de46c8 367 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 368 if (48 <= *c && *c <= 57) goto take_frac_number;
citrusbyte 0:01a2f8de46c8 369 switch (*c) {
citrusbyte 0:01a2f8de46c8 370 CASE_NUMBER_TOKEN_END;
citrusbyte 0:01a2f8de46c8 371 case 69: goto take_exponent;
citrusbyte 0:01a2f8de46c8 372 case 101: goto take_exponent;
citrusbyte 0:01a2f8de46c8 373 default: goto error_number;
citrusbyte 0:01a2f8de46c8 374 }
citrusbyte 0:01a2f8de46c8 375 take_exponent:
citrusbyte 0:01a2f8de46c8 376 type |= jsonlite_number_exp;
citrusbyte 0:01a2f8de46c8 377 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 378 if (48 <= *c && *c <= 57) goto take_exponent_number;
citrusbyte 0:01a2f8de46c8 379 switch(*c) {
citrusbyte 0:01a2f8de46c8 380 case 43: goto take_exponent_sign;
citrusbyte 0:01a2f8de46c8 381 case 45: goto take_exponent_sign;
citrusbyte 0:01a2f8de46c8 382 default: goto error_number;
citrusbyte 0:01a2f8de46c8 383 }
citrusbyte 0:01a2f8de46c8 384 take_exponent_sign:
citrusbyte 0:01a2f8de46c8 385 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 386 if (48 <= *c && *c <= 57) goto take_exponent_number;
citrusbyte 0:01a2f8de46c8 387 goto error_number;
citrusbyte 0:01a2f8de46c8 388 take_exponent_number:
citrusbyte 0:01a2f8de46c8 389 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 390 if (48 <= *c && *c <= 57) goto take_exponent_number;
citrusbyte 0:01a2f8de46c8 391 switch(*c) {
citrusbyte 0:01a2f8de46c8 392 CASE_NUMBER_TOKEN_END;
citrusbyte 0:01a2f8de46c8 393 default: goto error_number;
citrusbyte 0:01a2f8de46c8 394 }
citrusbyte 0:01a2f8de46c8 395 take_digits:
citrusbyte 0:01a2f8de46c8 396 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 397 if (48 <= *c && *c <= 57) goto take_digits;
citrusbyte 0:01a2f8de46c8 398 switch(*c) {
citrusbyte 0:01a2f8de46c8 399 CASE_NUMBER_TOKEN_END;
citrusbyte 0:01a2f8de46c8 400 case 46: goto found_fraction;
citrusbyte 0:01a2f8de46c8 401 case 69: goto take_exponent;
citrusbyte 0:01a2f8de46c8 402 case 101: goto take_exponent;
citrusbyte 0:01a2f8de46c8 403 default: goto error_number;
citrusbyte 0:01a2f8de46c8 404 }
citrusbyte 0:01a2f8de46c8 405 found_token:
citrusbyte 0:01a2f8de46c8 406 token.end = c;
citrusbyte 0:01a2f8de46c8 407 token.number_type = type;
citrusbyte 0:01a2f8de46c8 408 CALL_VALUE_CALLBACK(parser->callbacks, number_found, &token);
citrusbyte 0:01a2f8de46c8 409 state--;
citrusbyte 0:01a2f8de46c8 410 goto state_selection;
citrusbyte 0:01a2f8de46c8 411 }
citrusbyte 0:01a2f8de46c8 412
citrusbyte 0:01a2f8de46c8 413 // State machine for string token parsing.
citrusbyte 0:01a2f8de46c8 414 string_token_parsing:
citrusbyte 0:01a2f8de46c8 415 {
citrusbyte 0:01a2f8de46c8 416 jsonlite_string_type type = jsonlite_string_ascii;
citrusbyte 0:01a2f8de46c8 417 uint32_t value, utf32;
citrusbyte 0:01a2f8de46c8 418 token.start = c + 1;
citrusbyte 0:01a2f8de46c8 419 next_char:
citrusbyte 0:01a2f8de46c8 420 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 421 if (*c == '"') goto string_parsed;
citrusbyte 0:01a2f8de46c8 422 if (*c == '\\') goto escaped;
citrusbyte 0:01a2f8de46c8 423 if (*c >= 0x80) goto utf8;
citrusbyte 0:01a2f8de46c8 424 if (*c < 0x20) goto error_token;
citrusbyte 0:01a2f8de46c8 425 goto next_char;
citrusbyte 0:01a2f8de46c8 426 escaped:
citrusbyte 0:01a2f8de46c8 427 type |= jsonlite_string_escape;
citrusbyte 0:01a2f8de46c8 428 if (++c == l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 429 switch (*c) {
citrusbyte 0:01a2f8de46c8 430 case 34: goto next_char;
citrusbyte 0:01a2f8de46c8 431 case 47: goto next_char;
citrusbyte 0:01a2f8de46c8 432 case 92: goto next_char;
citrusbyte 0:01a2f8de46c8 433 case 98: goto next_char;
citrusbyte 0:01a2f8de46c8 434 case 102: goto next_char;
citrusbyte 0:01a2f8de46c8 435 case 110: goto next_char;
citrusbyte 0:01a2f8de46c8 436 case 114: goto next_char;
citrusbyte 0:01a2f8de46c8 437 case 116: goto next_char;
citrusbyte 0:01a2f8de46c8 438 case 117: goto hex;
citrusbyte 0:01a2f8de46c8 439 }
citrusbyte 0:01a2f8de46c8 440 goto error_escape;
citrusbyte 0:01a2f8de46c8 441 hex:
citrusbyte 0:01a2f8de46c8 442 type |= jsonlite_string_unicode_escape;
citrusbyte 0:01a2f8de46c8 443 if (c++ + 4 >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 444 CHECK_HEX(*c); value = jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 445 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 446 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 447 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c);
citrusbyte 0:01a2f8de46c8 448
citrusbyte 0:01a2f8de46c8 449 if ((value & 0xFFFFu) >= 0xFFFEu) goto error_token;
citrusbyte 0:01a2f8de46c8 450 if (value >= 0xFDD0u && value <= 0xFDEFu) goto error_token;
citrusbyte 0:01a2f8de46c8 451 if (0xD800 > value || value > 0xDBFF) goto next_char;
citrusbyte 0:01a2f8de46c8 452
citrusbyte 0:01a2f8de46c8 453 // UTF-16 Surrogate
citrusbyte 0:01a2f8de46c8 454 utf32 = (value - 0xD800) << 10;
citrusbyte 0:01a2f8de46c8 455 if (c++ + 6 >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 456 if (*c++ != '\\') goto error_escape;
citrusbyte 0:01a2f8de46c8 457 if (*c++ != 'u') goto error_escape;
citrusbyte 0:01a2f8de46c8 458 CHECK_HEX(*c); value = jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 459 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 460 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c++);
citrusbyte 0:01a2f8de46c8 461 CHECK_HEX(*c); value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*c);
citrusbyte 0:01a2f8de46c8 462
citrusbyte 0:01a2f8de46c8 463 if (value < 0xDC00 || value > 0xDFFF) goto error_escape;
citrusbyte 0:01a2f8de46c8 464 utf32 += value - 0xDC00 + 0x10000;
citrusbyte 0:01a2f8de46c8 465 if ((utf32 & 0x0FFFFu) >= 0x0FFFEu) goto error_token;
citrusbyte 0:01a2f8de46c8 466 goto next_char;
citrusbyte 0:01a2f8de46c8 467 utf8:
citrusbyte 0:01a2f8de46c8 468 type |= jsonlite_string_utf8;
citrusbyte 0:01a2f8de46c8 469 int res = jsonlite_clz(((*c) ^ 0xFF) << 0x19);
citrusbyte 0:01a2f8de46c8 470 utf32 = (*c & (0xFF >> (res + 1)));
citrusbyte 0:01a2f8de46c8 471 value = 0xAAAAAAAA; // == 1010...
citrusbyte 0:01a2f8de46c8 472 if (c + res >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 473 switch (res) {
citrusbyte 0:01a2f8de46c8 474 case 3: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
citrusbyte 0:01a2f8de46c8 475 case 2: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
citrusbyte 0:01a2f8de46c8 476 case 1: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
citrusbyte 0:01a2f8de46c8 477 if (value != 0xAAAAAAAA) goto error_utf8;
citrusbyte 0:01a2f8de46c8 478 if ((utf32 & 0xFFFFu) >= 0xFFFEu) goto error_utf8;
citrusbyte 0:01a2f8de46c8 479 if (utf32 >= 0xFDD0u && utf32 <= 0xFDEFu) goto error_utf8;
citrusbyte 0:01a2f8de46c8 480 }
citrusbyte 0:01a2f8de46c8 481 goto next_char;
citrusbyte 0:01a2f8de46c8 482 string_parsed:
citrusbyte 0:01a2f8de46c8 483 token.string_type = type;
citrusbyte 0:01a2f8de46c8 484 token.end = c;
citrusbyte 0:01a2f8de46c8 485 parser->cursor = c + 1;
citrusbyte 0:01a2f8de46c8 486 if (*state == state_value) {
citrusbyte 0:01a2f8de46c8 487 CALL_VALUE_CALLBACK(parser->callbacks, string_found, &token);
citrusbyte 0:01a2f8de46c8 488 } else {
citrusbyte 0:01a2f8de46c8 489 CALL_VALUE_CALLBACK(parser->callbacks, key_found, &token);
citrusbyte 0:01a2f8de46c8 490 }
citrusbyte 0:01a2f8de46c8 491 state--;
citrusbyte 0:01a2f8de46c8 492 goto skip_char_and_spaces;
citrusbyte 0:01a2f8de46c8 493 }
citrusbyte 0:01a2f8de46c8 494
citrusbyte 0:01a2f8de46c8 495 // Primitive tokens states.
citrusbyte 0:01a2f8de46c8 496 true_token_parsing:
citrusbyte 0:01a2f8de46c8 497 if (c++ + 3 >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 498 if (*c++ != 'r') goto error_token;
citrusbyte 0:01a2f8de46c8 499 if (*c++ != 'u') goto error_token;
citrusbyte 0:01a2f8de46c8 500 if (*c++ != 'e') goto error_token;
citrusbyte 0:01a2f8de46c8 501 CALL_STATE_CALLBACK(parser->callbacks, true_found);
citrusbyte 0:01a2f8de46c8 502 state--;
citrusbyte 0:01a2f8de46c8 503 goto state_selection;
citrusbyte 0:01a2f8de46c8 504 false_token_paring:
citrusbyte 0:01a2f8de46c8 505 if (c++ + 4 >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 506 if (*c++ != 'a') goto error_token;
citrusbyte 0:01a2f8de46c8 507 if (*c++ != 'l') goto error_token;
citrusbyte 0:01a2f8de46c8 508 if (*c++ != 's') goto error_token;
citrusbyte 0:01a2f8de46c8 509 if (*c++ != 'e') goto error_token;
citrusbyte 0:01a2f8de46c8 510 CALL_STATE_CALLBACK(parser->callbacks, false_found);
citrusbyte 0:01a2f8de46c8 511 state--;
citrusbyte 0:01a2f8de46c8 512 goto state_selection;
citrusbyte 0:01a2f8de46c8 513 null_token_parsing:
citrusbyte 0:01a2f8de46c8 514 if (c++ + 3 >= l) goto end_of_stream;
citrusbyte 0:01a2f8de46c8 515 if (*c++ != 'u') goto error_token;
citrusbyte 0:01a2f8de46c8 516 if (*c++ != 'l') goto error_token;
citrusbyte 0:01a2f8de46c8 517 if (*c++ != 'l') goto error_token;
citrusbyte 0:01a2f8de46c8 518 CALL_STATE_CALLBACK(parser->callbacks, null_found);
citrusbyte 0:01a2f8de46c8 519 state--;
citrusbyte 0:01a2f8de46c8 520 goto state_selection;
citrusbyte 0:01a2f8de46c8 521
citrusbyte 0:01a2f8de46c8 522 // Error handling states.
citrusbyte 0:01a2f8de46c8 523 error_depth: parser->result = jsonlite_result_depth_limit; goto end;
citrusbyte 0:01a2f8de46c8 524 error_exp_ooa: parser->result = jsonlite_result_expected_object_or_array; goto end;
citrusbyte 0:01a2f8de46c8 525 error_exp_value: parser->result = jsonlite_result_expected_value; goto end;
citrusbyte 0:01a2f8de46c8 526 error_exp_koe: parser->result = jsonlite_result_expected_key_or_end; goto end;
citrusbyte 0:01a2f8de46c8 527 error_exp_key: parser->result = jsonlite_result_expected_key; goto end;
citrusbyte 0:01a2f8de46c8 528 error_exp_colon: parser->result = jsonlite_result_expected_colon; goto end;
citrusbyte 0:01a2f8de46c8 529 error_exp_coe: parser->result = jsonlite_result_expected_comma_or_end; goto end;
citrusbyte 0:01a2f8de46c8 530 error_escape: parser->result = jsonlite_result_invalid_escape; goto end;
citrusbyte 0:01a2f8de46c8 531 error_number: parser->result = jsonlite_result_invalid_number; goto end;
citrusbyte 0:01a2f8de46c8 532 error_token: parser->result = jsonlite_result_invalid_token; goto end;
citrusbyte 0:01a2f8de46c8 533 error_utf8: parser->result = jsonlite_result_invalid_utf8; goto end;
citrusbyte 0:01a2f8de46c8 534 suspend: parser->result = jsonlite_result_suspended; goto end;
citrusbyte 0:01a2f8de46c8 535 // End of stream states.
citrusbyte 0:01a2f8de46c8 536 end_of_stream_space:
citrusbyte 0:01a2f8de46c8 537 token_start = l;
citrusbyte 0:01a2f8de46c8 538 end_of_stream:
citrusbyte 0:01a2f8de46c8 539 parser->result = jsonlite_result_end_of_stream;
citrusbyte 0:01a2f8de46c8 540 goto end;
citrusbyte 0:01a2f8de46c8 541
citrusbyte 0:01a2f8de46c8 542 success:
citrusbyte 0:01a2f8de46c8 543 parser->result = jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 544 end:
citrusbyte 0:01a2f8de46c8 545 parser->token_start = token_start;
citrusbyte 0:01a2f8de46c8 546 parser->current = state;
citrusbyte 0:01a2f8de46c8 547 parser->cursor = c;
citrusbyte 0:01a2f8de46c8 548 parser->callbacks.parse_finished(&parser->callbacks.context);
citrusbyte 0:01a2f8de46c8 549 }
citrusbyte 0:01a2f8de46c8 550
citrusbyte 0:01a2f8de46c8 551 static void jsonlite_finish_parse(jsonlite_parser parser) {
citrusbyte 0:01a2f8de46c8 552 if (parser->result == jsonlite_result_suspended) {
citrusbyte 0:01a2f8de46c8 553 return;
citrusbyte 0:01a2f8de46c8 554 }
citrusbyte 0:01a2f8de46c8 555
citrusbyte 0:01a2f8de46c8 556 if (*parser->current == state_end) {
citrusbyte 0:01a2f8de46c8 557 return;
citrusbyte 0:01a2f8de46c8 558 }
citrusbyte 0:01a2f8de46c8 559
citrusbyte 0:01a2f8de46c8 560 parser->rest_size = parser->limit - parser->token_start;
citrusbyte 0:01a2f8de46c8 561 if (parser->rest_size > 0) {
citrusbyte 0:01a2f8de46c8 562 parser->rest = malloc(parser->rest_size);
citrusbyte 0:01a2f8de46c8 563 memcpy(parser->rest, parser->token_start, parser->rest_size); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 564 }
citrusbyte 0:01a2f8de46c8 565 }
citrusbyte 0:01a2f8de46c8 566 //
citrusbyte 0:01a2f8de46c8 567 // Copyright 2012-2013, Andrii Mamchur
citrusbyte 0:01a2f8de46c8 568 //
citrusbyte 0:01a2f8de46c8 569 // Licensed under the Apache License, Version 2.0 (the "License");
citrusbyte 0:01a2f8de46c8 570 // you may not use this file except in compliance with the License.
citrusbyte 0:01a2f8de46c8 571 // You may obtain a copy of the License at
citrusbyte 0:01a2f8de46c8 572 //
citrusbyte 0:01a2f8de46c8 573 // http://www.apache.org/licenses/LICENSE-2.0
citrusbyte 0:01a2f8de46c8 574 //
citrusbyte 0:01a2f8de46c8 575 // Unless required by applicable law or agreed to in writing, software
citrusbyte 0:01a2f8de46c8 576 // distributed under the License is distributed on an "AS IS" BASIS,
citrusbyte 0:01a2f8de46c8 577 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
citrusbyte 0:01a2f8de46c8 578 // See the License for the specific language governing permissions and
citrusbyte 0:01a2f8de46c8 579 // limitations under the License
citrusbyte 0:01a2f8de46c8 580
citrusbyte 0:01a2f8de46c8 581 #ifndef JSONLITE_AMALGAMATED
citrusbyte 0:01a2f8de46c8 582 #include "../include/jsonlite_builder.h"
citrusbyte 0:01a2f8de46c8 583 #endif
citrusbyte 0:01a2f8de46c8 584
citrusbyte 0:01a2f8de46c8 585 #include <stdlib.h>
citrusbyte 0:01a2f8de46c8 586 #include <string.h>
citrusbyte 0:01a2f8de46c8 587 #include <stddef.h>
citrusbyte 0:01a2f8de46c8 588 #include <stdint.h>
citrusbyte 0:01a2f8de46c8 589
citrusbyte 0:01a2f8de46c8 590 #define jsonlite_builder_check_depth() \
citrusbyte 0:01a2f8de46c8 591 do { \
citrusbyte 0:01a2f8de46c8 592 if (builder->state - builder->stack >= builder->stack_depth - 1) { \
citrusbyte 0:01a2f8de46c8 593 return jsonlite_result_depth_limit; \
citrusbyte 0:01a2f8de46c8 594 } \
citrusbyte 0:01a2f8de46c8 595 } while (0)
citrusbyte 0:01a2f8de46c8 596
citrusbyte 0:01a2f8de46c8 597 typedef enum {
citrusbyte 0:01a2f8de46c8 598 jsonlite_accept_object_begin = 0x0001,
citrusbyte 0:01a2f8de46c8 599 jsonlite_accept_object_end = 0x0002,
citrusbyte 0:01a2f8de46c8 600 jsonlite_accept_array_begin = 0x0004,
citrusbyte 0:01a2f8de46c8 601 jsonlite_accept_array_end = 0x0008,
citrusbyte 0:01a2f8de46c8 602
citrusbyte 0:01a2f8de46c8 603 jsonlite_accept_key = 0x0010,
citrusbyte 0:01a2f8de46c8 604 jsonlite_accept_string = 0x0020,
citrusbyte 0:01a2f8de46c8 605 jsonlite_accept_number = 0x0040,
citrusbyte 0:01a2f8de46c8 606 jsonlite_accept_boolean = 0x0080,
citrusbyte 0:01a2f8de46c8 607 jsonlite_accept_null = 0x0100,
citrusbyte 0:01a2f8de46c8 608 jsonlite_accept_values_only = 0x0200,
citrusbyte 0:01a2f8de46c8 609 jsonlite_accept_next = 0x0400,
citrusbyte 0:01a2f8de46c8 610
citrusbyte 0:01a2f8de46c8 611 jsonlite_accept_value = 0
citrusbyte 0:01a2f8de46c8 612 | jsonlite_accept_object_begin
citrusbyte 0:01a2f8de46c8 613 | jsonlite_accept_array_begin
citrusbyte 0:01a2f8de46c8 614 | jsonlite_accept_string
citrusbyte 0:01a2f8de46c8 615 | jsonlite_accept_number
citrusbyte 0:01a2f8de46c8 616 | jsonlite_accept_boolean
citrusbyte 0:01a2f8de46c8 617 | jsonlite_accept_null,
citrusbyte 0:01a2f8de46c8 618
citrusbyte 0:01a2f8de46c8 619 jsonlite_accept_continue_object = 0
citrusbyte 0:01a2f8de46c8 620 | jsonlite_accept_next
citrusbyte 0:01a2f8de46c8 621 | jsonlite_accept_key
citrusbyte 0:01a2f8de46c8 622 | jsonlite_accept_object_end,
citrusbyte 0:01a2f8de46c8 623 jsonlite_accept_continue_array = 0
citrusbyte 0:01a2f8de46c8 624 | jsonlite_accept_next
citrusbyte 0:01a2f8de46c8 625 | jsonlite_accept_values_only
citrusbyte 0:01a2f8de46c8 626 | jsonlite_accept_value
citrusbyte 0:01a2f8de46c8 627 | jsonlite_accept_array_end
citrusbyte 0:01a2f8de46c8 628
citrusbyte 0:01a2f8de46c8 629 } jsonlite_accept;
citrusbyte 0:01a2f8de46c8 630
citrusbyte 0:01a2f8de46c8 631 typedef struct jsonlite_write_state {
citrusbyte 0:01a2f8de46c8 632 int accept;
citrusbyte 0:01a2f8de46c8 633 } jsonlite_write_state;
citrusbyte 0:01a2f8de46c8 634
citrusbyte 0:01a2f8de46c8 635 typedef struct jsonlite_builder_buffer {
citrusbyte 0:01a2f8de46c8 636 char data[2048];
citrusbyte 0:01a2f8de46c8 637 char *cursor;
citrusbyte 0:01a2f8de46c8 638 char *limit;
citrusbyte 0:01a2f8de46c8 639 struct jsonlite_builder_buffer *next;
citrusbyte 0:01a2f8de46c8 640 } jsonlite_builder_buffer;
citrusbyte 0:01a2f8de46c8 641
citrusbyte 0:01a2f8de46c8 642 typedef struct jsonlite_builder_struct {
citrusbyte 0:01a2f8de46c8 643 jsonlite_builder_buffer *first;
citrusbyte 0:01a2f8de46c8 644 jsonlite_builder_buffer *buffer;
citrusbyte 0:01a2f8de46c8 645
citrusbyte 0:01a2f8de46c8 646 jsonlite_write_state *stack;
citrusbyte 0:01a2f8de46c8 647 jsonlite_write_state *state;
citrusbyte 0:01a2f8de46c8 648 ptrdiff_t stack_depth;
citrusbyte 0:01a2f8de46c8 649
citrusbyte 0:01a2f8de46c8 650 char *doubleFormat;
citrusbyte 0:01a2f8de46c8 651
citrusbyte 0:01a2f8de46c8 652 size_t indentation;
citrusbyte 0:01a2f8de46c8 653 } jsonlite_builder_struct;
citrusbyte 0:01a2f8de46c8 654
citrusbyte 0:01a2f8de46c8 655 static int jsonlite_builder_accept(jsonlite_builder builder, jsonlite_accept a);
citrusbyte 0:01a2f8de46c8 656 static void jsonlite_builder_pop_state(jsonlite_builder builder);
citrusbyte 0:01a2f8de46c8 657 static void jsonlite_builder_push_buffer(jsonlite_builder builder);
citrusbyte 0:01a2f8de46c8 658 static void jsonlite_builder_prepare_value_writing(jsonlite_builder builder);
citrusbyte 0:01a2f8de46c8 659 static void jsonlite_builder_raw_char(jsonlite_builder builder, char data);
citrusbyte 0:01a2f8de46c8 660 static void jsonlite_builder_write_uft8(jsonlite_builder builder, const char *data, size_t length);
citrusbyte 0:01a2f8de46c8 661 static void jsonlite_builder_raw(jsonlite_builder builder, const void *data, size_t length);
citrusbyte 0:01a2f8de46c8 662 static void jsonlite_builder_repeat(jsonlite_builder builder, const char ch, size_t count);
citrusbyte 0:01a2f8de46c8 663
citrusbyte 0:01a2f8de46c8 664 jsonlite_builder jsonlite_builder_init(size_t depth) {
citrusbyte 0:01a2f8de46c8 665 jsonlite_builder builder;
citrusbyte 0:01a2f8de46c8 666
citrusbyte 0:01a2f8de46c8 667 depth = depth < 2 ? 2 : depth;
citrusbyte 0:01a2f8de46c8 668
citrusbyte 0:01a2f8de46c8 669 builder = (jsonlite_builder)calloc(1, sizeof(jsonlite_builder_struct) + depth * sizeof(jsonlite_write_state));
citrusbyte 0:01a2f8de46c8 670 builder->first = (jsonlite_builder_buffer *)malloc(sizeof(jsonlite_builder_buffer));
citrusbyte 0:01a2f8de46c8 671 builder->buffer = builder->first;
citrusbyte 0:01a2f8de46c8 672 builder->buffer->cursor = builder->buffer->data;
citrusbyte 0:01a2f8de46c8 673 builder->buffer->limit = builder->buffer->data + sizeof(builder->buffer->data);
citrusbyte 0:01a2f8de46c8 674 builder->buffer->next = NULL;
citrusbyte 0:01a2f8de46c8 675
citrusbyte 0:01a2f8de46c8 676 builder->stack = (jsonlite_write_state *)((uint8_t *)builder + sizeof(jsonlite_builder_struct));
citrusbyte 0:01a2f8de46c8 677 builder->stack_depth = depth;
citrusbyte 0:01a2f8de46c8 678 builder->state = builder->stack;
citrusbyte 0:01a2f8de46c8 679 builder->state->accept = jsonlite_accept_object_begin | jsonlite_accept_array_begin;
citrusbyte 0:01a2f8de46c8 680
citrusbyte 0:01a2f8de46c8 681 builder->indentation = 0;
citrusbyte 0:01a2f8de46c8 682 jsonlite_builder_set_double_format(builder, "%.16g");
citrusbyte 0:01a2f8de46c8 683 return builder;
citrusbyte 0:01a2f8de46c8 684 }
citrusbyte 0:01a2f8de46c8 685
citrusbyte 0:01a2f8de46c8 686 jsonlite_result jsonlite_builder_release(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 687 jsonlite_builder_buffer *b = NULL;
citrusbyte 0:01a2f8de46c8 688 void *prev;
citrusbyte 0:01a2f8de46c8 689
citrusbyte 0:01a2f8de46c8 690 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 691 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 692 }
citrusbyte 0:01a2f8de46c8 693
citrusbyte 0:01a2f8de46c8 694 for (b = builder->first; b != NULL;) {
citrusbyte 0:01a2f8de46c8 695 prev = b;
citrusbyte 0:01a2f8de46c8 696 b = b->next;
citrusbyte 0:01a2f8de46c8 697 free(prev);
citrusbyte 0:01a2f8de46c8 698 }
citrusbyte 0:01a2f8de46c8 699
citrusbyte 0:01a2f8de46c8 700 free(builder->doubleFormat);
citrusbyte 0:01a2f8de46c8 701 free(builder);
citrusbyte 0:01a2f8de46c8 702 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 703 }
citrusbyte 0:01a2f8de46c8 704
citrusbyte 0:01a2f8de46c8 705 jsonlite_result jsonlite_builder_set_indentation(jsonlite_builder builder, size_t indentation) {
citrusbyte 0:01a2f8de46c8 706 if (builder != NULL) {
citrusbyte 0:01a2f8de46c8 707 builder->indentation = indentation;
citrusbyte 0:01a2f8de46c8 708 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 709 }
citrusbyte 0:01a2f8de46c8 710 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 711 }
citrusbyte 0:01a2f8de46c8 712
citrusbyte 0:01a2f8de46c8 713 jsonlite_result jsonlite_builder_set_double_format(jsonlite_builder builder, const char *format) {
citrusbyte 0:01a2f8de46c8 714 if (builder != NULL && format != NULL) {
citrusbyte 0:01a2f8de46c8 715 builder->doubleFormat = strdup(format);
citrusbyte 0:01a2f8de46c8 716 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 717 }
citrusbyte 0:01a2f8de46c8 718 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 719 }
citrusbyte 0:01a2f8de46c8 720
citrusbyte 0:01a2f8de46c8 721 static int jsonlite_builder_accept(jsonlite_builder builder, jsonlite_accept a) {
citrusbyte 0:01a2f8de46c8 722 return (builder->state->accept & a) == a;
citrusbyte 0:01a2f8de46c8 723 }
citrusbyte 0:01a2f8de46c8 724
citrusbyte 0:01a2f8de46c8 725 static void jsonlite_builder_push_state(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 726 builder->state++;
citrusbyte 0:01a2f8de46c8 727 }
citrusbyte 0:01a2f8de46c8 728
citrusbyte 0:01a2f8de46c8 729 static void jsonlite_builder_pop_state(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 730 jsonlite_write_state *ws = --builder->state;
citrusbyte 0:01a2f8de46c8 731 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 732 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 733 } else {
citrusbyte 0:01a2f8de46c8 734 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 735 }
citrusbyte 0:01a2f8de46c8 736 }
citrusbyte 0:01a2f8de46c8 737
citrusbyte 0:01a2f8de46c8 738 static void jsonlite_builder_push_buffer(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 739 jsonlite_builder_buffer *buffer = builder->buffer;
citrusbyte 0:01a2f8de46c8 740 buffer->next = malloc(sizeof(jsonlite_builder_buffer));
citrusbyte 0:01a2f8de46c8 741 buffer = builder->buffer = buffer->next;
citrusbyte 0:01a2f8de46c8 742
citrusbyte 0:01a2f8de46c8 743 buffer->cursor = buffer->data;
citrusbyte 0:01a2f8de46c8 744 buffer->limit = buffer->data + sizeof(buffer->data);
citrusbyte 0:01a2f8de46c8 745 buffer->next = NULL;
citrusbyte 0:01a2f8de46c8 746 }
citrusbyte 0:01a2f8de46c8 747
citrusbyte 0:01a2f8de46c8 748 static void jsonlite_builder_prepare_value_writing(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 749 jsonlite_write_state *ws = builder->state;
citrusbyte 0:01a2f8de46c8 750 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 751 if (jsonlite_builder_accept(builder, jsonlite_accept_next) ) {
citrusbyte 0:01a2f8de46c8 752 jsonlite_builder_raw_char(builder, ',');
citrusbyte 0:01a2f8de46c8 753 }
citrusbyte 0:01a2f8de46c8 754 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 755 jsonlite_builder_raw_char(builder, '\r');
citrusbyte 0:01a2f8de46c8 756 jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
citrusbyte 0:01a2f8de46c8 757 }
citrusbyte 0:01a2f8de46c8 758 } else {
citrusbyte 0:01a2f8de46c8 759 ws->accept &= ~jsonlite_accept_value;
citrusbyte 0:01a2f8de46c8 760 ws->accept |= jsonlite_accept_key;
citrusbyte 0:01a2f8de46c8 761 }
citrusbyte 0:01a2f8de46c8 762 ws->accept |= jsonlite_accept_next;
citrusbyte 0:01a2f8de46c8 763 }
citrusbyte 0:01a2f8de46c8 764
citrusbyte 0:01a2f8de46c8 765 jsonlite_result jsonlite_builder_object_begin(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 766 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 767 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 768 }
citrusbyte 0:01a2f8de46c8 769
citrusbyte 0:01a2f8de46c8 770 jsonlite_builder_check_depth();
citrusbyte 0:01a2f8de46c8 771
citrusbyte 0:01a2f8de46c8 772 if (jsonlite_builder_accept(builder, jsonlite_accept_object_begin)) {
citrusbyte 0:01a2f8de46c8 773 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 774 jsonlite_builder_push_state(builder);
citrusbyte 0:01a2f8de46c8 775 builder->state->accept = jsonlite_accept_object_end | jsonlite_accept_key;
citrusbyte 0:01a2f8de46c8 776 jsonlite_builder_raw_char(builder, '{');
citrusbyte 0:01a2f8de46c8 777 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 778 }
citrusbyte 0:01a2f8de46c8 779
citrusbyte 0:01a2f8de46c8 780 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 781 }
citrusbyte 0:01a2f8de46c8 782
citrusbyte 0:01a2f8de46c8 783 jsonlite_result jsonlite_builder_object_end(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 784 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 785 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 786 }
citrusbyte 0:01a2f8de46c8 787
citrusbyte 0:01a2f8de46c8 788 if (jsonlite_builder_accept(builder, jsonlite_accept_object_end)) {
citrusbyte 0:01a2f8de46c8 789 jsonlite_builder_pop_state(builder);
citrusbyte 0:01a2f8de46c8 790 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 791 jsonlite_builder_raw_char(builder, '\r');
citrusbyte 0:01a2f8de46c8 792 jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
citrusbyte 0:01a2f8de46c8 793 }
citrusbyte 0:01a2f8de46c8 794 jsonlite_builder_raw_char(builder, '}');
citrusbyte 0:01a2f8de46c8 795 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 796 }
citrusbyte 0:01a2f8de46c8 797
citrusbyte 0:01a2f8de46c8 798 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 799 }
citrusbyte 0:01a2f8de46c8 800
citrusbyte 0:01a2f8de46c8 801 jsonlite_result jsonlite_builder_array_begin(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 802 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 803 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 804 }
citrusbyte 0:01a2f8de46c8 805
citrusbyte 0:01a2f8de46c8 806 jsonlite_builder_check_depth();
citrusbyte 0:01a2f8de46c8 807
citrusbyte 0:01a2f8de46c8 808 if (jsonlite_builder_accept(builder, jsonlite_accept_array_begin)) {
citrusbyte 0:01a2f8de46c8 809 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 810 jsonlite_builder_push_state(builder);
citrusbyte 0:01a2f8de46c8 811 builder->state->accept = jsonlite_accept_array_end
citrusbyte 0:01a2f8de46c8 812 | jsonlite_accept_value
citrusbyte 0:01a2f8de46c8 813 | jsonlite_accept_values_only;
citrusbyte 0:01a2f8de46c8 814 jsonlite_builder_raw_char(builder, '[');
citrusbyte 0:01a2f8de46c8 815 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 816 }
citrusbyte 0:01a2f8de46c8 817
citrusbyte 0:01a2f8de46c8 818 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 819 }
citrusbyte 0:01a2f8de46c8 820
citrusbyte 0:01a2f8de46c8 821 jsonlite_result jsonlite_builder_array_end(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 822 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 823 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 824 }
citrusbyte 0:01a2f8de46c8 825
citrusbyte 0:01a2f8de46c8 826 if (jsonlite_builder_accept(builder, jsonlite_accept_array_end)) {
citrusbyte 0:01a2f8de46c8 827 jsonlite_builder_pop_state(builder);
citrusbyte 0:01a2f8de46c8 828 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 829 jsonlite_builder_raw_char(builder, '\r');
citrusbyte 0:01a2f8de46c8 830 jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
citrusbyte 0:01a2f8de46c8 831 }
citrusbyte 0:01a2f8de46c8 832 jsonlite_builder_raw_char(builder, ']');
citrusbyte 0:01a2f8de46c8 833 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 834 }
citrusbyte 0:01a2f8de46c8 835
citrusbyte 0:01a2f8de46c8 836 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 837 }
citrusbyte 0:01a2f8de46c8 838
citrusbyte 0:01a2f8de46c8 839 static void jsonlite_builder_write_uft8(jsonlite_builder builder, const char *data, size_t length) {
citrusbyte 0:01a2f8de46c8 840 size_t i;
citrusbyte 0:01a2f8de46c8 841 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 842 for (i = 0; i < length; i++) {
citrusbyte 0:01a2f8de46c8 843 switch (data[i]) {
citrusbyte 0:01a2f8de46c8 844 case '"':
citrusbyte 0:01a2f8de46c8 845 jsonlite_builder_raw(builder, "\\\"", 2);
citrusbyte 0:01a2f8de46c8 846 break;
citrusbyte 0:01a2f8de46c8 847 case '\\':
citrusbyte 0:01a2f8de46c8 848 jsonlite_builder_raw(builder, "\\\\", 2);
citrusbyte 0:01a2f8de46c8 849 break;
citrusbyte 0:01a2f8de46c8 850 case '\b':
citrusbyte 0:01a2f8de46c8 851 jsonlite_builder_raw(builder, "\\b", 2);
citrusbyte 0:01a2f8de46c8 852 break;
citrusbyte 0:01a2f8de46c8 853 case '\f':
citrusbyte 0:01a2f8de46c8 854 jsonlite_builder_raw(builder, "\\f", 2);
citrusbyte 0:01a2f8de46c8 855 break;
citrusbyte 0:01a2f8de46c8 856 case '\n':
citrusbyte 0:01a2f8de46c8 857 jsonlite_builder_raw(builder, "\\n", 2);
citrusbyte 0:01a2f8de46c8 858 break;
citrusbyte 0:01a2f8de46c8 859 case '\r':
citrusbyte 0:01a2f8de46c8 860 jsonlite_builder_raw(builder, "\\r", 2);
citrusbyte 0:01a2f8de46c8 861 break;
citrusbyte 0:01a2f8de46c8 862 case '\t':
citrusbyte 0:01a2f8de46c8 863 jsonlite_builder_raw(builder, "\\t", 2);
citrusbyte 0:01a2f8de46c8 864 break;
citrusbyte 0:01a2f8de46c8 865 default:
citrusbyte 0:01a2f8de46c8 866 jsonlite_builder_raw_char(builder, data[i]);
citrusbyte 0:01a2f8de46c8 867 break;
citrusbyte 0:01a2f8de46c8 868 }
citrusbyte 0:01a2f8de46c8 869 }
citrusbyte 0:01a2f8de46c8 870 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 871 }
citrusbyte 0:01a2f8de46c8 872
citrusbyte 0:01a2f8de46c8 873 jsonlite_result jsonlite_builder_key(jsonlite_builder builder, const char *data, size_t length) {
citrusbyte 0:01a2f8de46c8 874 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 875
citrusbyte 0:01a2f8de46c8 876 if (builder == NULL || data == NULL) {
citrusbyte 0:01a2f8de46c8 877 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 878 }
citrusbyte 0:01a2f8de46c8 879
citrusbyte 0:01a2f8de46c8 880 ws = builder->state;
citrusbyte 0:01a2f8de46c8 881
citrusbyte 0:01a2f8de46c8 882 if (jsonlite_builder_accept(builder, jsonlite_accept_key) ) {
citrusbyte 0:01a2f8de46c8 883 if (jsonlite_builder_accept(builder, jsonlite_accept_next) ) {
citrusbyte 0:01a2f8de46c8 884 jsonlite_builder_raw_char(builder, ',');
citrusbyte 0:01a2f8de46c8 885 }
citrusbyte 0:01a2f8de46c8 886 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 887 jsonlite_builder_raw_char(builder, '\r');
citrusbyte 0:01a2f8de46c8 888 jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
citrusbyte 0:01a2f8de46c8 889 }
citrusbyte 0:01a2f8de46c8 890 jsonlite_builder_write_uft8(builder, data, length);
citrusbyte 0:01a2f8de46c8 891 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 892 jsonlite_builder_raw(builder, ": ", 2);
citrusbyte 0:01a2f8de46c8 893 } else {
citrusbyte 0:01a2f8de46c8 894 jsonlite_builder_raw_char(builder, ':');
citrusbyte 0:01a2f8de46c8 895 }
citrusbyte 0:01a2f8de46c8 896 ws->accept = jsonlite_accept_value;
citrusbyte 0:01a2f8de46c8 897 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 898 }
citrusbyte 0:01a2f8de46c8 899
citrusbyte 0:01a2f8de46c8 900 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 901 }
citrusbyte 0:01a2f8de46c8 902
citrusbyte 0:01a2f8de46c8 903 jsonlite_result jsonlite_builder_string(jsonlite_builder builder, const char *data, size_t length) {
citrusbyte 0:01a2f8de46c8 904 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 905
citrusbyte 0:01a2f8de46c8 906 if (builder == NULL || data == NULL) {
citrusbyte 0:01a2f8de46c8 907 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 908 }
citrusbyte 0:01a2f8de46c8 909
citrusbyte 0:01a2f8de46c8 910 ws = builder->state;
citrusbyte 0:01a2f8de46c8 911
citrusbyte 0:01a2f8de46c8 912 if (jsonlite_builder_accept(builder, jsonlite_accept_value) ) {
citrusbyte 0:01a2f8de46c8 913 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 914 jsonlite_builder_write_uft8(builder, data, length);
citrusbyte 0:01a2f8de46c8 915 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 916 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 917 } else {
citrusbyte 0:01a2f8de46c8 918 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 919 }
citrusbyte 0:01a2f8de46c8 920 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 921 }
citrusbyte 0:01a2f8de46c8 922
citrusbyte 0:01a2f8de46c8 923 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 924 }
citrusbyte 0:01a2f8de46c8 925
citrusbyte 0:01a2f8de46c8 926 jsonlite_result jsonlite_builder_int(jsonlite_builder builder, long long value) {
citrusbyte 0:01a2f8de46c8 927 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 928 char buff[128];
citrusbyte 0:01a2f8de46c8 929 int size = 0;
citrusbyte 0:01a2f8de46c8 930
citrusbyte 0:01a2f8de46c8 931 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 932 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 933 }
citrusbyte 0:01a2f8de46c8 934
citrusbyte 0:01a2f8de46c8 935 ws = builder->state;
citrusbyte 0:01a2f8de46c8 936
citrusbyte 0:01a2f8de46c8 937 if (jsonlite_builder_accept(builder, jsonlite_accept_value) ) {
citrusbyte 0:01a2f8de46c8 938 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 939 size = sprintf(buff, "%lld", value);
citrusbyte 0:01a2f8de46c8 940 jsonlite_builder_raw(builder, buff, size);
citrusbyte 0:01a2f8de46c8 941 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 942 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 943 } else {
citrusbyte 0:01a2f8de46c8 944 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 945 }
citrusbyte 0:01a2f8de46c8 946 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 947 }
citrusbyte 0:01a2f8de46c8 948
citrusbyte 0:01a2f8de46c8 949 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 950 }
citrusbyte 0:01a2f8de46c8 951
citrusbyte 0:01a2f8de46c8 952 jsonlite_result jsonlite_builder_double(jsonlite_builder builder, double value) {
citrusbyte 0:01a2f8de46c8 953 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 954 char buff[128];
citrusbyte 0:01a2f8de46c8 955 int size = 0;
citrusbyte 0:01a2f8de46c8 956
citrusbyte 0:01a2f8de46c8 957 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 958 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 959 }
citrusbyte 0:01a2f8de46c8 960
citrusbyte 0:01a2f8de46c8 961 ws = builder->state;
citrusbyte 0:01a2f8de46c8 962
citrusbyte 0:01a2f8de46c8 963 if (jsonlite_builder_accept(builder, jsonlite_accept_value) ) {
citrusbyte 0:01a2f8de46c8 964 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 965 size = sprintf(buff, builder->doubleFormat, value);
citrusbyte 0:01a2f8de46c8 966 jsonlite_builder_raw(builder, buff, size);
citrusbyte 0:01a2f8de46c8 967 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 968 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 969 } else {
citrusbyte 0:01a2f8de46c8 970 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 971 }
citrusbyte 0:01a2f8de46c8 972 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 973 }
citrusbyte 0:01a2f8de46c8 974
citrusbyte 0:01a2f8de46c8 975 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 976 }
citrusbyte 0:01a2f8de46c8 977
citrusbyte 0:01a2f8de46c8 978 jsonlite_result jsonlite_builder_true(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 979 static const char value[] = "true";
citrusbyte 0:01a2f8de46c8 980 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 981
citrusbyte 0:01a2f8de46c8 982 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 983 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 984 }
citrusbyte 0:01a2f8de46c8 985
citrusbyte 0:01a2f8de46c8 986 ws = builder->state;
citrusbyte 0:01a2f8de46c8 987 if (!(jsonlite_builder_accept(builder, jsonlite_accept_value) )) {
citrusbyte 0:01a2f8de46c8 988
citrusbyte 0:01a2f8de46c8 989 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 990 }
citrusbyte 0:01a2f8de46c8 991
citrusbyte 0:01a2f8de46c8 992 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 993 jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
citrusbyte 0:01a2f8de46c8 994 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 995 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 996 } else {
citrusbyte 0:01a2f8de46c8 997 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 998 }
citrusbyte 0:01a2f8de46c8 999 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1000 }
citrusbyte 0:01a2f8de46c8 1001
citrusbyte 0:01a2f8de46c8 1002 jsonlite_result jsonlite_builder_false(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 1003 static const char value[] = "false";
citrusbyte 0:01a2f8de46c8 1004 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 1005
citrusbyte 0:01a2f8de46c8 1006 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 1007 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1008 }
citrusbyte 0:01a2f8de46c8 1009
citrusbyte 0:01a2f8de46c8 1010 ws = builder->state;
citrusbyte 0:01a2f8de46c8 1011 if (!(jsonlite_builder_accept(builder, jsonlite_accept_value) )) {
citrusbyte 0:01a2f8de46c8 1012
citrusbyte 0:01a2f8de46c8 1013 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1014 }
citrusbyte 0:01a2f8de46c8 1015
citrusbyte 0:01a2f8de46c8 1016 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 1017 jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
citrusbyte 0:01a2f8de46c8 1018 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 1019 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 1020 } else {
citrusbyte 0:01a2f8de46c8 1021 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 1022 }
citrusbyte 0:01a2f8de46c8 1023 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1024 }
citrusbyte 0:01a2f8de46c8 1025
citrusbyte 0:01a2f8de46c8 1026 jsonlite_result jsonlite_builder_null(jsonlite_builder builder) {
citrusbyte 0:01a2f8de46c8 1027 static const char value[] = "null";
citrusbyte 0:01a2f8de46c8 1028 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 1029
citrusbyte 0:01a2f8de46c8 1030 if (builder == NULL) {
citrusbyte 0:01a2f8de46c8 1031 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1032 }
citrusbyte 0:01a2f8de46c8 1033
citrusbyte 0:01a2f8de46c8 1034 ws = builder->state;
citrusbyte 0:01a2f8de46c8 1035 if (!(jsonlite_builder_accept(builder, jsonlite_accept_value) )) {
citrusbyte 0:01a2f8de46c8 1036
citrusbyte 0:01a2f8de46c8 1037 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1038 }
citrusbyte 0:01a2f8de46c8 1039
citrusbyte 0:01a2f8de46c8 1040 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 1041 jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
citrusbyte 0:01a2f8de46c8 1042 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 1043 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 1044 } else {
citrusbyte 0:01a2f8de46c8 1045 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 1046 }
citrusbyte 0:01a2f8de46c8 1047 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1048 }
citrusbyte 0:01a2f8de46c8 1049
citrusbyte 0:01a2f8de46c8 1050 static void jsonlite_builder_raw(jsonlite_builder builder, const void *data, size_t length) {
citrusbyte 0:01a2f8de46c8 1051 jsonlite_builder_buffer *buffer = builder->buffer;
citrusbyte 0:01a2f8de46c8 1052 size_t write_limit = buffer->limit - buffer->cursor;
citrusbyte 0:01a2f8de46c8 1053 if (write_limit >= length) {
citrusbyte 0:01a2f8de46c8 1054 memcpy(buffer->cursor, data, length); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1055 buffer->cursor += length;
citrusbyte 0:01a2f8de46c8 1056 } else {
citrusbyte 0:01a2f8de46c8 1057 memcpy(buffer->cursor, data, write_limit); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1058 buffer->cursor += write_limit;
citrusbyte 0:01a2f8de46c8 1059
citrusbyte 0:01a2f8de46c8 1060 jsonlite_builder_push_buffer(builder);
citrusbyte 0:01a2f8de46c8 1061 jsonlite_builder_raw(builder, (char *)data + write_limit, length - write_limit);
citrusbyte 0:01a2f8de46c8 1062 }
citrusbyte 0:01a2f8de46c8 1063 }
citrusbyte 0:01a2f8de46c8 1064
citrusbyte 0:01a2f8de46c8 1065 static void jsonlite_builder_repeat(jsonlite_builder builder, const char ch, size_t count) {
citrusbyte 0:01a2f8de46c8 1066 jsonlite_builder_buffer *buffer = builder->buffer;
citrusbyte 0:01a2f8de46c8 1067 size_t write_limit = buffer->limit - buffer->cursor;
citrusbyte 0:01a2f8de46c8 1068 if (write_limit >= count) {
citrusbyte 0:01a2f8de46c8 1069 memset(buffer->cursor, ch, count); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1070 buffer->cursor += count;
citrusbyte 0:01a2f8de46c8 1071 } else {
citrusbyte 0:01a2f8de46c8 1072 memset(buffer->cursor, ch, write_limit); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1073 buffer->cursor += write_limit;
citrusbyte 0:01a2f8de46c8 1074
citrusbyte 0:01a2f8de46c8 1075 jsonlite_builder_push_buffer(builder);
citrusbyte 0:01a2f8de46c8 1076 jsonlite_builder_repeat(builder, ch, count - write_limit);
citrusbyte 0:01a2f8de46c8 1077 }
citrusbyte 0:01a2f8de46c8 1078 }
citrusbyte 0:01a2f8de46c8 1079
citrusbyte 0:01a2f8de46c8 1080 static void jsonlite_builder_raw_char(jsonlite_builder builder, char data) {
citrusbyte 0:01a2f8de46c8 1081 jsonlite_builder_buffer *buffer = builder->buffer;
citrusbyte 0:01a2f8de46c8 1082 if (buffer->cursor >= buffer->limit) {
citrusbyte 0:01a2f8de46c8 1083 jsonlite_builder_push_buffer(builder);
citrusbyte 0:01a2f8de46c8 1084 }
citrusbyte 0:01a2f8de46c8 1085 *builder->buffer->cursor++ = data;
citrusbyte 0:01a2f8de46c8 1086 }
citrusbyte 0:01a2f8de46c8 1087
citrusbyte 0:01a2f8de46c8 1088 jsonlite_result jsonlite_builder_raw_key(jsonlite_builder builder, const void *data, size_t length) {
citrusbyte 0:01a2f8de46c8 1089 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 1090
citrusbyte 0:01a2f8de46c8 1091 if (builder == NULL || data == NULL || length == 0) {
citrusbyte 0:01a2f8de46c8 1092 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1093 }
citrusbyte 0:01a2f8de46c8 1094
citrusbyte 0:01a2f8de46c8 1095 ws = builder->state;
citrusbyte 0:01a2f8de46c8 1096 if (jsonlite_builder_accept(builder, jsonlite_accept_key) ) {
citrusbyte 0:01a2f8de46c8 1097 if (jsonlite_builder_accept(builder, jsonlite_accept_next) ) {
citrusbyte 0:01a2f8de46c8 1098 jsonlite_builder_raw(builder, ",", 1);
citrusbyte 0:01a2f8de46c8 1099 }
citrusbyte 0:01a2f8de46c8 1100
citrusbyte 0:01a2f8de46c8 1101 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 1102 jsonlite_builder_raw_char(builder, '\r');
citrusbyte 0:01a2f8de46c8 1103 jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
citrusbyte 0:01a2f8de46c8 1104 }
citrusbyte 0:01a2f8de46c8 1105 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 1106 jsonlite_builder_raw(builder, data, length);
citrusbyte 0:01a2f8de46c8 1107 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 1108 if (builder->indentation != 0) {
citrusbyte 0:01a2f8de46c8 1109 jsonlite_builder_raw(builder, ": ", 2);
citrusbyte 0:01a2f8de46c8 1110 } else {
citrusbyte 0:01a2f8de46c8 1111 jsonlite_builder_raw_char(builder, ':');
citrusbyte 0:01a2f8de46c8 1112 }
citrusbyte 0:01a2f8de46c8 1113 ws->accept = jsonlite_accept_value;
citrusbyte 0:01a2f8de46c8 1114 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1115 }
citrusbyte 0:01a2f8de46c8 1116
citrusbyte 0:01a2f8de46c8 1117 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1118 }
citrusbyte 0:01a2f8de46c8 1119
citrusbyte 0:01a2f8de46c8 1120 jsonlite_result jsonlite_builder_raw_string(jsonlite_builder builder, const void *data, size_t length) {
citrusbyte 0:01a2f8de46c8 1121 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 1122
citrusbyte 0:01a2f8de46c8 1123 if (builder == NULL || data == NULL || length == 0) {
citrusbyte 0:01a2f8de46c8 1124 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1125 }
citrusbyte 0:01a2f8de46c8 1126
citrusbyte 0:01a2f8de46c8 1127 ws = builder->state;
citrusbyte 0:01a2f8de46c8 1128
citrusbyte 0:01a2f8de46c8 1129 if (jsonlite_builder_accept(builder, jsonlite_accept_value) ) {
citrusbyte 0:01a2f8de46c8 1130 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 1131 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 1132 jsonlite_builder_raw(builder, data, length);
citrusbyte 0:01a2f8de46c8 1133 jsonlite_builder_raw_char(builder, '\"');
citrusbyte 0:01a2f8de46c8 1134 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 1135 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 1136 } else {
citrusbyte 0:01a2f8de46c8 1137 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 1138 }
citrusbyte 0:01a2f8de46c8 1139 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1140 }
citrusbyte 0:01a2f8de46c8 1141
citrusbyte 0:01a2f8de46c8 1142 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1143 }
citrusbyte 0:01a2f8de46c8 1144
citrusbyte 0:01a2f8de46c8 1145 jsonlite_result jsonlite_builder_raw_value(jsonlite_builder builder, const void *data, size_t length) {
citrusbyte 0:01a2f8de46c8 1146 jsonlite_write_state *ws;
citrusbyte 0:01a2f8de46c8 1147
citrusbyte 0:01a2f8de46c8 1148 if (builder == NULL || data == NULL || length == 0) {
citrusbyte 0:01a2f8de46c8 1149 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1150 }
citrusbyte 0:01a2f8de46c8 1151
citrusbyte 0:01a2f8de46c8 1152 ws = builder->state;
citrusbyte 0:01a2f8de46c8 1153
citrusbyte 0:01a2f8de46c8 1154 if (jsonlite_builder_accept(builder, jsonlite_accept_value) ) {
citrusbyte 0:01a2f8de46c8 1155 jsonlite_builder_prepare_value_writing(builder);
citrusbyte 0:01a2f8de46c8 1156 jsonlite_builder_raw(builder, data, length);
citrusbyte 0:01a2f8de46c8 1157 if (jsonlite_builder_accept(builder, jsonlite_accept_values_only) ) {
citrusbyte 0:01a2f8de46c8 1158 ws->accept = jsonlite_accept_continue_array;
citrusbyte 0:01a2f8de46c8 1159 } else {
citrusbyte 0:01a2f8de46c8 1160 ws->accept = jsonlite_accept_continue_object;
citrusbyte 0:01a2f8de46c8 1161 }
citrusbyte 0:01a2f8de46c8 1162 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1163 }
citrusbyte 0:01a2f8de46c8 1164
citrusbyte 0:01a2f8de46c8 1165 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1166 }
citrusbyte 0:01a2f8de46c8 1167
citrusbyte 0:01a2f8de46c8 1168 jsonlite_result jsonlite_builder_data(jsonlite_builder builder, char **data, size_t *size) {
citrusbyte 0:01a2f8de46c8 1169 jsonlite_builder_buffer *b;
citrusbyte 0:01a2f8de46c8 1170 char *buff = NULL;
citrusbyte 0:01a2f8de46c8 1171
citrusbyte 0:01a2f8de46c8 1172 if (builder == NULL || data == NULL || size == NULL) {
citrusbyte 0:01a2f8de46c8 1173 return jsonlite_result_invalid_argument;
citrusbyte 0:01a2f8de46c8 1174 }
citrusbyte 0:01a2f8de46c8 1175
citrusbyte 0:01a2f8de46c8 1176 *size = 0;
citrusbyte 0:01a2f8de46c8 1177 for (b = builder->first; b != NULL; b = b->next) {
citrusbyte 0:01a2f8de46c8 1178 *size += b->cursor - b->data;
citrusbyte 0:01a2f8de46c8 1179 }
citrusbyte 0:01a2f8de46c8 1180
citrusbyte 0:01a2f8de46c8 1181 if (*size == 0) {
citrusbyte 0:01a2f8de46c8 1182 return jsonlite_result_not_allowed;
citrusbyte 0:01a2f8de46c8 1183 }
citrusbyte 0:01a2f8de46c8 1184
citrusbyte 0:01a2f8de46c8 1185 *data = (char*)calloc(*size, 1);
citrusbyte 0:01a2f8de46c8 1186 buff = *data;
citrusbyte 0:01a2f8de46c8 1187 for (b = builder->first; b != NULL; b = b->next) {
citrusbyte 0:01a2f8de46c8 1188 size_t s = b->cursor - b->data;
citrusbyte 0:01a2f8de46c8 1189 memcpy(buff, b->data, s); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1190 buff += s;
citrusbyte 0:01a2f8de46c8 1191 }
citrusbyte 0:01a2f8de46c8 1192 return jsonlite_result_ok;
citrusbyte 0:01a2f8de46c8 1193 }
citrusbyte 0:01a2f8de46c8 1194 //
citrusbyte 0:01a2f8de46c8 1195 // Copyright 2012-2013, Andrii Mamchur
citrusbyte 0:01a2f8de46c8 1196 //
citrusbyte 0:01a2f8de46c8 1197 // Licensed under the Apache License, Version 2.0 (the "License");
citrusbyte 0:01a2f8de46c8 1198 // you may not use this file except in compliance with the License.
citrusbyte 0:01a2f8de46c8 1199 // You may obtain a copy of the License at
citrusbyte 0:01a2f8de46c8 1200 //
citrusbyte 0:01a2f8de46c8 1201 // http://www.apache.org/licenses/LICENSE-2.0
citrusbyte 0:01a2f8de46c8 1202 //
citrusbyte 0:01a2f8de46c8 1203 // Unless required by applicable law or agreed to in writing, software
citrusbyte 0:01a2f8de46c8 1204 // distributed under the License is distributed on an "AS IS" BASIS,
citrusbyte 0:01a2f8de46c8 1205 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
citrusbyte 0:01a2f8de46c8 1206 // See the License for the specific language governing permissions and
citrusbyte 0:01a2f8de46c8 1207 // limitations under the License
citrusbyte 0:01a2f8de46c8 1208
citrusbyte 0:01a2f8de46c8 1209 #ifndef JSONLITE_AMALGAMATED
citrusbyte 0:01a2f8de46c8 1210 #include "../include/jsonlite_token.h"
citrusbyte 0:01a2f8de46c8 1211 #endif
citrusbyte 0:01a2f8de46c8 1212
citrusbyte 0:01a2f8de46c8 1213 #include <stdlib.h>
citrusbyte 0:01a2f8de46c8 1214
citrusbyte 0:01a2f8de46c8 1215 #ifdef _MSC_VER
citrusbyte 0:01a2f8de46c8 1216 #include <intrin.h>
citrusbyte 0:01a2f8de46c8 1217
citrusbyte 0:01a2f8de46c8 1218 static uint32_t __inline jsonlite_clz( uint32_t x ) {
citrusbyte 0:01a2f8de46c8 1219 unsigned long r = 0;
citrusbyte 0:01a2f8de46c8 1220 _BitScanForward(&r, x);
citrusbyte 0:01a2f8de46c8 1221 return r;
citrusbyte 0:01a2f8de46c8 1222 }
citrusbyte 0:01a2f8de46c8 1223
citrusbyte 0:01a2f8de46c8 1224 #else
citrusbyte 0:01a2f8de46c8 1225
citrusbyte 0:01a2f8de46c8 1226 #define jsonlite_clz(x) __builtin_clz((x))
citrusbyte 0:01a2f8de46c8 1227
citrusbyte 0:01a2f8de46c8 1228 #endif
citrusbyte 0:01a2f8de46c8 1229
citrusbyte 0:01a2f8de46c8 1230 uint8_t jsonlite_hex_char_to_uint8(uint8_t c) {
citrusbyte 0:01a2f8de46c8 1231 uint8_t res = 0xFF;
citrusbyte 0:01a2f8de46c8 1232 if (c >= '0' && c <= '9') {
citrusbyte 0:01a2f8de46c8 1233 res = c - '0';
citrusbyte 0:01a2f8de46c8 1234 } else if (c >= 'a' && c <= 'f') {
citrusbyte 0:01a2f8de46c8 1235 res = c - 'a' + 10;
citrusbyte 0:01a2f8de46c8 1236 } else if (c >= 'A' && c <= 'F') {
citrusbyte 0:01a2f8de46c8 1237 res = c - 'A' + 10;
citrusbyte 0:01a2f8de46c8 1238 }
citrusbyte 0:01a2f8de46c8 1239 return res;
citrusbyte 0:01a2f8de46c8 1240 }
citrusbyte 0:01a2f8de46c8 1241
citrusbyte 0:01a2f8de46c8 1242 static int unicode_char_to_utf16(uint32_t ch, uint16_t *utf16) {
citrusbyte 0:01a2f8de46c8 1243 uint32_t v = ch - 0x10000;
citrusbyte 0:01a2f8de46c8 1244 uint32_t vh = v >> 10;
citrusbyte 0:01a2f8de46c8 1245 uint32_t vl = v & 0x3FF;
citrusbyte 0:01a2f8de46c8 1246 if (ch <= 0xFFFF) {
citrusbyte 0:01a2f8de46c8 1247 *utf16 = (uint16_t)ch;
citrusbyte 0:01a2f8de46c8 1248 return 1;
citrusbyte 0:01a2f8de46c8 1249 }
citrusbyte 0:01a2f8de46c8 1250
citrusbyte 0:01a2f8de46c8 1251 *utf16++ = (uint16_t)(0xD800 + vh);
citrusbyte 0:01a2f8de46c8 1252 *utf16 = (uint16_t)(0xDC00 + vl);
citrusbyte 0:01a2f8de46c8 1253 return 2;
citrusbyte 0:01a2f8de46c8 1254 }
citrusbyte 0:01a2f8de46c8 1255
citrusbyte 0:01a2f8de46c8 1256 size_t jsonlite_token_decode_size_for_uft8(jsonlite_token *ts) {
citrusbyte 0:01a2f8de46c8 1257 if (ts == NULL) {
citrusbyte 0:01a2f8de46c8 1258 return 0;
citrusbyte 0:01a2f8de46c8 1259 }
citrusbyte 0:01a2f8de46c8 1260
citrusbyte 0:01a2f8de46c8 1261 return ts->end - ts->start + 1;
citrusbyte 0:01a2f8de46c8 1262 }
citrusbyte 0:01a2f8de46c8 1263
citrusbyte 0:01a2f8de46c8 1264 size_t jsonlite_token_decode_to_uft8(jsonlite_token *ts, uint8_t **buffer) {
citrusbyte 0:01a2f8de46c8 1265 size_t size = jsonlite_token_decode_size_for_uft8(ts);
citrusbyte 0:01a2f8de46c8 1266 if (size == 0 || buffer == NULL) {
citrusbyte 0:01a2f8de46c8 1267 return 0;
citrusbyte 0:01a2f8de46c8 1268 }
citrusbyte 0:01a2f8de46c8 1269
citrusbyte 0:01a2f8de46c8 1270 const uint8_t *p = ts->start;
citrusbyte 0:01a2f8de46c8 1271 const uint8_t *l = ts->end;
citrusbyte 0:01a2f8de46c8 1272 uint32_t value, utf32;
citrusbyte 0:01a2f8de46c8 1273 uint8_t *c = *buffer = (uint8_t *)malloc(size);
citrusbyte 0:01a2f8de46c8 1274 int res;
citrusbyte 0:01a2f8de46c8 1275 step:
citrusbyte 0:01a2f8de46c8 1276 if (p == l) goto done;
citrusbyte 0:01a2f8de46c8 1277 if (*p == '\\') goto escaped;
citrusbyte 0:01a2f8de46c8 1278 if (*p >= 0x80) goto utf8;
citrusbyte 0:01a2f8de46c8 1279 *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1280 goto step;
citrusbyte 0:01a2f8de46c8 1281 escaped:
citrusbyte 0:01a2f8de46c8 1282 switch (*++p) {
citrusbyte 0:01a2f8de46c8 1283 case 34: *c++ = '"'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1284 case 47: *c++ = '/'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1285 case 92: *c++ = '\\'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1286 case 98: *c++ = '\b'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1287 case 102: *c++ = '\f'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1288 case 110: *c++ = '\n'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1289 case 114: *c++ = '\r'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1290 case 116: *c++ = '\t'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1291 }
citrusbyte 0:01a2f8de46c8 1292
citrusbyte 0:01a2f8de46c8 1293 // UTF-16
citrusbyte 0:01a2f8de46c8 1294 p++;
citrusbyte 0:01a2f8de46c8 1295 utf32 = jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1296 utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1297 utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1298 utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1299 if (0xD800 > utf32 || utf32 > 0xDBFF) goto encode;
citrusbyte 0:01a2f8de46c8 1300
citrusbyte 0:01a2f8de46c8 1301 // UTF-16 Surrogate
citrusbyte 0:01a2f8de46c8 1302 p += 2;
citrusbyte 0:01a2f8de46c8 1303 utf32 = (utf32 - 0xD800) << 10;
citrusbyte 0:01a2f8de46c8 1304 value = jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1305 value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1306 value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1307 value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1308 utf32 += value - 0xDC00 + 0x10000;
citrusbyte 0:01a2f8de46c8 1309 encode:
citrusbyte 0:01a2f8de46c8 1310 if (utf32 < 0x80) {
citrusbyte 0:01a2f8de46c8 1311 *c++ = (uint8_t)utf32;
citrusbyte 0:01a2f8de46c8 1312 } else if (utf32 < 0x0800) {
citrusbyte 0:01a2f8de46c8 1313 c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1314 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1315 c[0] = (uint8_t)utf32 | 0xC0;
citrusbyte 0:01a2f8de46c8 1316 c += 2;
citrusbyte 0:01a2f8de46c8 1317 } else if (utf32 < 0x10000) {
citrusbyte 0:01a2f8de46c8 1318 c[2] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1319 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1320 c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1321 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1322 c[0] = (uint8_t)utf32 | 0xE0;
citrusbyte 0:01a2f8de46c8 1323 c += 3;
citrusbyte 0:01a2f8de46c8 1324 } else {
citrusbyte 0:01a2f8de46c8 1325 c[3] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1326 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1327 c[2] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1328 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1329 c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
citrusbyte 0:01a2f8de46c8 1330 utf32 = utf32 >> 6;
citrusbyte 0:01a2f8de46c8 1331 c[0] = (uint8_t)utf32 | 0xF0;
citrusbyte 0:01a2f8de46c8 1332 c += 4;
citrusbyte 0:01a2f8de46c8 1333 }
citrusbyte 0:01a2f8de46c8 1334 goto step;
citrusbyte 0:01a2f8de46c8 1335 utf8:
citrusbyte 0:01a2f8de46c8 1336 res = jsonlite_clz(((*p) ^ 0xFF) << 0x19);
citrusbyte 0:01a2f8de46c8 1337 *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1338 switch (res) {
citrusbyte 0:01a2f8de46c8 1339 case 3: *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1340 case 2: *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1341 case 1: *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1342 }
citrusbyte 0:01a2f8de46c8 1343 goto step;
citrusbyte 0:01a2f8de46c8 1344 done:
citrusbyte 0:01a2f8de46c8 1345 *c = 0;
citrusbyte 0:01a2f8de46c8 1346 return c - *buffer;
citrusbyte 0:01a2f8de46c8 1347 }
citrusbyte 0:01a2f8de46c8 1348
citrusbyte 0:01a2f8de46c8 1349 size_t jsonlite_token_decode_size_for_uft16(jsonlite_token *ts) {
citrusbyte 0:01a2f8de46c8 1350 if (ts == NULL) {
citrusbyte 0:01a2f8de46c8 1351 return 0;
citrusbyte 0:01a2f8de46c8 1352 }
citrusbyte 0:01a2f8de46c8 1353
citrusbyte 0:01a2f8de46c8 1354 return (ts->end - ts->start + 1) * sizeof(uint16_t);
citrusbyte 0:01a2f8de46c8 1355 }
citrusbyte 0:01a2f8de46c8 1356
citrusbyte 0:01a2f8de46c8 1357 size_t jsonlite_token_decode_to_uft16(jsonlite_token *ts, uint16_t **buffer) {
citrusbyte 0:01a2f8de46c8 1358 size_t size = jsonlite_token_decode_size_for_uft16(ts);
citrusbyte 0:01a2f8de46c8 1359 if (size == 0 || buffer == NULL) {
citrusbyte 0:01a2f8de46c8 1360 return 0;
citrusbyte 0:01a2f8de46c8 1361 }
citrusbyte 0:01a2f8de46c8 1362
citrusbyte 0:01a2f8de46c8 1363 const uint8_t *p = ts->start;
citrusbyte 0:01a2f8de46c8 1364 const uint8_t *l = ts->end;
citrusbyte 0:01a2f8de46c8 1365 uint16_t utf16;
citrusbyte 0:01a2f8de46c8 1366 uint16_t *c = *buffer = (uint16_t *)malloc(size);
citrusbyte 0:01a2f8de46c8 1367 int res;
citrusbyte 0:01a2f8de46c8 1368 step:
citrusbyte 0:01a2f8de46c8 1369 if (p == l) goto done;
citrusbyte 0:01a2f8de46c8 1370 if (*p == '\\') goto escaped;
citrusbyte 0:01a2f8de46c8 1371 if (*p >= 0x80) goto utf8;
citrusbyte 0:01a2f8de46c8 1372 *c++ = *p++;
citrusbyte 0:01a2f8de46c8 1373 goto step;
citrusbyte 0:01a2f8de46c8 1374 escaped:
citrusbyte 0:01a2f8de46c8 1375 switch (*++p) {
citrusbyte 0:01a2f8de46c8 1376 case 34: *c++ = '"'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1377 case 47: *c++ = '/'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1378 case 92: *c++ = '\\'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1379 case 98: *c++ = '\b'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1380 case 102: *c++ = '\f'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1381 case 110: *c++ = '\n'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1382 case 114: *c++ = '\r'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1383 case 116: *c++ = '\t'; p++; goto step;
citrusbyte 0:01a2f8de46c8 1384 }
citrusbyte 0:01a2f8de46c8 1385
citrusbyte 0:01a2f8de46c8 1386 // UTF-16
citrusbyte 0:01a2f8de46c8 1387 p++;
citrusbyte 0:01a2f8de46c8 1388 utf16 = jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1389 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1390 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1391 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1392 *c++ = utf16;
citrusbyte 0:01a2f8de46c8 1393 if (0xD800 > utf16 || utf16 > 0xDBFF) goto step;
citrusbyte 0:01a2f8de46c8 1394
citrusbyte 0:01a2f8de46c8 1395 // UTF-16 Surrogate
citrusbyte 0:01a2f8de46c8 1396 p += 2;
citrusbyte 0:01a2f8de46c8 1397 utf16 = jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1398 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1399 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1400 utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
citrusbyte 0:01a2f8de46c8 1401 *c++ = utf16;
citrusbyte 0:01a2f8de46c8 1402 goto step;
citrusbyte 0:01a2f8de46c8 1403 utf8:
citrusbyte 0:01a2f8de46c8 1404 res = jsonlite_clz(((*p) ^ 0xFF) << 0x19);
citrusbyte 0:01a2f8de46c8 1405 uint32_t code = (*p & (0xFF >> (res + 1)));
citrusbyte 0:01a2f8de46c8 1406 switch (res) {
citrusbyte 0:01a2f8de46c8 1407 case 3: code = (code << 6) | (*++p & 0x3F);
citrusbyte 0:01a2f8de46c8 1408 case 2: code = (code << 6) | (*++p & 0x3F);
citrusbyte 0:01a2f8de46c8 1409 case 1: code = (code << 6) | (*++p & 0x3F);
citrusbyte 0:01a2f8de46c8 1410 case 0: ++p;
citrusbyte 0:01a2f8de46c8 1411 }
citrusbyte 0:01a2f8de46c8 1412
citrusbyte 0:01a2f8de46c8 1413 c += unicode_char_to_utf16(code, c);
citrusbyte 0:01a2f8de46c8 1414 goto step;
citrusbyte 0:01a2f8de46c8 1415 done:
citrusbyte 0:01a2f8de46c8 1416 *c = 0;
citrusbyte 0:01a2f8de46c8 1417 return (c - *buffer) * sizeof(uint16_t);
citrusbyte 0:01a2f8de46c8 1418 }
citrusbyte 0:01a2f8de46c8 1419 //
citrusbyte 0:01a2f8de46c8 1420 // Copyright 2012-2013, Andrii Mamchur
citrusbyte 0:01a2f8de46c8 1421 //
citrusbyte 0:01a2f8de46c8 1422 // Licensed under the Apache License, Version 2.0 (the "License");
citrusbyte 0:01a2f8de46c8 1423 // you may not use this file except in compliance with the License.
citrusbyte 0:01a2f8de46c8 1424 // You may obtain a copy of the License at
citrusbyte 0:01a2f8de46c8 1425 //
citrusbyte 0:01a2f8de46c8 1426 // http://www.apache.org/licenses/LICENSE-2.0
citrusbyte 0:01a2f8de46c8 1427 //
citrusbyte 0:01a2f8de46c8 1428 // Unless required by applicable law or agreed to in writing, software
citrusbyte 0:01a2f8de46c8 1429 // distributed under the License is distributed on an "AS IS" BASIS,
citrusbyte 0:01a2f8de46c8 1430 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
citrusbyte 0:01a2f8de46c8 1431 // See the License for the specific language governing permissions and
citrusbyte 0:01a2f8de46c8 1432 // limitations under the License
citrusbyte 0:01a2f8de46c8 1433
citrusbyte 0:01a2f8de46c8 1434 #ifndef JSONLITE_AMALGAMATED
citrusbyte 0:01a2f8de46c8 1435 #include "../include/jsonlite_token_pool.h"
citrusbyte 0:01a2f8de46c8 1436 #endif
citrusbyte 0:01a2f8de46c8 1437
citrusbyte 0:01a2f8de46c8 1438 #include <stdlib.h>
citrusbyte 0:01a2f8de46c8 1439 #include <string.h>
citrusbyte 0:01a2f8de46c8 1440
citrusbyte 0:01a2f8de46c8 1441 #define JSONLITE_TOKEN_POOL_FRONT 0x80
citrusbyte 0:01a2f8de46c8 1442 #define JSONLITE_TOKEN_POOL_FRONT_MASK (JSONLITE_TOKEN_POOL_FRONT - 1)
citrusbyte 0:01a2f8de46c8 1443
citrusbyte 0:01a2f8de46c8 1444 typedef struct content_pool_size {
citrusbyte 0:01a2f8de46c8 1445 jsonlite_token_bucket *buckets[JSONLITE_TOKEN_POOL_FRONT];
citrusbyte 0:01a2f8de46c8 1446 size_t buckets_length[JSONLITE_TOKEN_POOL_FRONT];
citrusbyte 0:01a2f8de46c8 1447 size_t buckets_capacity[JSONLITE_TOKEN_POOL_FRONT];
citrusbyte 0:01a2f8de46c8 1448
citrusbyte 0:01a2f8de46c8 1449 uint8_t *content_pool;
citrusbyte 0:01a2f8de46c8 1450 size_t content_pool_size;
citrusbyte 0:01a2f8de46c8 1451
citrusbyte 0:01a2f8de46c8 1452 jsonlite_token_pool_release_value_fn release_fn;
citrusbyte 0:01a2f8de46c8 1453
citrusbyte 0:01a2f8de46c8 1454 } jsonlite_token_pool_struct;
citrusbyte 0:01a2f8de46c8 1455
citrusbyte 0:01a2f8de46c8 1456 static void jsonlite_extend_capacity(jsonlite_token_pool pool, int index);
citrusbyte 0:01a2f8de46c8 1457 static int jsonlite_bucket_not_copied(jsonlite_token_pool pool, jsonlite_token_bucket *b);
citrusbyte 0:01a2f8de46c8 1458 static int jsonlite_token_compare(const uint8_t *t1, const uint8_t *t2, size_t length);
citrusbyte 0:01a2f8de46c8 1459 static uint32_t jsonlite_hash(const uint8_t *data, size_t len);
citrusbyte 0:01a2f8de46c8 1460
citrusbyte 0:01a2f8de46c8 1461 jsonlite_token_pool jsonlite_token_pool_create(jsonlite_token_pool_release_value_fn release_fn) {
citrusbyte 0:01a2f8de46c8 1462 jsonlite_token_pool pool = (jsonlite_token_pool)calloc(1, sizeof(jsonlite_token_pool_struct));
citrusbyte 0:01a2f8de46c8 1463 pool->release_fn = release_fn;
citrusbyte 0:01a2f8de46c8 1464 return pool;
citrusbyte 0:01a2f8de46c8 1465 }
citrusbyte 0:01a2f8de46c8 1466
citrusbyte 0:01a2f8de46c8 1467 void jsonlite_token_pool_copy_tokens(jsonlite_token_pool pool) {
citrusbyte 0:01a2f8de46c8 1468 jsonlite_token_bucket *b;
citrusbyte 0:01a2f8de46c8 1469 size_t size = pool->content_pool_size;
citrusbyte 0:01a2f8de46c8 1470 int i;
citrusbyte 0:01a2f8de46c8 1471
citrusbyte 0:01a2f8de46c8 1472 for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
citrusbyte 0:01a2f8de46c8 1473 b = pool->buckets[i];
citrusbyte 0:01a2f8de46c8 1474 if (jsonlite_bucket_not_copied(pool, b)) {
citrusbyte 0:01a2f8de46c8 1475 size += b->end - b->start;
citrusbyte 0:01a2f8de46c8 1476 }
citrusbyte 0:01a2f8de46c8 1477 }
citrusbyte 0:01a2f8de46c8 1478
citrusbyte 0:01a2f8de46c8 1479 if (size == pool->content_pool_size) {
citrusbyte 0:01a2f8de46c8 1480 return;
citrusbyte 0:01a2f8de46c8 1481 }
citrusbyte 0:01a2f8de46c8 1482
citrusbyte 0:01a2f8de46c8 1483 uint8_t *buffer = (uint8_t *)malloc(size);
citrusbyte 0:01a2f8de46c8 1484 ptrdiff_t offset = 0;
citrusbyte 0:01a2f8de46c8 1485 if (pool->content_pool != NULL) {
citrusbyte 0:01a2f8de46c8 1486 offset = buffer - pool->content_pool;
citrusbyte 0:01a2f8de46c8 1487 memcpy(buffer, pool->content_pool, pool->content_pool_size); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1488 }
citrusbyte 0:01a2f8de46c8 1489
citrusbyte 0:01a2f8de46c8 1490 uint8_t *p = buffer + pool->content_pool_size;
citrusbyte 0:01a2f8de46c8 1491 for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
citrusbyte 0:01a2f8de46c8 1492 b = pool->buckets[i];
citrusbyte 0:01a2f8de46c8 1493 if (b == NULL) {
citrusbyte 0:01a2f8de46c8 1494 continue;
citrusbyte 0:01a2f8de46c8 1495 }
citrusbyte 0:01a2f8de46c8 1496
citrusbyte 0:01a2f8de46c8 1497 if (jsonlite_bucket_not_copied(pool, b)) {
citrusbyte 0:01a2f8de46c8 1498 size_t length = b->end - b->start;
citrusbyte 0:01a2f8de46c8 1499 memcpy(p, b->start, length); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1500 b->start = p,
citrusbyte 0:01a2f8de46c8 1501 b->end = p + length,
citrusbyte 0:01a2f8de46c8 1502 p += length;
citrusbyte 0:01a2f8de46c8 1503 } else {
citrusbyte 0:01a2f8de46c8 1504 b->start += offset;
citrusbyte 0:01a2f8de46c8 1505 b->end += offset;
citrusbyte 0:01a2f8de46c8 1506 }
citrusbyte 0:01a2f8de46c8 1507 }
citrusbyte 0:01a2f8de46c8 1508
citrusbyte 0:01a2f8de46c8 1509 free(pool->content_pool);
citrusbyte 0:01a2f8de46c8 1510 pool->content_pool = buffer;
citrusbyte 0:01a2f8de46c8 1511 pool->content_pool_size = size;
citrusbyte 0:01a2f8de46c8 1512 }
citrusbyte 0:01a2f8de46c8 1513
citrusbyte 0:01a2f8de46c8 1514 void jsonlite_token_pool_release(jsonlite_token_pool pool) {
citrusbyte 0:01a2f8de46c8 1515 int i, j;
citrusbyte 0:01a2f8de46c8 1516 if (pool == NULL) {
citrusbyte 0:01a2f8de46c8 1517 return;
citrusbyte 0:01a2f8de46c8 1518 }
citrusbyte 0:01a2f8de46c8 1519
citrusbyte 0:01a2f8de46c8 1520 for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
citrusbyte 0:01a2f8de46c8 1521 jsonlite_token_bucket *bucket = pool->buckets[i];
citrusbyte 0:01a2f8de46c8 1522 if (bucket == NULL) {
citrusbyte 0:01a2f8de46c8 1523 continue;
citrusbyte 0:01a2f8de46c8 1524 }
citrusbyte 0:01a2f8de46c8 1525
citrusbyte 0:01a2f8de46c8 1526 if (pool->release_fn != NULL) {
citrusbyte 0:01a2f8de46c8 1527 size_t count = pool->buckets_length[i];
citrusbyte 0:01a2f8de46c8 1528 for (j = 0; j < count; j++, bucket++) {
citrusbyte 0:01a2f8de46c8 1529 pool->release_fn((void *)bucket->value);
citrusbyte 0:01a2f8de46c8 1530 }
citrusbyte 0:01a2f8de46c8 1531 }
citrusbyte 0:01a2f8de46c8 1532
citrusbyte 0:01a2f8de46c8 1533 free(pool->buckets[i]);
citrusbyte 0:01a2f8de46c8 1534 }
citrusbyte 0:01a2f8de46c8 1535
citrusbyte 0:01a2f8de46c8 1536 free(pool->content_pool);
citrusbyte 0:01a2f8de46c8 1537 free(pool);
citrusbyte 0:01a2f8de46c8 1538 }
citrusbyte 0:01a2f8de46c8 1539
citrusbyte 0:01a2f8de46c8 1540 jsonlite_token_bucket* jsonlite_token_pool_get_bucket(jsonlite_token_pool pool, jsonlite_token *token) {
citrusbyte 0:01a2f8de46c8 1541 if (pool == NULL || token == NULL) {
citrusbyte 0:01a2f8de46c8 1542 return NULL;
citrusbyte 0:01a2f8de46c8 1543 }
citrusbyte 0:01a2f8de46c8 1544
citrusbyte 0:01a2f8de46c8 1545 if (token->start == NULL || token->end == NULL) {
citrusbyte 0:01a2f8de46c8 1546 return NULL;
citrusbyte 0:01a2f8de46c8 1547 }
citrusbyte 0:01a2f8de46c8 1548
citrusbyte 0:01a2f8de46c8 1549 size_t length = token->end - token->start;
citrusbyte 0:01a2f8de46c8 1550 uint32_t hash = jsonlite_hash(token->start, length);
citrusbyte 0:01a2f8de46c8 1551 uint32_t index = hash & JSONLITE_TOKEN_POOL_FRONT_MASK;
citrusbyte 0:01a2f8de46c8 1552 jsonlite_token_bucket *bucket = pool->buckets[index];
citrusbyte 0:01a2f8de46c8 1553 size_t count = pool->buckets_length[index];
citrusbyte 0:01a2f8de46c8 1554 for (; count > 0; count--, bucket++) {
citrusbyte 0:01a2f8de46c8 1555 if (bucket->hash != hash) {
citrusbyte 0:01a2f8de46c8 1556 continue;
citrusbyte 0:01a2f8de46c8 1557 }
citrusbyte 0:01a2f8de46c8 1558
citrusbyte 0:01a2f8de46c8 1559 if (length != bucket->end - bucket->start) {
citrusbyte 0:01a2f8de46c8 1560 continue;
citrusbyte 0:01a2f8de46c8 1561 }
citrusbyte 0:01a2f8de46c8 1562
citrusbyte 0:01a2f8de46c8 1563 if (jsonlite_token_compare(token->start, bucket->start, length)) {
citrusbyte 0:01a2f8de46c8 1564 return bucket;
citrusbyte 0:01a2f8de46c8 1565 }
citrusbyte 0:01a2f8de46c8 1566 }
citrusbyte 0:01a2f8de46c8 1567
citrusbyte 0:01a2f8de46c8 1568 if (pool->buckets_length[index] >= pool->buckets_capacity[index]) {
citrusbyte 0:01a2f8de46c8 1569 jsonlite_extend_capacity(pool, index);
citrusbyte 0:01a2f8de46c8 1570 }
citrusbyte 0:01a2f8de46c8 1571
citrusbyte 0:01a2f8de46c8 1572 bucket = pool->buckets[index] + pool->buckets_length[index]++;
citrusbyte 0:01a2f8de46c8 1573 bucket->hash = hash;
citrusbyte 0:01a2f8de46c8 1574 bucket->start = token->start;
citrusbyte 0:01a2f8de46c8 1575 bucket->end = token->end;
citrusbyte 0:01a2f8de46c8 1576 bucket->value = NULL;
citrusbyte 0:01a2f8de46c8 1577 return bucket;
citrusbyte 0:01a2f8de46c8 1578 }
citrusbyte 0:01a2f8de46c8 1579
citrusbyte 0:01a2f8de46c8 1580 static int jsonlite_token_compare(const uint8_t *t1, const uint8_t *t2, size_t length) {
citrusbyte 0:01a2f8de46c8 1581 return memcmp(t1, t2, length) == 0 ? 1 : 0;
citrusbyte 0:01a2f8de46c8 1582 }
citrusbyte 0:01a2f8de46c8 1583
citrusbyte 0:01a2f8de46c8 1584 static void jsonlite_extend_capacity(jsonlite_token_pool pool, int index) {
citrusbyte 0:01a2f8de46c8 1585 size_t capacity = pool->buckets_capacity[index];
citrusbyte 0:01a2f8de46c8 1586 if (capacity == 0) {
citrusbyte 0:01a2f8de46c8 1587 capacity = 0x10;
citrusbyte 0:01a2f8de46c8 1588 }
citrusbyte 0:01a2f8de46c8 1589
citrusbyte 0:01a2f8de46c8 1590 size_t size = capacity * sizeof(jsonlite_token_bucket);
citrusbyte 0:01a2f8de46c8 1591 jsonlite_token_bucket *b = pool->buckets[index];
citrusbyte 0:01a2f8de46c8 1592 jsonlite_token_bucket *extended = (jsonlite_token_bucket *)malloc(2 * size);
citrusbyte 0:01a2f8de46c8 1593
citrusbyte 0:01a2f8de46c8 1594 if (b != NULL) {
citrusbyte 0:01a2f8de46c8 1595 memcpy(extended, b, size); // LCOV_EXCL_LINE
citrusbyte 0:01a2f8de46c8 1596 free(b);
citrusbyte 0:01a2f8de46c8 1597 }
citrusbyte 0:01a2f8de46c8 1598
citrusbyte 0:01a2f8de46c8 1599 pool->buckets[index] = extended;
citrusbyte 0:01a2f8de46c8 1600 pool->buckets_capacity[index] = 2 * capacity;
citrusbyte 0:01a2f8de46c8 1601 }
citrusbyte 0:01a2f8de46c8 1602
citrusbyte 0:01a2f8de46c8 1603 static int jsonlite_bucket_not_copied(jsonlite_token_pool pool, jsonlite_token_bucket *b) {
citrusbyte 0:01a2f8de46c8 1604 if (b == NULL) {
citrusbyte 0:01a2f8de46c8 1605 return 0;
citrusbyte 0:01a2f8de46c8 1606 }
citrusbyte 0:01a2f8de46c8 1607
citrusbyte 0:01a2f8de46c8 1608 int res = b->start < pool->content_pool;
citrusbyte 0:01a2f8de46c8 1609 res |= b->start >= pool->content_pool + pool->content_pool_size;
citrusbyte 0:01a2f8de46c8 1610 return res;
citrusbyte 0:01a2f8de46c8 1611 }
citrusbyte 0:01a2f8de46c8 1612
citrusbyte 0:01a2f8de46c8 1613 // Used MurmurHash2 function by Austin Appleby
citrusbyte 0:01a2f8de46c8 1614 // http://code.google.com/p/smhasher/ revision 147
citrusbyte 0:01a2f8de46c8 1615
citrusbyte 0:01a2f8de46c8 1616 //-----------------------------------------------------------------------------
citrusbyte 0:01a2f8de46c8 1617 // MurmurHash2 was written by Austin Appleby, and is placed in the public
citrusbyte 0:01a2f8de46c8 1618 // domain. The author hereby disclaims copyright to this source code.
citrusbyte 0:01a2f8de46c8 1619
citrusbyte 0:01a2f8de46c8 1620 // Note - This code makes a few assumptions about how your machine behaves -
citrusbyte 0:01a2f8de46c8 1621
citrusbyte 0:01a2f8de46c8 1622 // 1. We can read a 4-byte value from any address without crashing
citrusbyte 0:01a2f8de46c8 1623 // 2. sizeof(int) == 4
citrusbyte 0:01a2f8de46c8 1624
citrusbyte 0:01a2f8de46c8 1625 // And it has a few limitations -
citrusbyte 0:01a2f8de46c8 1626
citrusbyte 0:01a2f8de46c8 1627 // 1. It will not work incrementally.
citrusbyte 0:01a2f8de46c8 1628 // 2. It will not produce the same results on little-endian and big-endian
citrusbyte 0:01a2f8de46c8 1629 // machines.
citrusbyte 0:01a2f8de46c8 1630
citrusbyte 0:01a2f8de46c8 1631 static uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
citrusbyte 0:01a2f8de46c8 1632 {
citrusbyte 0:01a2f8de46c8 1633 // 'm' and 'r' are mixing constants generated offline.
citrusbyte 0:01a2f8de46c8 1634 // They're not really 'magic', they just happen to work well.
citrusbyte 0:01a2f8de46c8 1635
citrusbyte 0:01a2f8de46c8 1636 const uint32_t m = 0x5bd1e995;
citrusbyte 0:01a2f8de46c8 1637 const int r = 24;
citrusbyte 0:01a2f8de46c8 1638
citrusbyte 0:01a2f8de46c8 1639 // Initialize the hash to a 'random' value
citrusbyte 0:01a2f8de46c8 1640
citrusbyte 0:01a2f8de46c8 1641 uint32_t h = seed ^ len;
citrusbyte 0:01a2f8de46c8 1642
citrusbyte 0:01a2f8de46c8 1643 // Mix 4 bytes at a time into the hash
citrusbyte 0:01a2f8de46c8 1644
citrusbyte 0:01a2f8de46c8 1645 const unsigned char * data = (const unsigned char *)key;
citrusbyte 0:01a2f8de46c8 1646
citrusbyte 0:01a2f8de46c8 1647 while(len >= 4)
citrusbyte 0:01a2f8de46c8 1648 {
citrusbyte 0:01a2f8de46c8 1649 uint32_t k = *(uint32_t*)data;
citrusbyte 0:01a2f8de46c8 1650
citrusbyte 0:01a2f8de46c8 1651 k *= m;
citrusbyte 0:01a2f8de46c8 1652 k ^= k >> r;
citrusbyte 0:01a2f8de46c8 1653 k *= m;
citrusbyte 0:01a2f8de46c8 1654
citrusbyte 0:01a2f8de46c8 1655 h *= m;
citrusbyte 0:01a2f8de46c8 1656 h ^= k;
citrusbyte 0:01a2f8de46c8 1657
citrusbyte 0:01a2f8de46c8 1658 data += 4;
citrusbyte 0:01a2f8de46c8 1659 len -= 4;
citrusbyte 0:01a2f8de46c8 1660 }
citrusbyte 0:01a2f8de46c8 1661
citrusbyte 0:01a2f8de46c8 1662 // Handle the last few bytes of the input array
citrusbyte 0:01a2f8de46c8 1663
citrusbyte 0:01a2f8de46c8 1664 switch(len)
citrusbyte 0:01a2f8de46c8 1665 {
citrusbyte 0:01a2f8de46c8 1666 case 3: h ^= data[2] << 16;
citrusbyte 0:01a2f8de46c8 1667 case 2: h ^= data[1] << 8;
citrusbyte 0:01a2f8de46c8 1668 case 1: h ^= data[0];
citrusbyte 0:01a2f8de46c8 1669 h *= m;
citrusbyte 0:01a2f8de46c8 1670 };
citrusbyte 0:01a2f8de46c8 1671
citrusbyte 0:01a2f8de46c8 1672 // Do a few final mixes of the hash to ensure the last few
citrusbyte 0:01a2f8de46c8 1673 // bytes are well-incorporated.
citrusbyte 0:01a2f8de46c8 1674
citrusbyte 0:01a2f8de46c8 1675 h ^= h >> 13;
citrusbyte 0:01a2f8de46c8 1676 h *= m;
citrusbyte 0:01a2f8de46c8 1677 h ^= h >> 15;
citrusbyte 0:01a2f8de46c8 1678
citrusbyte 0:01a2f8de46c8 1679 return h;
citrusbyte 0:01a2f8de46c8 1680 }
citrusbyte 0:01a2f8de46c8 1681
citrusbyte 0:01a2f8de46c8 1682 //-----------------------------------------------------------------------------
citrusbyte 0:01a2f8de46c8 1683
citrusbyte 0:01a2f8de46c8 1684 static uint32_t jsonlite_hash(const uint8_t *data, size_t len) {
citrusbyte 0:01a2f8de46c8 1685 return MurmurHash2(data, (int)len, 0);
citrusbyte 0:01a2f8de46c8 1686 }
citrusbyte 0:01a2f8de46c8 1687