Home Alert System

Dependencies:   PWM_Tone_Library DHT

Committer:
aziz111
Date:
Fri Mar 08 17:15:02 2019 +0000
Revision:
5:569a4894abc1
Parent:
3:78f223d34f36
Final

Who changed what in which revision?

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