Home Alert System

Dependencies:   PWM_Tone_Library DHT

Revision:
3:78f223d34f36
diff -r 3a61e56476bc -r 78f223d34f36 jsonlite/jsonlite.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsonlite/jsonlite.c	Tue Mar 05 02:34:44 2019 +0000
@@ -0,0 +1,1942 @@
+#define JSONLITE_AMALGAMATED
+#include "jsonlite.h"
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+const char *jsonlite_version = "1.1.2";
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+#ifndef JSONLITE_AMALGAMATED
+#include "../include/jsonlite_builder.h"
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#define jsonlite_builder_check_depth()          \
+do {                                            \
+    if (builder->state >= builder->limit) {     \
+        return jsonlite_result_depth_limit;     \
+    }                                           \
+} while (0)
+
+enum {
+    jsonlite_accept_object_begin    = 0x0001,
+    jsonlite_accept_object_end      = 0x0002,
+    jsonlite_accept_array_begin     = 0x0004,
+    jsonlite_accept_array_end       = 0x0008,
+    jsonlite_accept_key             = 0x0010,
+    jsonlite_accept_string          = 0x0020,
+    jsonlite_accept_number          = 0x0040,
+    jsonlite_accept_boolean         = 0x0080,
+    jsonlite_accept_null            = 0x0100,
+    jsonlite_accept_values_only     = 0x0200,
+    jsonlite_accept_next            = 0x0400,
+
+    jsonlite_accept_value           = 0
+                                    | jsonlite_accept_object_begin
+                                    | jsonlite_accept_array_begin
+                                    | jsonlite_accept_string
+                                    | jsonlite_accept_number
+                                    | jsonlite_accept_boolean
+                                    | jsonlite_accept_null,
+    jsonlite_accept_continue_object = 0
+                                    | jsonlite_accept_next
+                                    | jsonlite_accept_key
+                                    | jsonlite_accept_object_end,
+    jsonlite_accept_continue_array = 0
+                                    | jsonlite_accept_next
+                                    | jsonlite_accept_values_only
+                                    | jsonlite_accept_value
+                                    | jsonlite_accept_array_end
+};
+
+typedef uint16_t jsonlite_write_state;
+typedef struct jsonlite_builder_struct {
+    jsonlite_write_state *state;
+    jsonlite_write_state *limit;
+    jsonlite_write_state *stack;
+    jsonlite_stream stream;
+
+    size_t indentation;
+    char *doubleFormat;
+} jsonlite_builder_struct;
+
+static int jsonlite_builder_accept(jsonlite_builder builder, jsonlite_write_state a);
+static void jsonlite_builder_pop_state(jsonlite_builder builder);
+static void jsonlite_builder_prepare_value_writing(jsonlite_builder builder);
+static void jsonlite_builder_raw_char(jsonlite_builder builder, char data);
+static void jsonlite_builder_write_uft8(jsonlite_builder builder, const char *data, size_t length);
+static void jsonlite_builder_raw(jsonlite_builder builder, const void *data, size_t length);
+static void jsonlite_builder_repeat(jsonlite_builder builder, const char ch, size_t count);
+static void jsonlite_builder_write_base64(jsonlite_builder builder, const void *data, size_t length);
+
+jsonlite_builder jsonlite_builder_init(size_t depth, jsonlite_stream stream) {
+    jsonlite_builder builder;
+
+    depth = depth < 2 ? 2 : depth;
+
+    builder = malloc(sizeof(jsonlite_builder_struct) + depth * sizeof(jsonlite_write_state));
+    builder->state = (jsonlite_write_state *)((uint8_t *)builder + sizeof(jsonlite_builder_struct));
+    builder->limit = builder->state + depth - 1;
+    builder->stack = builder->state;
+    builder->stream = stream;
+    builder->indentation = 0;
+    *builder->state = jsonlite_accept_object_begin | jsonlite_accept_array_begin;
+    jsonlite_builder_set_double_format(builder, "%.16g");
+    return builder;
+}
+
+jsonlite_result jsonlite_builder_release(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    free(builder->doubleFormat);
+    free(builder);
+    return jsonlite_result_ok;
+}
+
+jsonlite_result jsonlite_builder_set_indentation(jsonlite_builder builder, size_t indentation) {
+    if (builder != NULL) {
+        builder->indentation = indentation;
+        return jsonlite_result_ok;
+    }
+    return jsonlite_result_invalid_argument;
+}
+
+jsonlite_result jsonlite_builder_set_double_format(jsonlite_builder builder, const char *format) {
+    if (builder != NULL && format != NULL) {
+        builder->doubleFormat = strdup(format);
+        return jsonlite_result_ok;
+    }
+    return jsonlite_result_invalid_argument;
+}
+
+static int jsonlite_builder_accept(jsonlite_builder builder, jsonlite_write_state a) {
+    return (*builder->state & a) == a;
+}
+
+static void jsonlite_builder_pop_state(jsonlite_builder builder) {
+    jsonlite_write_state *ws = --builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+        *ws = jsonlite_accept_continue_array;
+    } else {
+        *ws = jsonlite_accept_continue_object;
+    }
+}
+
+static void jsonlite_builder_prepare_value_writing(jsonlite_builder builder) {
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+        if (jsonlite_builder_accept(builder, jsonlite_accept_next)) {
+            jsonlite_builder_raw_char(builder, ',');
+        }
+
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw_char(builder, '\r');
+            jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
+        }
+    } else {
+        *ws &= ~jsonlite_accept_value;
+        *ws |= jsonlite_accept_key;
+    }
+    *ws |= jsonlite_accept_next;
+}
+
+jsonlite_result jsonlite_builder_object_begin(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_builder_check_depth();
+
+    if (jsonlite_builder_accept(builder, jsonlite_accept_object_begin)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        *++builder->state = jsonlite_accept_object_end | jsonlite_accept_key;
+        jsonlite_builder_raw_char(builder, '{');
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_object_end(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    if (jsonlite_builder_accept(builder, jsonlite_accept_object_end)) {
+        jsonlite_builder_pop_state(builder);
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw_char(builder, '\r');
+            jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
+        }
+        jsonlite_builder_raw_char(builder, '}');
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_array_begin(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_builder_check_depth();
+
+    if (jsonlite_builder_accept(builder, jsonlite_accept_array_begin)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        *++builder->state = jsonlite_accept_array_end
+            | jsonlite_accept_value
+            | jsonlite_accept_values_only;
+        jsonlite_builder_raw_char(builder, '[');
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_array_end(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    if (jsonlite_builder_accept(builder, jsonlite_accept_array_end)) {
+        jsonlite_builder_pop_state(builder);
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw_char(builder, '\r');
+            jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
+        }
+        jsonlite_builder_raw_char(builder, ']');
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+static void jsonlite_builder_write_uft8(jsonlite_builder builder, const char *data, size_t length) {
+    char b[2] = {'\\', '?'};
+    const char *c = data;
+    const char *p = data;
+    const char *l = data + length;
+
+    jsonlite_builder_raw_char(builder, '\"');
+next:
+    if (c == l)                     goto end;
+    switch (*c) {
+        case '"':   b[1] = '"';     goto flush;
+        case '\\':  b[1] = '\\';    goto flush;
+        case '\b':  b[1] = 'b';     goto flush;
+        case '\f':  b[1] = 'f';     goto flush;
+        case '\n':  b[1] = 'n';     goto flush;
+        case '\r':  b[1] = 'r';     goto flush;
+        case '\t':  b[1] = 't';     goto flush;
+        default:    c++;            goto next;
+    }
+flush:
+    jsonlite_stream_write(builder->stream, p, c - p);
+    jsonlite_stream_write(builder->stream, b, 2);
+    p = ++c;
+    goto next;
+end:
+    jsonlite_stream_write(builder->stream, p, c - p);
+    jsonlite_builder_raw_char(builder, '\"');
+}
+
+jsonlite_result jsonlite_builder_key(jsonlite_builder builder, const char *data, size_t length) {
+    if (builder == NULL || data == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_key)) {
+        if (jsonlite_builder_accept(builder, jsonlite_accept_next)) {
+            jsonlite_builder_raw_char(builder, ',');
+        }
+
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw_char(builder, '\r');
+            jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
+        }
+
+        jsonlite_builder_write_uft8(builder, data, length);
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw(builder, ": ", 2);
+        } else {
+            jsonlite_builder_raw_char(builder, ':');
+        }
+        *ws = jsonlite_accept_value;
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_string(jsonlite_builder builder, const char *data, size_t length) {
+    if (builder == NULL || data == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        jsonlite_builder_write_uft8(builder, data, length);
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_int(jsonlite_builder builder, long long value) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    char buff[64];
+    size_t size = 0;
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        size = sprintf(buff, "%lld", value);
+        jsonlite_builder_raw(builder, buff, size);
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_double(jsonlite_builder builder, double value) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    char buff[64];
+    size_t size = 0;
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        size = sprintf(buff, builder->doubleFormat, value);
+        jsonlite_builder_raw(builder, buff, size);
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_true(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    static const char value[] = "true";
+    jsonlite_write_state *ws = builder->state;
+    if (!(jsonlite_builder_accept(builder, jsonlite_accept_value))) {
+
+        return jsonlite_result_not_allowed;
+    }
+
+    jsonlite_builder_prepare_value_writing(builder);
+    jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
+    if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+        *ws = jsonlite_accept_continue_array;
+    } else {
+        *ws = jsonlite_accept_continue_object;
+    }
+    return jsonlite_result_ok;
+}
+
+jsonlite_result jsonlite_builder_false(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    static const char value[] = "false";
+    jsonlite_write_state *ws = builder->state;
+    if (!(jsonlite_builder_accept(builder, jsonlite_accept_value))) {
+        return jsonlite_result_not_allowed;
+    }
+
+    jsonlite_builder_prepare_value_writing(builder);
+    jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
+    if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+        *ws = jsonlite_accept_continue_array;
+    } else {
+        *ws = jsonlite_accept_continue_object;
+    }
+    return jsonlite_result_ok;
+}
+
+jsonlite_result jsonlite_builder_null(jsonlite_builder builder) {
+    if (builder == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    static const char value[] = "null";
+    jsonlite_write_state *ws = builder->state;
+    if (!(jsonlite_builder_accept(builder, jsonlite_accept_value))) {
+
+        return jsonlite_result_not_allowed;
+    }
+
+    jsonlite_builder_prepare_value_writing(builder);
+    jsonlite_builder_raw(builder, (char *)value, sizeof(value) - 1);
+    if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+        *ws = jsonlite_accept_continue_array;
+    } else {
+        *ws = jsonlite_accept_continue_object;
+    }
+    return jsonlite_result_ok;
+}
+
+static void jsonlite_builder_raw(jsonlite_builder builder, const void *data, size_t length) {
+    jsonlite_stream_write(builder->stream, data, length);
+}
+
+static void jsonlite_builder_repeat(jsonlite_builder builder, const char ch, size_t count) {
+    ptrdiff_t i = 0;
+    for (; i < count; i++) {
+        jsonlite_stream_write(builder->stream, &ch, 1);
+    }
+}
+
+static  void jsonlite_builder_raw_char(jsonlite_builder builder, char data) {
+    jsonlite_stream_write(builder->stream, &data, 1);
+}
+
+jsonlite_result jsonlite_builder_raw_key(jsonlite_builder builder, const void *data, size_t length) {
+    if (builder == NULL || data == NULL || length == 0) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_key)) {
+        if (jsonlite_builder_accept(builder, jsonlite_accept_next)) {
+            jsonlite_builder_raw(builder, ",", 1);
+        }
+
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw_char(builder, '\r');
+            jsonlite_builder_repeat(builder, ' ', (builder->state - builder->stack) * builder->indentation);
+        }
+
+        jsonlite_builder_raw_char(builder, '\"');
+        jsonlite_builder_raw(builder, data, length);
+        jsonlite_builder_raw_char(builder, '\"');
+        if (builder->indentation != 0) {
+            jsonlite_builder_raw(builder, ": ", 2);
+        } else {
+            jsonlite_builder_raw_char(builder, ':');
+        }
+        *ws = jsonlite_accept_value;
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_raw_string(jsonlite_builder builder, const void *data, size_t length) {
+    if (builder == NULL || data == NULL || length == 0) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        jsonlite_builder_raw_char(builder, '\"');
+        jsonlite_builder_raw(builder, data, length);
+        jsonlite_builder_raw_char(builder, '\"');
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+jsonlite_result jsonlite_builder_raw_value(jsonlite_builder builder, const void *data, size_t length) {
+    if (builder == NULL || data == NULL || length == 0) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        jsonlite_builder_raw(builder, data, length);
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+}
+
+static void jsonlite_builder_write_base64(jsonlite_builder builder, const void *data, size_t length) {
+    static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    char buffer[5] = {0};
+    const uint8_t *c = data;
+    const uint8_t *l = data + length;
+    uint32_t bits;
+    jsonlite_stream_write(builder->stream, "\"", 1);
+next:
+    switch (l - c) {
+        case 0:
+            goto done;
+        case 1:
+            bits = *c++ << 16;
+            buffer[0] = encode[(bits & 0x00FC0000) >> 18];
+            buffer[1] = encode[(bits & 0x0003F000) >> 12];
+            buffer[2] = '=';
+            buffer[3] = '=';
+            l = c;
+            goto write;
+        case 2:
+            bits = *c++ << 16;
+            bits |= *c++ << 8;
+            buffer[0] = encode[(bits & 0x00FC0000) >> 18];
+            buffer[1] = encode[(bits & 0x0003F000) >> 12];
+            buffer[2] = encode[(bits & 0x00000FC0) >> 6];
+            buffer[3] = '=';
+            l = c;
+            goto write;
+        default:
+            bits = *c++ << 16;
+            bits |= *c++ << 8;
+            bits |= *c++;
+            buffer[0] = encode[(bits & 0x00FC0000) >> 18];
+            buffer[1] = encode[(bits & 0x0003F000) >> 12];
+            buffer[2] = encode[(bits & 0x00000FC0) >> 6];
+            buffer[3] = encode[(bits & 0x0000003F)];
+            goto write;
+    }
+write:
+    jsonlite_stream_write(builder->stream, buffer, 4);
+    goto next;
+done:
+    jsonlite_stream_write(builder->stream, "\"", 1);
+}
+
+jsonlite_result jsonlite_builder_base64_value(jsonlite_builder builder, const void *data, size_t length) {
+    if (builder == NULL || data == NULL || length == 0) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    jsonlite_write_state *ws = builder->state;
+    if (jsonlite_builder_accept(builder, jsonlite_accept_value)) {
+        jsonlite_builder_prepare_value_writing(builder);
+        jsonlite_builder_write_base64(builder, data, length);
+        if (jsonlite_builder_accept(builder, jsonlite_accept_values_only)) {
+            *ws = jsonlite_accept_continue_array;
+        } else {
+            *ws = jsonlite_accept_continue_object;
+        }
+        return jsonlite_result_ok;
+    }
+
+    return jsonlite_result_not_allowed;
+
+}
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+#ifndef JSONLITE_AMALGAMATED
+#include "jsonlite_parser.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+
+#include <intrin.h>
+
+static uint32_t __inline jsonlite_clz(uint32_t x) {
+   unsigned long r = 0;
+   _BitScanForward(&r, x);
+   return r;
+}
+
+#else
+
+#define jsonlite_clz(x) __builtin_clz((x))
+
+#endif
+
+#define MIN_DEPTH 2
+#define CALL_VALUE_CALLBACK(cbs, type, token)   (cbs.type(&cbs.context, token))
+#define CALL_STATE_CALLBACK(cbs, type)          (cbs.type(&cbs.context))
+
+#define HEX_CHAR_TO_INT(c, step)        \
+if (0x30 <= *c && *c <= 0x39) {         \
+    hex_value = *c - 0x30;              \
+} else if (0x41 <= *c && *c <= 0x46) {  \
+    hex_value = *c - 0x37;              \
+} else if (0x61 <= *c && *c <= 0x66) {  \
+    hex_value = *c - 0x57;              \
+} else goto error_escape;               \
+c += step
+
+#define CASE_NUMBER_TOKEN_END   \
+case 0x09: goto number_parsed;  \
+case 0x0A: goto number_parsed;  \
+case 0x0D: goto number_parsed;  \
+case 0x20: goto number_parsed;  \
+case 0x2C: goto number_parsed;  \
+case 0x5D: goto number_parsed;  \
+case 0x7D: goto number_parsed
+
+enum {
+    state_start,
+    state_object_key,
+    state_object_key_end,
+    state_colon,
+    state_object_comma_end,
+    state_array_value_end,
+    state_array_comma_end,
+    state_key,
+    state_value,
+    state_end,
+
+    state_stop = 1 << 7
+};
+
+typedef uint8_t parse_state;
+struct jsonlite_parser_struct {
+    const uint8_t *cursor;
+    const uint8_t *limit;
+    const uint8_t *buffer;
+    uint8_t *buffer_own;
+
+    parse_state *current;
+    parse_state *last;
+    parse_state **control;
+
+    jsonlite_result result;
+    jsonlite_parser_callbacks callbacks;
+} jsonlite_parser_struct;
+
+static void jsonlite_do_parse(jsonlite_parser parser);
+static void empty_value_callback(jsonlite_callback_context *ctx, jsonlite_token *t) {}
+static void empty_state_callback(jsonlite_callback_context *ctx) {}
+
+const jsonlite_parser_callbacks jsonlite_default_callbacks = {
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_state_callback,
+    &empty_value_callback,
+    &empty_value_callback,
+    &empty_value_callback,
+    {NULL, NULL}
+};
+
+size_t jsonlite_parser_estimate_size(size_t depth) {
+    depth = depth < MIN_DEPTH ? 32 : depth;
+    return sizeof(jsonlite_parser_struct) + depth * sizeof(parse_state);
+}
+
+static jsonlite_parser jsonlite_parser_configure(void *memory, size_t size) {
+    size_t depth = (size - sizeof(jsonlite_parser_struct)) / sizeof(parse_state);
+    jsonlite_parser parser = (jsonlite_parser)memory;
+    parser->result = jsonlite_result_unknown;
+    parser->buffer_own = NULL;
+    parser->callbacks = jsonlite_default_callbacks;
+    parser->control = NULL;
+    parser->current = ((uint8_t *)parser + sizeof(jsonlite_parser_struct));
+    parser->current[0] = state_end;
+    parser->current[1] = state_start;
+    parser->last = parser->current + depth;
+    parser->current++;
+    return parser;
+}
+
+jsonlite_parser jsonlite_parser_init(size_t depth) {
+    size_t size = jsonlite_parser_estimate_size(depth);
+    void *memory = malloc(size);
+    return jsonlite_parser_configure(memory, size);
+}
+
+jsonlite_parser jsonlite_parser_init_memory(void *memory, size_t size) {
+    if (memory == NULL) {
+        return NULL;
+    }
+
+    if (size < jsonlite_parser_estimate_size(MIN_DEPTH)) {
+        return NULL;
+    }
+
+    return jsonlite_parser_configure(memory, size);
+}
+
+jsonlite_result jsonlite_parser_set_callback(jsonlite_parser parser, const jsonlite_parser_callbacks *cbs) {
+    if (parser == NULL || cbs == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    parser->callbacks = *cbs;
+    parser->callbacks.context.parser = parser;
+    return jsonlite_result_ok;
+}
+
+jsonlite_result jsonlite_parser_get_result(jsonlite_parser parser) {
+    if (parser == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    return parser->result;
+}
+
+jsonlite_result jsonlite_parser_tokenize(jsonlite_parser parser, const void *buffer, size_t size) {
+    if (parser == NULL || buffer == NULL || size == 0) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    if (parser->buffer_own != NULL) {
+        size_t total_size = size + parser->limit - parser->buffer_own;
+        uint8_t *b = (uint8_t *)malloc(total_size);
+        memcpy(b, parser->buffer_own, parser->limit - parser->buffer_own);  // LCOV_EXCL_LINE
+        memcpy(b + (parser->limit - parser->buffer_own), buffer, size);     // LCOV_EXCL_LINE
+
+        free(parser->buffer_own);
+
+        parser->buffer = b;
+        parser->buffer_own = b;
+        parser->cursor = b;
+        parser->limit = b + total_size;
+    } else {
+        parser->buffer = buffer;
+        parser->cursor = parser->buffer;
+        parser->limit = parser->buffer + size;
+    }
+
+    jsonlite_do_parse(parser);
+    return parser->result;
+}
+
+jsonlite_result jsonlite_parser_resume(jsonlite_parser parser) {
+    if (parser == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    if (parser->result != jsonlite_result_suspended) {
+        return jsonlite_result_not_allowed;
+    }
+
+    jsonlite_do_parse(parser);
+    return parser->result;
+}
+
+jsonlite_result jsonlite_parser_suspend(jsonlite_parser parser) {
+    return jsonlite_parser_terminate(parser, jsonlite_result_suspended);
+}
+
+jsonlite_result jsonlite_parser_terminate(jsonlite_parser parser, jsonlite_result result) {
+    if (parser == NULL) {
+        return jsonlite_result_invalid_argument;
+    }
+
+    if (parser->control == NULL) {
+        return jsonlite_result_not_allowed;
+    }
+
+    parser->result = result;
+    **parser->control |= state_stop;
+    return jsonlite_result_ok;
+}
+
+void jsonlite_parser_release(jsonlite_parser parser) {
+    jsonlite_parser_cleanup(parser);
+    free(parser);
+}
+
+void jsonlite_parser_cleanup(jsonlite_parser parser) {
+    if (parser == NULL) {
+        return;
+    }
+
+    free(parser->buffer_own);
+}
+
+static void jsonlite_do_parse(jsonlite_parser parser) {
+    const uint8_t *c = parser->cursor;
+    const uint8_t *l = parser->limit;
+    const uint8_t *token_start = NULL;
+    const parse_state *last = parser->last;
+    parse_state *state = parser->current;
+    jsonlite_token token = {NULL, NULL, NULL, 0};
+    jsonlite_result result = jsonlite_result_ok;
+    uint32_t value, utf32;
+    uint8_t hex_value;
+
+    *state &= ~state_stop;
+    parser->control = &state;
+    goto select_state;
+
+structure_finished:
+    if (*state == state_end)            goto end;
+skip_char_and_whitespaces:
+    c++;
+select_state:
+    if (c == l)     goto end_of_stream_whitespaces;
+    if (*c == 0x20) goto skip_char_and_whitespaces;
+    if (*c == 0x0A) goto skip_char_and_whitespaces;
+    if (*c == 0x0D) goto skip_char_and_whitespaces;
+    if (*c == 0x09) goto skip_char_and_whitespaces;
+    token_start = c;
+
+    switch (*state) {
+        case state_value:               goto parse_value;
+        case state_colon:               goto parse_colon;
+        case state_object_comma_end:    goto parse_object_comma_end;
+        case state_object_key:          goto parse_key;
+        case state_object_key_end:      goto parse_key_end;
+        case state_array_comma_end:     goto parse_array_comma_end;
+        case state_array_value_end:     goto parse_array_value_end;
+        case state_key:                 goto parse_string_token;
+        case state_start:
+            if (*c == 0x7B)             goto parse_object;
+            if (*c == 0x5B)             goto parse_array_state;
+            goto error_exp_ooa;
+        case state_end:                 goto end;
+        default:
+            result = parser->result;
+            goto end;
+    }
+parse_object:
+    *state = state_object_key_end;
+    CALL_STATE_CALLBACK(parser->callbacks, object_start);
+    goto skip_char_and_whitespaces;
+parse_array_state:
+    *state = state_array_value_end;
+    CALL_STATE_CALLBACK(parser->callbacks, array_start);
+    goto skip_char_and_whitespaces;
+parse_key:
+    if (*c != 0x22) goto error_exp_key;
+    *state = state_colon;
+    *++state = state_key;
+    goto parse_string_token;
+parse_colon:
+    if (*c != 0x3A) goto error_exp_colon;
+    *state = state_object_comma_end;
+    *++state = state_value;
+    goto skip_char_and_whitespaces;
+parse_key_end:
+    switch (*c) {
+        case 0x22:
+            *state = state_colon;
+            if (++state == last) goto error_depth;
+            *state = state_key;
+            goto parse_string_token;
+        case 0x7D:
+            state--;
+            CALL_STATE_CALLBACK(parser->callbacks, object_end);
+            goto structure_finished;
+        default: goto error_exp_koe;
+    }
+parse_object_comma_end:
+    switch (*c) {
+        case 0x2C:
+            *state = state_object_key;
+            goto skip_char_and_whitespaces;
+        case 0x7D:
+            state--;
+            CALL_STATE_CALLBACK(parser->callbacks, object_end);
+            goto structure_finished;
+        default: goto error_exp_coe;
+    }
+parse_array_value_end:
+    switch (*c) {
+        case 0x5D:
+            state--;
+            CALL_STATE_CALLBACK(parser->callbacks, array_end);
+            goto structure_finished;
+        default:
+            *state = state_array_comma_end;
+            if (++state == last) goto error_depth;
+            *state = state_value;
+            goto parse_value;
+    }
+parse_array_comma_end:
+    switch (*c) {
+        case 0x2C:
+            *++state = state_value;
+            goto skip_char_and_whitespaces;
+        case 0x5D:
+            state--;
+            CALL_STATE_CALLBACK(parser->callbacks, array_end);
+            goto structure_finished;
+        default: goto error_exp_coe;
+    }
+parse_value:
+    if (0x31 <= *c && *c <= 0x39)   goto parse_digit_leading_number;
+    if (*c == 0x30)                 goto parse_zero_leading_number;
+    if (*c == 0x2D)                 goto parse_negative_number;
+    if (*c == 0x22)                 goto parse_string_token;
+    if (*c == 0x74)                 goto parse_true_token;
+    if (*c == 0x66)                 goto parse_false_token;
+    if (*c == 0x6E)                 goto parse_null_token;
+    if (*c == 0x7B)                 goto parse_object;
+    if (*c == 0x5B)                 goto parse_array_state;
+    goto error_exp_value;
+
+// Number parsing
+parse_negative_number:
+    token.start = c;
+    token.type.number = jsonlite_number_int | jsonlite_number_negative;
+    if (++c == l)                   goto end_of_stream;
+    if (0x31 <= *c && *c <= 0x39)   goto parse_digits;
+    if (*c == 0x30)                 goto parse_exponent_fraction;
+    goto error_number;
+parse_zero_leading_number:
+    token.start = c;
+    token.type.number = jsonlite_number_int | jsonlite_number_zero_leading;
+parse_exponent_fraction:
+    if (++c == l)                   goto end_of_stream;
+    switch (*c) {
+        CASE_NUMBER_TOKEN_END;
+        case 0x2E:                  goto parse_fraction;
+        case 0x45:                  goto parse_exponent;
+        case 0x65:                  goto parse_exponent;
+        default:                    goto error_number;
+    }
+parse_fraction:
+    token.type.number |= jsonlite_number_frac;
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_frac_number;
+    goto error_number;
+parse_frac_number:
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_frac_number;
+    switch (*c) {
+        CASE_NUMBER_TOKEN_END;
+        case 0x45:                  goto parse_exponent;
+        case 0x65:                  goto parse_exponent;
+        default:                    goto error_number;
+    }
+parse_exponent:
+    token.type.number |= jsonlite_number_exp;
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_exponent_number;
+    switch(*c) {
+        case 0x2B:                  goto parse_exponent_sign;
+        case 0x2D:                  goto parse_exponent_sign;
+        default:                    goto error_number;
+    }
+parse_exponent_sign:
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_exponent_number;
+    goto error_number;
+parse_exponent_number:
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_exponent_number;
+    switch(*c) {
+        CASE_NUMBER_TOKEN_END;
+        default:                    goto error_number;
+    }
+parse_digit_leading_number:
+    token.start = c;
+    token.type.number = jsonlite_number_int | jsonlite_number_digit_leading;
+parse_digits:
+    if (++c == l)                   goto end_of_stream;
+    if (0x30 <= *c && *c <= 0x39)   goto parse_digits;
+    switch(*c) {
+        CASE_NUMBER_TOKEN_END;
+        case 0x2E:                  goto parse_fraction;
+        case 0x45:                  goto parse_exponent;
+        case 0x65:                  goto parse_exponent;
+        default:                    goto error_number;
+    }
+number_parsed:
+    token.end = c;
+    state--;
+    CALL_VALUE_CALLBACK(parser->callbacks, number_found, &token);
+    goto select_state;
+
+// String parsing
+parse_string_token:
+    token.type.string = jsonlite_string_ascii;
+    token.start = c + 1;
+next_char:
+    if (++c == l)       goto end_of_stream;
+    if (*c == 0x22)     goto string_parsed;
+    if (*c == 0x5C)     goto escaped;
+    if (*c > 0x7F)      goto utf8;
+    if (*c < 0x20)      goto error_token;
+    goto next_char;
+escaped:
+    token.type.string |= jsonlite_string_escape;
+    if (++c == l)       goto end_of_stream;
+    switch (*c) {
+        case 0x22:      goto next_char;     // "    quotation mark  U+0022
+        case 0x2F:      goto next_char;     // /    solidus         U+002F
+        case 0x5C:      goto next_char;     // \    reverse solidus U+005C
+        case 0x62:      goto next_char;     // b    backspace       U+0008
+        case 0x66:      goto next_char;     // f    form feed       U+000C
+        case 0x6E:      goto next_char;     // n    line feed       U+000A
+        case 0x72:      goto next_char;     // r    carriage return U+000D
+        case 0x74:      goto next_char;     // t    tab             U+0009
+        case 0x75:      goto hex;           // uXXXX                U+XXXX
+        default:        goto error_escape;
+    }
+hex:
+    token.type.string |= jsonlite_string_unicode_escape;
+    if (c++ + 4 >= l)       goto end_of_stream;
+    HEX_CHAR_TO_INT(c, 1);  value = hex_value;
+    HEX_CHAR_TO_INT(c, 1);  value = (uint32_t)(value << 4) | hex_value;
+    HEX_CHAR_TO_INT(c, 1);  value = (uint32_t)(value << 4) | hex_value;
+    HEX_CHAR_TO_INT(c, 0);  value = (uint32_t)(value << 4) | hex_value;
+
+    if ((value & 0xFFFFu) >= 0xFFFEu)           token.type.string |= jsonlite_string_unicode_noncharacter;
+    if (value >= 0xFDD0u && value <= 0xFDEFu)   token.type.string |= jsonlite_string_unicode_noncharacter;
+    if (0xD800 > value || value > 0xDBFF)       goto next_char;
+
+    // UTF-16 Surrogate
+    utf32 = (value - 0xD800) << 10;
+    if (c++ + 6 >= l)       goto end_of_stream;
+    if (*c++ != 0x5C)       goto error_escape;
+    if (*c++ != 0x75)       goto error_escape;
+    HEX_CHAR_TO_INT(c, 1);  value = hex_value;
+    HEX_CHAR_TO_INT(c, 1);  value = (uint32_t)(value << 4) | hex_value;
+    HEX_CHAR_TO_INT(c, 1);  value = (uint32_t)(value << 4) | hex_value;
+    HEX_CHAR_TO_INT(c, 0);  value = (uint32_t)(value << 4) | hex_value;
+
+    if (value < 0xDC00 || value > 0xDFFF)       goto error_escape;
+    utf32 += value - 0xDC00 + 0x10000;
+    if ((utf32 & 0x0FFFFu) >= 0x0FFFEu)         token.type.string |= jsonlite_string_unicode_noncharacter;
+    goto next_char;
+utf8:
+    token.type.string |= jsonlite_string_utf8;
+    int res = jsonlite_clz((unsigned int)((*c) ^ 0xFF) << 0x19);
+    utf32 = (*c & (0xFF >> (res + 1)));
+    value = 0xAAAAAAAA; // == 1010...
+    if (c + res >= l) goto end_of_stream;
+    switch (res) {
+        case 3: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
+        case 2: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
+        case 1: value = (value << 2) | (*++c >> 6); utf32 = (utf32 << 6) | (*c & 0x3F);
+            if (value != 0xAAAAAAAA)                    goto error_utf8;
+            if ((utf32 & 0xFFFFu) >= 0xFFFEu)           token.type.string |= jsonlite_string_unicode_noncharacter;
+            if (utf32 >= 0xFDD0u && utf32 <= 0xFDEFu)   token.type.string |= jsonlite_string_unicode_noncharacter;
+    }
+    goto next_char;
+string_parsed:
+    token.end = c;
+    parser->cursor = c + 1;
+    if (*state-- == state_value) {
+        CALL_VALUE_CALLBACK(parser->callbacks, string_found, &token);
+    } else {
+        CALL_VALUE_CALLBACK(parser->callbacks, key_found, &token);
+    }
+    goto skip_char_and_whitespaces;
+
+// Primitive tokens
+parse_true_token:
+    if (c++ + 3 >= l)   goto end_of_stream;
+    if (*c++ != 0x72)   goto error_token;
+    if (*c++ != 0x75)   goto error_token;
+    if (*c++ != 0x65)   goto error_token;
+    state--;
+    CALL_STATE_CALLBACK(parser->callbacks, true_found);
+    goto select_state;
+parse_false_token:
+    if (c++ + 4 >= l)   goto end_of_stream;
+    if (*c++ != 0x61)   goto error_token;
+    if (*c++ != 0x6C)   goto error_token;
+    if (*c++ != 0x73)   goto error_token;
+    if (*c++ != 0x65)   goto error_token;
+    state--;
+    CALL_STATE_CALLBACK(parser->callbacks, false_found);
+    goto select_state;
+parse_null_token:
+    if (c++ + 3 >= l)   goto end_of_stream;
+    if (*c++ != 0x75)   goto error_token;
+    if (*c++ != 0x6C)   goto error_token;
+    if (*c++ != 0x6C)   goto error_token;
+    state--;
+    CALL_STATE_CALLBACK(parser->callbacks, null_found);
+    goto select_state;
+
+// Error states.
+error_depth:        result = jsonlite_result_depth_limit;               goto end;
+error_exp_ooa:      result = jsonlite_result_expected_object_or_array;  goto end;
+error_exp_value:    result = jsonlite_result_expected_value;            goto end;
+error_exp_koe:      result = jsonlite_result_expected_key_or_end;       goto end;
+error_exp_key:      result = jsonlite_result_expected_key;              goto end;
+error_exp_colon:    result = jsonlite_result_expected_colon;            goto end;
+error_exp_coe:      result = jsonlite_result_expected_comma_or_end;     goto end;
+error_escape:       result = jsonlite_result_invalid_escape;            goto end;
+error_number:       result = jsonlite_result_invalid_number;            goto end;
+error_token:        result = jsonlite_result_invalid_token;             goto end;
+error_utf8:         result = jsonlite_result_invalid_utf8;              goto end;
+
+// End of stream states.
+end_of_stream_whitespaces:
+    token_start = l;
+end_of_stream:
+    result = jsonlite_result_end_of_stream;
+end:
+    parser->result = result;
+    parser->current = state;
+    parser->control = NULL;
+    parser->cursor = c;
+    parser->callbacks.parse_finished(&parser->callbacks.context);
+    if (result != jsonlite_result_end_of_stream) {
+        return;
+    }
+
+    res = parser->buffer_own != NULL;
+    if ((parser->limit - token_start) > 0) {
+        parser->buffer_own = malloc(parser->limit - token_start);       // LCOV_EXCL_LINE
+        parser->limit = parser->buffer_own + (parser->limit - token_start);
+        memcpy(parser->buffer_own, token_start, parser->limit - parser->buffer_own);
+        if (res) {
+            free((void *)parser->buffer);
+            parser->buffer = parser->buffer_own;
+        }
+    } else {
+        if (res) {
+            free((void *)parser->buffer_own);
+            parser->buffer = NULL;
+            parser->buffer_own = NULL;
+        }
+    }
+}
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+#ifndef JSONLITE_AMALGAMATED
+#include "../include/jsonlite_stream.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+struct jsonlite_stream_struct {
+    jsonlite_stream_write_fn write;
+    jsonlite_stream_release_fn release;
+} jsonlite_stream_struct;
+
+int jsonlite_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    return stream->write(stream, data, length);
+}
+
+void jsonlite_stream_release(jsonlite_stream stream) {
+    if (stream == NULL) {
+        return;
+    }
+
+    if (stream->release != NULL) {
+        stream->release(stream);
+    }
+}
+
+static void jsonlite_stream_free_mem(jsonlite_stream stream) {
+    free((void *)stream);
+}
+
+#define CAST_TO_MEM_STREAM(S)   (jsonlite_mem_stream *)((uint8_t *)(S) + sizeof(jsonlite_stream_struct))
+#define SIZE_OF_MEM_STREAM()    (sizeof(jsonlite_stream_struct) + sizeof(jsonlite_mem_stream))
+
+typedef struct jsonlite_mem_stream_block {
+    struct jsonlite_mem_stream_block *next;
+    uint8_t *data;
+} jsonlite_mem_stream_block;
+
+typedef struct jsonlite_mem_stream {
+    size_t block_size;
+    uint8_t *cursor;
+    uint8_t *limit;
+    struct jsonlite_mem_stream_block *current;
+    struct jsonlite_mem_stream_block *first;
+} jsonlite_mem_stream;
+
+static int jsonlite_mem_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    jsonlite_mem_stream *mem_stream = CAST_TO_MEM_STREAM(stream);
+    size_t write_limit = mem_stream->limit - mem_stream->cursor;
+    if (write_limit >= length) {
+        memcpy(mem_stream->cursor, data, length); // LCOV_EXCL_LINE
+        mem_stream->cursor += length;
+    } else {
+        memcpy(mem_stream->cursor, data, write_limit); // LCOV_EXCL_LINE
+        mem_stream->cursor += write_limit;
+
+        size_t size = sizeof(jsonlite_mem_stream_block) + mem_stream->block_size;
+        jsonlite_mem_stream_block *block = malloc(size);
+        block->data = (uint8_t *)block + sizeof(jsonlite_mem_stream_block);
+        block->next = NULL;
+
+        mem_stream->current->next = block;
+        mem_stream->current = block;
+        mem_stream->cursor = block->data;
+        mem_stream->limit = block->data + mem_stream->block_size;
+
+        jsonlite_mem_stream_write(stream, (char *)data + write_limit, length - write_limit);
+    }
+
+    return (int)length;
+}
+
+static void jsonlite_mem_stream_release(jsonlite_stream stream) {
+    jsonlite_mem_stream *mem_stream = CAST_TO_MEM_STREAM(stream);
+    jsonlite_mem_stream_block *block = mem_stream->first;
+    void *prev;
+    for (; block != NULL;) {
+        prev = block;
+        block = block->next;
+        free(prev);
+    }
+
+    free((void *)stream);
+}
+
+jsonlite_stream jsonlite_mem_stream_init(size_t block_size) {
+    size_t size = SIZE_OF_MEM_STREAM();
+    struct jsonlite_stream_struct *stream = malloc(size);
+    stream->write = jsonlite_mem_stream_write;
+    stream->release = jsonlite_mem_stream_release;
+
+    jsonlite_mem_stream_block *first = malloc(sizeof(jsonlite_mem_stream_block) + block_size);
+    first->data = (uint8_t *)first + sizeof(jsonlite_mem_stream_block);
+    first->next = NULL;
+
+    jsonlite_mem_stream *mem_stream = CAST_TO_MEM_STREAM(stream);
+    mem_stream->block_size = block_size;
+    mem_stream->cursor = first->data;
+    mem_stream->limit = first->data + block_size;
+    mem_stream->current = first;
+    mem_stream->first = first;
+    return stream;
+}
+
+size_t jsonlite_mem_stream_data(jsonlite_stream stream, uint8_t **data, size_t extra_bytes) {
+    jsonlite_mem_stream *mem_stream = CAST_TO_MEM_STREAM(stream);
+    jsonlite_mem_stream_block *block = NULL;
+    uint8_t *buff = NULL;
+    size_t size = 0;
+
+    for (block = mem_stream->first; block != NULL; block = block->next) {
+        if (block->next != NULL) {
+            size += mem_stream->block_size;
+        } else {
+            size += mem_stream->cursor - block->data;
+        }
+    }
+
+    if (size == 0) {
+        *data = NULL;
+    } else {
+        *data = (uint8_t *)malloc(size + extra_bytes);
+        buff = *data;
+        for (block = mem_stream->first; block != NULL; block = block->next) {
+            if (block->next != NULL) {
+                memcpy(buff, block->data, mem_stream->block_size); // LCOV_EXCL_LINE
+                buff += mem_stream->block_size;
+            } else {
+                memcpy(buff, block->data, mem_stream->cursor - block->data); // LCOV_EXCL_LINE
+            }
+        }
+    }
+
+    return size;
+}
+
+#define CAST_TO_STATIC_MEM_STREAM(S)   (jsonlite_static_mem_stream *)((uint8_t *)(S) + sizeof(jsonlite_stream_struct))
+#define SIZE_OF_STATIC_MEM_STREAM()    (sizeof(jsonlite_stream_struct) + sizeof(jsonlite_static_mem_stream))
+
+typedef struct jsonlite_static_mem_stream {
+    uint8_t *buffer;
+    size_t size;
+    size_t written;
+    uint8_t *limit;
+    int enabled;
+} jsonlite_static_mem_stream;
+
+static int jsonlite_static_mem_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    jsonlite_static_mem_stream *mem_stream = CAST_TO_STATIC_MEM_STREAM(stream);
+    size_t write_limit = mem_stream->size - mem_stream->written;
+    if (mem_stream->enabled && write_limit >= length) {
+        memcpy(mem_stream->buffer + mem_stream->written, data, length); // LCOV_EXCL_LINE
+        mem_stream->written += length;
+    } else {
+        mem_stream->enabled = 0;
+        return 0;
+    }
+
+    return (int)length;
+}
+
+jsonlite_stream jsonlite_static_mem_stream_init(void *buffer, size_t size) {
+    size_t s = SIZE_OF_STATIC_MEM_STREAM();
+    struct jsonlite_stream_struct *stream = malloc(s);
+    stream->write = jsonlite_static_mem_stream_write;
+    stream->release = jsonlite_stream_free_mem;
+
+    jsonlite_static_mem_stream *mem_stream = CAST_TO_STATIC_MEM_STREAM(stream);
+    mem_stream->buffer = buffer;
+    mem_stream->size = size;
+    mem_stream->written = 0;
+    mem_stream->enabled = 1;
+    return stream;
+}
+
+size_t jsonlite_static_mem_stream_written_bytes(jsonlite_stream stream) {
+    jsonlite_static_mem_stream *mem_stream = CAST_TO_STATIC_MEM_STREAM(stream);
+    return mem_stream->written;
+}
+
+#define CAST_TO_FILE_STREAM(S)   (jsonlite_file_stream *)((uint8_t *)(S) + sizeof(jsonlite_stream_struct))
+#define SIZE_OF_FILE_STREAM()    (sizeof(jsonlite_stream_struct) + sizeof(jsonlite_file_stream))
+
+typedef struct jsonlite_file_stream {
+    FILE *file;
+} jsonlite_file_stream;
+
+static int jsonlite_file_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    jsonlite_file_stream *file_stream = CAST_TO_FILE_STREAM(stream);
+    return (int)fwrite(data, 1, length, file_stream->file);
+}
+
+jsonlite_stream jsonlite_file_stream_init(FILE *file) {
+    size_t size = SIZE_OF_FILE_STREAM();
+    struct jsonlite_stream_struct *stream = malloc(size);
+    stream->write = jsonlite_file_stream_write;
+    stream->release = jsonlite_stream_free_mem;
+
+    jsonlite_file_stream *file_stream = CAST_TO_FILE_STREAM(stream);
+    file_stream->file = file;
+    return stream;
+}
+
+static int jsonlite_null_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    return (int)length;
+}
+
+static int jsonlite_stdout_stream_write(jsonlite_stream stream, const void *data, size_t length) {
+    return (int)fwrite(data, 1, length, stdout);
+}
+
+static struct jsonlite_stream_struct jsonlite_stdout_stream_struct = {jsonlite_stdout_stream_write, NULL};
+static struct jsonlite_stream_struct jsonlite_null_stream_struct = {jsonlite_null_stream_write, NULL};
+
+jsonlite_stream jsonlite_stdout_stream = &jsonlite_stdout_stream_struct;
+jsonlite_stream jsonlite_null_stream = &jsonlite_null_stream_struct;
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+#ifndef JSONLITE_AMALGAMATED
+#include "../include/jsonlite_token.h"
+#endif
+
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+#include <intrin.h>
+
+static uint32_t __inline jsonlite_clz( uint32_t x ) {
+   unsigned long r = 0;
+   _BitScanForward(&r, x);
+   return r;
+}
+
+#else
+
+#define jsonlite_clz(x) __builtin_clz((x))
+
+#endif
+
+static uint8_t jsonlite_hex_char_to_uint8(uint8_t c) {
+    if (c >= 'a') {
+        return c - 'a' + 10;
+    }
+
+    if (c >= 'A') {
+        return c - 'A' + 10;
+    }
+
+    return c - '0';
+}
+
+static int unicode_char_to_utf16(uint32_t ch, uint16_t *utf16) {
+    uint32_t v = ch - 0x10000;
+    uint32_t vh = v >> 10;
+    uint32_t vl = v & 0x3FF;
+    if (ch <= 0xFFFF) {
+        *utf16 = (uint16_t)ch;
+        return 1;
+    }
+
+    *utf16++ = (uint16_t)(0xD800 + vh);
+    *utf16 = (uint16_t)(0xDC00 + vl);
+    return 2;
+}
+
+size_t jsonlite_token_size_of_uft8(jsonlite_token *ts) {
+    return (size_t)(ts->end - ts->start + 1);
+}
+
+size_t jsonlite_token_to_uft8(jsonlite_token *ts, uint8_t **buffer) {
+    size_t size = jsonlite_token_size_of_uft8(ts);
+    const uint8_t *p = ts->start;
+    const uint8_t *l = ts->end;
+    uint32_t value, utf32;
+    uint8_t *c = *buffer = (uint8_t *)malloc(size);
+    int res;
+step:
+    if (p == l)         goto done;
+    if (*p == '\\')     goto escaped;
+    if (*p >= 0x80)     goto utf8;
+    *c++ = *p++;
+    goto step;
+escaped:
+    switch (*++p) {
+        case 34:    *c++ = '"';     p++; goto step;
+        case 47:    *c++ = '/';     p++; goto step;
+        case 92:    *c++ = '\\';    p++; goto step;
+        case 98:    *c++ = '\b';    p++; goto step;
+        case 102:   *c++ = '\f';    p++; goto step;
+        case 110:   *c++ = '\n';    p++; goto step;
+        case 114:   *c++ = '\r';    p++; goto step;
+        case 116:   *c++ = '\t';    p++; goto step;
+    }
+
+    // UTF-16
+    p++;
+    utf32 = jsonlite_hex_char_to_uint8(*p++);
+    utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf32 = (uint32_t)(utf32 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    if (0xD800 > utf32 || utf32 > 0xDBFF) goto encode;
+
+    // UTF-16 Surrogate
+    p += 2;
+    utf32 = (utf32 - 0xD800) << 10;
+    value = jsonlite_hex_char_to_uint8(*p++);
+    value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
+    value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
+    value = (uint32_t)(value << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf32 += value - 0xDC00 + 0x10000;
+encode:
+    if (utf32 < 0x80) {
+        *c++ = (uint8_t)utf32;
+    } else if (utf32 < 0x0800) {
+        c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[0] = (uint8_t)utf32 | 0xC0;
+        c += 2;
+    } else if (utf32 < 0x10000) {
+        c[2] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[0] = (uint8_t)utf32 | 0xE0;
+        c += 3;
+    } else {
+        c[3] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[2] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[1] = (uint8_t)(utf32 & 0x3F) | 0x80;
+        utf32 = utf32 >> 6;
+        c[0] = (uint8_t)utf32 | 0xF0;
+        c += 4;
+    }
+    goto step;
+utf8:
+    res = jsonlite_clz(((*p) ^ 0xFF) << 0x19);
+    *c++ = *p++;
+    switch (res) {
+        case 3: *c++ = *p++;
+        case 2: *c++ = *p++;
+        case 1: *c++ = *p++;
+    }
+    goto step;
+done:
+    *c = 0;
+    return c - *buffer;
+}
+
+size_t jsonlite_token_size_of_uft16(jsonlite_token *ts) {
+    return (ts->end - ts->start + 1) * sizeof(uint16_t);
+}
+
+size_t jsonlite_token_to_uft16(jsonlite_token *ts, uint16_t **buffer) {
+    size_t size = jsonlite_token_size_of_uft16(ts);
+    const uint8_t *p = ts->start;
+    const uint8_t *l = ts->end;
+    uint16_t utf16;
+    uint16_t *c = *buffer = (uint16_t *)malloc(size);
+    int res;
+step:
+    if (p == l)         goto done;
+    if (*p == '\\')     goto escaped;
+    if (*p >= 0x80)     goto utf8;
+    *c++ = *p++;
+    goto step;
+escaped:
+    switch (*++p) {
+        case 34:    *c++ = '"';     p++; goto step;
+        case 47:    *c++ = '/';     p++; goto step;
+        case 92:    *c++ = '\\';    p++; goto step;
+        case 98:    *c++ = '\b';    p++; goto step;
+        case 102:   *c++ = '\f';    p++; goto step;
+        case 110:   *c++ = '\n';    p++; goto step;
+        case 114:   *c++ = '\r';    p++; goto step;
+        case 116:   *c++ = '\t';    p++; goto step;
+    }
+
+    // UTF-16
+    p++;
+    utf16 = jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    *c++ = utf16;
+    if (0xD800 > utf16 || utf16 > 0xDBFF) goto step;
+
+    // UTF-16 Surrogate
+    p += 2;
+    utf16 = jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    utf16 = (uint16_t)(utf16 << 4) | jsonlite_hex_char_to_uint8(*p++);
+    *c++ = utf16;
+    goto step;
+utf8:
+    res = jsonlite_clz(((*p) ^ 0xFF) << 0x19);
+    uint32_t code = (*p & (0xFF >> (res + 1)));
+    switch (res) {
+        case 3: code = (code << 6) | (*++p & 0x3F);
+        case 2: code = (code << 6) | (*++p & 0x3F);
+        case 1: code = (code << 6) | (*++p & 0x3F);
+        case 0: ++p;
+    }
+
+    c += unicode_char_to_utf16(code, c);
+    goto step;
+done:
+    *c = 0;
+    return (c - *buffer) * sizeof(uint16_t);
+}
+
+size_t jsonlite_token_size_of_base64_binary(jsonlite_token *ts) {
+    return (((ts->end - ts->start) * 3) / 4 + 3) & ~3;
+}
+
+size_t jsonlite_token_base64_to_binary(jsonlite_token *ts, void **buffer) {
+    size_t length = 0;
+    size_t size = jsonlite_token_size_of_base64_binary(ts);
+    const uint8_t *p = ts->start;
+    const uint8_t *l = ts->end;
+    uint8_t *c;
+    size_t bytes, i;
+    if (size > 0) {
+        c = *buffer = (uint16_t *)malloc(size);
+    } else {
+        *buffer = NULL;
+        goto error;
+    }
+next:
+    bytes = 0;
+    i = 0;
+    do {
+        if (p == l) goto error;
+        i++;
+        bytes <<= 6;
+        if (0x41 <= *p && *p <= 0x5A) { bytes |= *p++ - 0x41; continue; }
+        if (0x61 <= *p && *p <= 0x7A) { bytes |= *p++ - 0x47; continue; }
+        if (0x30 <= *p && *p <= 0x39) { bytes |= *p++ + 0x04; continue; }
+        if (*p == 0x2B) { bytes |= 0x3E; p++; continue; }
+        if (*p == 0x2F) { bytes |= 0x3F; p++; continue; }
+        if (*p == '=') {
+            switch (l - p) {
+                case 1:
+                    *c++ = (uint8_t)((bytes >> 16) & 0x000000FF);
+                    *c = (uint8_t)((bytes >> 8) & 0x000000FF);
+                    return length + 2;
+                case 2:
+                    *c = (uint8_t)((bytes >> 10) & 0x000000FF);
+                    return length + 1;
+            }
+        }
+        if (*p == 0x5C && *++p == 0x2F) { bytes |= 0x3F; p++; continue; }
+        goto error;
+    } while (i < 4);
+
+    *c++ = (uint8_t)((bytes >> 16)  & 0x000000FF);
+    *c++ = (uint8_t)((bytes >> 8)   & 0x000000FF);
+    *c++ = (uint8_t)((bytes)        & 0x000000FF);
+    length += 3;
+
+    if (p == l) goto done;
+    goto next;
+error:
+    free(*buffer);
+    *buffer = NULL;
+    length = 0;
+done:
+    return length;
+}
+
+long jsonlite_token_to_long(jsonlite_token *token) {
+    long res = 0;
+    int negative = (token->type.number & jsonlite_number_negative) == jsonlite_number_negative;
+    ptrdiff_t length = token->end - token->start - negative;
+    const uint8_t *c = token->start + negative;
+    switch (length & 3) {
+        for (; length > 0; length -= 4) {
+            case 0: res = res * 10 + *c++ - '0';
+            case 3: res = res * 10 + *c++ - '0';
+            case 2: res = res * 10 + *c++ - '0';
+            case 1: res = res * 10 + *c++ - '0';
+        }
+    }
+
+    return negative ? -res : res;
+}
+
+long long jsonlite_token_to_long_long(jsonlite_token *token) {
+    long long res = 0;
+    int negative = (token->type.number & jsonlite_number_negative) == jsonlite_number_negative;
+    ptrdiff_t length = token->end - token->start - negative;
+    const uint8_t *c = token->start + negative;
+    switch (length & 7) {
+        for (; length > 0; length -= 8) {
+            case 0: res = res * 10 + *c++ - '0';
+            case 7: res = res * 10 + *c++ - '0';
+            case 6: res = res * 10 + *c++ - '0';
+            case 5: res = res * 10 + *c++ - '0';
+            case 4: res = res * 10 + *c++ - '0';
+            case 3: res = res * 10 + *c++ - '0';
+            case 2: res = res * 10 + *c++ - '0';
+            case 1: res = res * 10 + *c++ - '0';
+        }
+    }
+
+    return negative ? -res : res;
+}
+//
+//  Copyright 2012-2013, Andrii Mamchur
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License
+
+#ifndef JSONLITE_AMALGAMATED
+#include "../include/jsonlite_token_pool.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#define JSONLITE_TOKEN_POOL_FRONT 0x80
+#define JSONLITE_TOKEN_POOL_FRONT_MASK (JSONLITE_TOKEN_POOL_FRONT - 1)
+
+typedef struct jsonlite_token_block {
+    jsonlite_token_bucket *buckets;
+    size_t capacity;
+} jsonlite_token_block;
+
+typedef struct jsonlite_token_pool_struct {
+    jsonlite_token_block blocks[JSONLITE_TOKEN_POOL_FRONT];
+    uint8_t *content_pool;
+    size_t content_pool_size;
+    jsonlite_token_pool_release_value_fn release_fn;
+
+} jsonlite_token_pool_struct;
+
+static void jsonlite_extend_capacity(jsonlite_token_pool pool, ptrdiff_t index);
+static uint32_t jsonlite_hash(const uint8_t *data, size_t len);
+static jsonlite_token_bucket terminate_bucket = {NULL, NULL, 0, 0, NULL};
+
+jsonlite_token_pool jsonlite_token_pool_create(jsonlite_token_pool_release_value_fn release_fn) {
+    jsonlite_token_pool pool = (jsonlite_token_pool)malloc(sizeof(jsonlite_token_pool_struct));
+    int i;
+    for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
+        pool->blocks[i].buckets = &terminate_bucket;
+        pool->blocks[i].capacity = 0;
+    }
+    pool->release_fn = release_fn;
+    pool->content_pool = NULL;
+    pool->content_pool_size = 0;
+    return pool;
+}
+
+void jsonlite_token_pool_copy_tokens(jsonlite_token_pool pool) {
+    jsonlite_token_bucket *bucket;
+    size_t size = 0;
+    int i;
+    for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
+        bucket = pool->blocks[i].buckets;
+        while (bucket->start != NULL) {
+            size += bucket->end - bucket->start;
+            bucket++;
+        }
+    }
+
+    if (size == pool->content_pool_size) {
+        return;
+    }
+
+    uint8_t *buffer = (uint8_t *)malloc(size);
+    uint8_t *p = buffer;
+    for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
+        bucket = pool->blocks[i].buckets;
+        while (bucket->start != NULL) {
+            size_t length = bucket->end - bucket->start;
+            memcpy(p, bucket->start, length); // LCOV_EXCL_LINE
+            bucket->start = p;
+            bucket->end = p + length;
+            p += length;
+            bucket++;
+        }
+    }
+
+    free(pool->content_pool);
+    pool->content_pool = buffer;
+    pool->content_pool_size = size;
+}
+
+void jsonlite_token_pool_release(jsonlite_token_pool pool) {
+    int i;
+    for (i = 0; i < JSONLITE_TOKEN_POOL_FRONT; i++) {
+        jsonlite_token_bucket *bucket = pool->blocks[i].buckets;
+        if (bucket->start == NULL) {
+            continue;
+        }
+
+        if (pool->release_fn != NULL) {
+            for (; bucket->start != NULL; bucket++) {
+                pool->release_fn((void *)bucket->value);
+            }
+        }
+
+        free(pool->blocks[i].buckets);
+    }
+
+    free(pool->content_pool);
+    free(pool);
+}
+
+jsonlite_token_bucket* jsonlite_token_pool_get_bucket(jsonlite_token_pool pool, jsonlite_token *token) {
+    ptrdiff_t length = token->end - token->start;
+    ptrdiff_t hash = jsonlite_hash(token->start, (size_t)length);
+    ptrdiff_t index = hash & JSONLITE_TOKEN_POOL_FRONT_MASK;
+    size_t count = 0;
+    jsonlite_token_bucket *bucket = pool->blocks[index].buckets;
+    for (; bucket->start != NULL; count++, bucket++) {
+        if (bucket->hash != hash) {
+            continue;
+        }
+
+        if (length != bucket->end - bucket->start) {
+            continue;
+        }
+
+        if (memcmp(token->start, bucket->start, (size_t)length) == 0) {
+            return bucket;
+        }
+    }
+
+    size_t capacity = pool->blocks[index].capacity;
+    if (count + 1 >= capacity) {
+        jsonlite_extend_capacity(pool, index);
+    }
+
+    bucket = pool->blocks[index].buckets + count;
+    bucket->hash = hash;
+    bucket->start = token->start;
+    bucket->end = token->end;
+    bucket->value = NULL;
+    bucket[1].start = NULL;
+    return bucket;
+}
+
+static void jsonlite_extend_capacity(jsonlite_token_pool pool, ptrdiff_t index) {
+    size_t capacity = pool->blocks[index].capacity;
+    if (capacity == 0) {
+        capacity = 0x10;
+    }
+
+    size_t size = capacity * sizeof(jsonlite_token_bucket);
+    jsonlite_token_bucket *buckets = pool->blocks[index].buckets;
+    jsonlite_token_bucket *extended = (jsonlite_token_bucket *)malloc(2 * size);
+
+    if (buckets->start != NULL) {
+        memcpy(extended, buckets, size); // LCOV_EXCL_LINE
+        free(buckets);
+    }
+
+    pool->blocks[index].buckets = extended;
+    pool->blocks[index].capacity = 2 * capacity;
+}
+
+// Used MurmurHash2 function by Austin Appleby
+// http://code.google.com/p/smhasher/ revision 147
+
+//-----------------------------------------------------------------------------
+// MurmurHash2 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+// Note - This code makes a few assumptions about how your machine behaves -
+
+// 1. We can read a 4-byte value from any address without crashing
+// 2. sizeof(int) == 4
+
+// And it has a few limitations -
+
+// 1. It will not work incrementally.
+// 2. It will not produce the same results on little-endian and big-endian
+//    machines.
+
+static uint32_t MurmurHash2(const void * key, size_t len)
+{
+    // 'm' and 'r' are mixing constants generated offline.
+    // They're not really 'magic', they just happen to work well.
+
+    const uint32_t m = 0x5bd1e995;
+    const int r = 24;
+
+    // Initialize the hash to a 'random' value
+
+    uint32_t h = (uint32_t)len;
+
+    // Mix 4 bytes at a time into the hash
+
+    const unsigned char * data = (const unsigned char *)key;
+
+    while(len >= 4)
+    {
+        uint32_t k = *(uint32_t*)data;
+
+        k *= m;
+        k ^= k >> r;
+        k *= m;
+
+        h *= m;
+        h ^= k;
+
+        data += 4;
+        len -= 4;
+    }
+
+    // Handle the last few bytes of the input array
+
+    switch(len)
+    {
+        case 3: h ^= data[2] << 16;
+        case 2: h ^= data[1] << 8;
+        case 1: h ^= data[0];
+            h *= m;
+    };
+
+    // Do a few final mixes of the hash to ensure the last few
+    // bytes are well-incorporated.
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+}
+
+//-----------------------------------------------------------------------------
+
+static uint32_t jsonlite_hash(const uint8_t *data, size_t len) {
+    return MurmurHash2(data, len);
+}
\ No newline at end of file