fi;
for x in $tests; do
tstcnt=$(($tstcnt+1))
- switches=`basename $x|sed -e 's/^[^.]*\.\(.*\)\.re$/-\1/g' -e 's/^[^-].*//g' -e 's/\([^ ]\)--/\1 --/g' -e 's/(\([^)]*\))/ \1/g'`
+ switches=`basename $x|sed -e 's/^[^.]*\.\(.*\)\.re$/-\1/g' -e 's/^[^-].*//g' -e 's/\([^ ]\)--/\1 --/g' -e 's/(\([^)]*\))/ \1/g' -e 's/- //g'`
genname=`printf "%s" "$switches"|sed -e 's,--.*$,,g' -e 's,^.[^o]*$,,g' -e 's,^[^ot]*t.*o.*$,,g' -e 's,^-[^o]*o\(.*\),@builddir@/test/\1,g'`
headers=`printf "%s" "$switches"|sed -e 's,--.*$,,g' -e 's,^.[^t]*$,,g' -e 's,^[^ot]*o.*t.*$,,g' -e 's,^-[^t]*t\(.*\),@builddir@/test/\1,g'`
switches=`printf "%s" "$switches"|sed -e 's,^-\([^ot-]*[ot]\)\(.*\)$,-\1@builddir@/test/\2,g'`
--- /dev/null
+/* Generated by re2c */
+#line 1 "input_custom_default.--input(custom).re"
+bool lex (const char * cursor, const char * const limit)
+{
+ const char * marker;
+ const char * ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() *cursor
+# define YYSKIP() ++cursor
+# define YYBACKUP() marker = cursor
+# define YYBACKUPCTX() ctxmarker = cursor
+# define YYRESTORE() cursor = marker
+# define YYRESTORECTX() cursor = ctxmarker
+# define YYHAS(n) limit - cursor < n
+# define YYFILL(n) {}
+
+#line 18 "<stdout>"
+{
+ YYCTYPE yych;
+
+ if (YYHAS (13)) YYFILL(13);
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'i': goto yy4;
+ default: goto yy2;
+ }
+yy2:
+ YYSKIP ();
+yy3:
+#line 16 "input_custom_default.--input(custom).re"
+ { return false; }
+#line 33 "<stdout>"
+yy4:
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'n': goto yy5;
+ default: goto yy3;
+ }
+yy5:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 't': goto yy7;
+ default: goto yy6;
+ }
+yy6:
+ YYRESTORE ();
+ goto yy3;
+yy7:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy8;
+ default: goto yy6;
+ }
+yy8:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'b': goto yy9;
+ default: goto yy6;
+ }
+yy9:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'u': goto yy10;
+ default: goto yy6;
+ }
+yy10:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy11;
+ default: goto yy6;
+ }
+yy11:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy12;
+ default: goto yy6;
+ }
+yy12:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'e': goto yy13;
+ default: goto yy6;
+ }
+yy13:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'r': goto yy14;
+ default: goto yy6;
+ }
+yy14:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy15;
+ default: goto yy6;
+ }
+yy15:
+ YYBACKUPCTX ();
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '[': goto yy16;
+ default: goto yy6;
+ }
+yy16:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ default: goto yy6;
+ }
+yy17:
+ YYSKIP ();
+ if (YYHAS (1)) YYFILL(1);
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ case ']': goto yy19;
+ default: goto yy6;
+ }
+yy19:
+ YYSKIP ();
+ YYRESTORECTX ();
+ YYSKIP ();
+#line 15 "input_custom_default.--input(custom).re"
+ { return true; }
+#line 156 "<stdout>"
+}
+#line 17 "input_custom_default.--input(custom).re"
+
+}
+
+int main ()
+{
+ char buffer [] = "int buffer [1024]";
+ return !lex (buffer, buffer + sizeof (buffer));
+}
--- /dev/null
+bool lex (const char * cursor, const char * const limit)
+{
+ const char * marker;
+ const char * ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() *cursor
+# define YYSKIP() ++cursor
+# define YYBACKUP() marker = cursor
+# define YYBACKUPCTX() ctxmarker = cursor
+# define YYRESTORE() cursor = marker
+# define YYRESTORECTX() cursor = ctxmarker
+# define YYHAS(n) limit - cursor < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ char buffer [] = "int buffer [1024]";
+ return !lex (buffer, buffer + sizeof (buffer));
+}
--- /dev/null
+/* Generated by re2c */
+#line 1 "input_custom_fgetc.--input(custom).re"
+#include <stdio.h>
+
+char peek (FILE * f)
+{
+ char c = fgetc (f);
+ ungetc (c, f);
+ return c;
+}
+
+bool lex (FILE * f, const long limit)
+{
+ long marker;
+ long ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() peek (f)
+# define YYSKIP() fgetc (f)
+# define YYBACKUP() marker = ftell (f)
+# define YYBACKUPCTX() ctxmarker = ftell (f)
+# define YYRESTORE() fseek (f, marker, SEEK_SET)
+# define YYRESTORECTX() fseek (f, ctxmarker, SEEK_SET)
+# define YYHAS(n) limit - ftell (f) < n
+# define YYFILL(n) {}
+
+#line 27 "<stdout>"
+{
+ YYCTYPE yych;
+
+ if (YYHAS (13)) YYFILL(13);
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'i': goto yy4;
+ default: goto yy2;
+ }
+yy2:
+ YYSKIP ();
+yy3:
+#line 25 "input_custom_fgetc.--input(custom).re"
+ { return false; }
+#line 42 "<stdout>"
+yy4:
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'n': goto yy5;
+ default: goto yy3;
+ }
+yy5:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 't': goto yy7;
+ default: goto yy6;
+ }
+yy6:
+ YYRESTORE ();
+ goto yy3;
+yy7:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy8;
+ default: goto yy6;
+ }
+yy8:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'b': goto yy9;
+ default: goto yy6;
+ }
+yy9:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'u': goto yy10;
+ default: goto yy6;
+ }
+yy10:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy11;
+ default: goto yy6;
+ }
+yy11:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy12;
+ default: goto yy6;
+ }
+yy12:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'e': goto yy13;
+ default: goto yy6;
+ }
+yy13:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'r': goto yy14;
+ default: goto yy6;
+ }
+yy14:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy15;
+ default: goto yy6;
+ }
+yy15:
+ YYBACKUPCTX ();
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '[': goto yy16;
+ default: goto yy6;
+ }
+yy16:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ default: goto yy6;
+ }
+yy17:
+ YYSKIP ();
+ if (YYHAS (1)) YYFILL(1);
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ case ']': goto yy19;
+ default: goto yy6;
+ }
+yy19:
+ YYSKIP ();
+ YYRESTORECTX ();
+ YYSKIP ();
+#line 24 "input_custom_fgetc.--input(custom).re"
+ { return true; }
+#line 165 "<stdout>"
+}
+#line 26 "input_custom_fgetc.--input(custom).re"
+
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ const char fn [] = "input.txt";
+
+ FILE * f = fopen (fn, "w");
+ fwrite (buffer, 1, sizeof (buffer), f);
+ fclose (f);
+
+ f = fopen (fn, "rb");
+ int result = !lex (f, sizeof (buffer));
+ fclose (f);
+
+ return result;
+}
--- /dev/null
+#include <stdio.h>
+
+char peek (FILE * f)
+{
+ char c = fgetc (f);
+ ungetc (c, f);
+ return c;
+}
+
+bool lex (FILE * f, const long limit)
+{
+ long marker;
+ long ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() peek (f)
+# define YYSKIP() fgetc (f)
+# define YYBACKUP() marker = ftell (f)
+# define YYBACKUPCTX() ctxmarker = ftell (f)
+# define YYRESTORE() fseek (f, marker, SEEK_SET)
+# define YYRESTORECTX() fseek (f, ctxmarker, SEEK_SET)
+# define YYHAS(n) limit - ftell (f) < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ const char fn [] = "input.txt";
+
+ FILE * f = fopen (fn, "w");
+ fwrite (buffer, 1, sizeof (buffer), f);
+ fclose (f);
+
+ f = fopen (fn, "rb");
+ int result = !lex (f, sizeof (buffer));
+ fclose (f);
+
+ return result;
+}
--- /dev/null
+/* Generated by re2c */
+#line 1 "input_custom_istringstream.--input(custom).re"
+#include <sstream>
+
+bool lex (std::istringstream & is, const std::streampos limit)
+{
+ std::streampos marker;
+ std::streampos ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() is.peek ()
+# define YYSKIP() is.ignore ()
+# define YYBACKUP() marker = is.tellg ()
+# define YYBACKUPCTX() ctxmarker = is.tellg ()
+# define YYRESTORE() is.seekg (marker)
+# define YYRESTORECTX() is.seekg (ctxmarker)
+# define YYHAS(n) limit - is.tellg () < n
+# define YYFILL(n) {}
+
+#line 20 "<stdout>"
+{
+ YYCTYPE yych;
+
+ if (YYHAS (13)) YYFILL(13);
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'i': goto yy4;
+ default: goto yy2;
+ }
+yy2:
+ YYSKIP ();
+yy3:
+#line 18 "input_custom_istringstream.--input(custom).re"
+ { return false; }
+#line 35 "<stdout>"
+yy4:
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'n': goto yy5;
+ default: goto yy3;
+ }
+yy5:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 't': goto yy7;
+ default: goto yy6;
+ }
+yy6:
+ YYRESTORE ();
+ goto yy3;
+yy7:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy8;
+ default: goto yy6;
+ }
+yy8:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'b': goto yy9;
+ default: goto yy6;
+ }
+yy9:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'u': goto yy10;
+ default: goto yy6;
+ }
+yy10:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy11;
+ default: goto yy6;
+ }
+yy11:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'f': goto yy12;
+ default: goto yy6;
+ }
+yy12:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'e': goto yy13;
+ default: goto yy6;
+ }
+yy13:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'r': goto yy14;
+ default: goto yy6;
+ }
+yy14:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case ' ': goto yy15;
+ default: goto yy6;
+ }
+yy15:
+ YYBACKUPCTX ();
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '[': goto yy16;
+ default: goto yy6;
+ }
+yy16:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ default: goto yy6;
+ }
+yy17:
+ YYSKIP ();
+ if (YYHAS (1)) YYFILL(1);
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy17;
+ case ']': goto yy19;
+ default: goto yy6;
+ }
+yy19:
+ YYSKIP ();
+ YYRESTORECTX ();
+ YYSKIP ();
+#line 17 "input_custom_istringstream.--input(custom).re"
+ { return true; }
+#line 158 "<stdout>"
+}
+#line 19 "input_custom_istringstream.--input(custom).re"
+
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ std::istringstream is (buffer);
+ return !lex (is, sizeof (buffer));
+}
--- /dev/null
+#include <sstream>
+
+bool lex (std::istringstream & is, const std::streampos limit)
+{
+ std::streampos marker;
+ std::streampos ctxmarker;
+# define YYCTYPE char
+# define YYPEEK() is.peek ()
+# define YYSKIP() is.ignore ()
+# define YYBACKUP() marker = is.tellg ()
+# define YYBACKUPCTX() ctxmarker = is.tellg ()
+# define YYRESTORE() is.seekg (marker)
+# define YYRESTORECTX() is.seekg (ctxmarker)
+# define YYHAS(n) limit - is.tellg () < n
+# define YYFILL(n) {}
+ /*!re2c
+ "int buffer " / "[" [0-9]+ "]" { return true; }
+ * { return false; }
+ */
+}
+
+int main ()
+{
+ const char buffer [] = "int buffer [1024]";
+ std::istringstream is (buffer);
+ return !lex (is, sizeof (buffer));
+}
--- /dev/null
+/* Generated by re2c */
+#line 1 "input_custom_mjson.--input(custom).re"
+#include <assert.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+/**
+ * mjson - modified json parser
+ * syntax changes:
+ * - no {} needed around the whole file
+ * - "=" is allowed instead of ":"
+ * - quotes around the key are optional
+ * - commas after values are optional
+ * - and c-style comments allowed
+ *
+ * intermediate storage is based on ideas from BJSON specification: http://bjson.org
+ *
+ * some code ideas are borrowed from another json parser: https://github.com/megous/sjson
+ */
+
+#ifndef __MJSON_H_INCLUDED__
+#define __MJSON_H_INCLUDED__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct _mjson_entry_t;
+
+typedef const struct _mjson_entry_t* mjson_element_t;
+
+enum mjson_element_id_t
+{
+ MJSON_ID_NULL = 0,
+ MJSON_ID_FALSE = 1,
+ MJSON_ID_EMPTY_STRING = 2,
+ MJSON_ID_TRUE = 3,
+
+ MJSON_ID_UINT32 = 4,
+ MJSON_ID_UINT64 = 5,
+
+ MJSON_ID_SINT32 = 6,
+ MJSON_ID_SINT64 = 7,
+
+ MJSON_ID_FLOAT32 = 8,
+ MJSON_ID_FLOAT64 = 9,
+
+ MJSON_ID_UTF8_KEY32 = 10,
+ MJSON_ID_UTF8_KEY64 = 11,
+
+ MJSON_ID_UTF8_STRING32 = 12,
+ MJSON_ID_UTF8_STRING64 = 13,
+
+ MJSON_ID_BINARY32 = 14,
+ MJSON_ID_BINARY64 = 15,
+
+ MJSON_ID_ARRAY32 = 16,
+ MJSON_ID_ARRAY64 = 17,
+
+ MJSON_ID_DICT32 = 18,
+ MJSON_ID_DICT64 = 19
+};
+
+int mjson_parse(const char *json_data, size_t json_data_size, void* storage_buf, size_t storage_buf_size, mjson_element_t* top_element);
+
+mjson_element_t mjson_get_top_element(void* storage_buf, size_t storage_buf_size);
+
+mjson_element_t mjson_get_element_first(mjson_element_t array);
+mjson_element_t mjson_get_element_next (mjson_element_t array, mjson_element_t current_value);
+mjson_element_t mjson_get_element (mjson_element_t array, int index);
+
+mjson_element_t mjson_get_member_first(mjson_element_t dictionary, mjson_element_t* value);
+mjson_element_t mjson_get_member_next (mjson_element_t dictionary, mjson_element_t current_key, mjson_element_t* next_value);
+mjson_element_t mjson_get_member (mjson_element_t dictionary, const char* name);
+
+int mjson_get_type(mjson_element_t element);
+
+const char* mjson_get_string(mjson_element_t element, const char* fallback);
+int32_t mjson_get_int (mjson_element_t element, int32_t fallback);
+float mjson_get_float (mjson_element_t element, float fallback);
+int mjson_get_bool (mjson_element_t element, int fallback);
+int mjson_is_null (mjson_element_t element);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+enum mjson_token_t
+{
+ TOK_NONE,
+ TOK_IDENTIFIER,
+ TOK_NOESC_STRING,
+ TOK_STRING,
+ TOK_OCT_NUMBER,
+ TOK_HEX_NUMBER,
+ TOK_DEC_NUMBER,
+ TOK_FLOAT_NUMBER,
+ TOK_COMMA,
+ TOK_COLON,
+ TOK_EQUAL,
+ TOK_LEFT_BRACKET,
+ TOK_RIGHT_BRACKET,
+ TOK_LEFT_CURLY_BRACKET,
+ TOK_RIGHT_CURLY_BRACKET,
+ TOK_FALSE,
+ TOK_TRUE,
+ TOK_NULL,
+ TOK_WHITESPACE,
+ TOK_INVALID,
+ TOK_COUNT
+};
+
+struct _mjson_parser_t
+{
+ int token;
+ uint8_t* start;
+ uint8_t* next;
+ uint8_t* end;
+ uint8_t* bjson;
+ uint8_t* bjson_limit;
+};
+
+struct _mjson_entry_t
+{
+ uint32_t id;
+ union
+ {
+ uint32_t val_u32;
+ int32_t val_s32;
+ float val_f32;
+ };
+};
+
+#define RETURN_VAL_IF_FAIL(cond, val) if (!(cond)) return (val)
+#define RETURN_IF_FAIL(cond) if (!(cond)) return
+#define MAX_UTF8_CHAR_LEN 6
+#define TRUE 1
+#define FALSE 0
+
+typedef struct _mjson_parser_t mjson_parser_t;
+typedef struct _mjson_entry_t mjson_entry_t;
+
+static void* parsectx_allocate_output(mjson_parser_t* ctx, ptrdiff_t size);
+
+static void parsectx_next_token (mjson_parser_t* context);
+
+static int parse_value_list (mjson_parser_t *context);
+static int parse_key_value_pair(mjson_parser_t *context, int stop_token);
+
+static mjson_element_t next_element(mjson_element_t element);
+
+int mjson_parse(const char *json_data, size_t json_data_size, void* storage_buf, size_t storage_buf_size, const mjson_entry_t** top_element)
+{
+ uint32_t* fourcc;
+ mjson_parser_t c = {
+ TOK_NONE, 0,
+ (uint8_t*)json_data, (uint8_t*)json_data + json_data_size,
+ (uint8_t*)storage_buf, (uint8_t*)storage_buf + storage_buf_size
+ };
+ int stop_token = TOK_NONE;
+
+ *top_element = 0;
+
+ fourcc = (uint32_t*)parsectx_allocate_output(&c, (ptrdiff_t)sizeof(uint32_t));
+
+ if (!fourcc) return 0;
+
+ *fourcc = '23JB';
+
+ parsectx_next_token(&c);
+
+ if (c.token == TOK_LEFT_BRACKET)
+ {
+ parsectx_next_token(&c);
+ if (!parse_value_list(&c))
+ return 0;
+ }
+ else
+ {
+ if (c.token == TOK_LEFT_CURLY_BRACKET)
+ {
+ stop_token = TOK_RIGHT_CURLY_BRACKET;
+ parsectx_next_token(&c);
+ }
+
+ if (!parse_key_value_pair(&c, stop_token))
+ return 0;
+ }
+
+ if (c.token != TOK_NONE)
+ return 0;
+
+ *top_element = (mjson_entry_t*)(fourcc + 1);
+
+ return 1;
+}
+
+mjson_element_t mjson_get_top_element(void* storage_buf, size_t storage_buf_size)
+{
+ mjson_element_t top = (mjson_element_t)storage_buf;
+
+ RETURN_VAL_IF_FAIL(top, NULL);
+ RETURN_VAL_IF_FAIL(top->id == MJSON_ID_DICT32 || top->id == MJSON_ID_ARRAY32, NULL);
+ RETURN_VAL_IF_FAIL(top->val_u32 <= storage_buf_size, NULL);
+
+ return top;
+}
+
+mjson_element_t mjson_get_element_first(mjson_element_t array)
+{
+ RETURN_VAL_IF_FAIL(array, NULL);
+ RETURN_VAL_IF_FAIL(array->id == MJSON_ID_ARRAY32, NULL);
+
+ return array + 1;
+}
+
+mjson_element_t mjson_get_element_next(mjson_element_t array, mjson_element_t current_value)
+{
+ mjson_element_t next = NULL;
+
+ RETURN_VAL_IF_FAIL(array, NULL);
+ RETURN_VAL_IF_FAIL(current_value, NULL);
+ RETURN_VAL_IF_FAIL(array->id == MJSON_ID_ARRAY32, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)array + array->val_u32 > (uint8_t*)current_value, NULL);
+
+ next = next_element(current_value);
+
+ RETURN_VAL_IF_FAIL((uint8_t*)array + array->val_u32 > (uint8_t*)next, NULL);
+
+ return next;
+}
+
+mjson_element_t mjson_get_element(mjson_element_t array, int index)
+{
+ mjson_element_t result;
+
+ result = mjson_get_element_first(array);
+ while (result && index--)
+ result = mjson_get_element_next(array, result);
+
+ return result;
+}
+
+mjson_element_t mjson_get_member_first(mjson_element_t dictionary, mjson_element_t* value)
+{
+ RETURN_VAL_IF_FAIL(dictionary, NULL);
+ RETURN_VAL_IF_FAIL(dictionary->id == MJSON_ID_DICT32, NULL);
+ RETURN_VAL_IF_FAIL((dictionary+1)->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ *value = next_element(dictionary+1);
+
+ return dictionary + 1;
+}
+
+mjson_element_t mjson_get_member_next(mjson_element_t dictionary, mjson_element_t current_key, mjson_element_t* next_value)
+{
+ mjson_element_t next_key = NULL;
+
+ RETURN_VAL_IF_FAIL(dictionary, NULL);
+ RETURN_VAL_IF_FAIL(dictionary->id == MJSON_ID_DICT32, NULL);
+ RETURN_VAL_IF_FAIL(current_key, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)dictionary + dictionary->val_u32 > (uint8_t*)current_key, NULL);
+ RETURN_VAL_IF_FAIL(current_key->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ next_key = next_element(current_key);
+ next_key = next_element(next_key);
+
+ RETURN_VAL_IF_FAIL(next_key, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)dictionary + dictionary->val_u32 > (uint8_t*)next_key, NULL);
+ RETURN_VAL_IF_FAIL(next_key->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ *next_value = next_element(next_key);
+
+ return next_key;
+}
+
+mjson_element_t mjson_get_member(mjson_element_t dictionary, const char* name)
+{
+ mjson_element_t key, result;
+
+ key = mjson_get_member_first(dictionary, &result);
+ while (key && strncmp(name, (char*)(key+1), key->val_u32) != 0)
+ result = mjson_get_member_next(dictionary, key, &result);
+
+ return result;
+}
+
+int mjson_get_type(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, MJSON_ID_NULL);
+
+ return element->id;
+}
+
+const char* mjson_get_string(mjson_element_t element, const char* fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_UTF8_STRING32 ||
+ element->id == MJSON_ID_UTF8_KEY32,
+ fallback);
+
+ return (const char*)(element+1);
+}
+
+int32_t mjson_get_int(mjson_element_t element, int32_t fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_SINT32, fallback);
+
+ return element->val_s32;
+}
+
+float mjson_get_float(mjson_element_t element, float fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_FLOAT32, fallback);
+
+ return element->val_f32;
+}
+
+int mjson_get_bool(mjson_element_t element, int fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_TRUE || element->id == MJSON_ID_FALSE, fallback);
+
+ return element->id == MJSON_ID_TRUE;
+}
+
+int mjson_is_null(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, TRUE);
+
+ return element->id == MJSON_ID_NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// API helpers
+/////////////////////////////////////////////////////////////////////////////
+
+static size_t element_size(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, 0);
+
+ switch(element->id)
+ {
+ case MJSON_ID_NULL:
+ case MJSON_ID_FALSE:
+ case MJSON_ID_EMPTY_STRING:
+ case MJSON_ID_TRUE:
+ return sizeof(uint32_t);
+
+ case MJSON_ID_UINT32:
+ case MJSON_ID_SINT32:
+ case MJSON_ID_FLOAT32:
+ return sizeof(mjson_entry_t);
+
+ case MJSON_ID_UTF8_KEY32:
+ case MJSON_ID_UTF8_STRING32:
+ return sizeof(mjson_entry_t) + ((element->val_u32 + 1 + 3) & (~3));
+
+ case MJSON_ID_BINARY32:
+ case MJSON_ID_ARRAY32:
+ case MJSON_ID_DICT32:
+ return sizeof(mjson_entry_t) + ((element->val_u32 + 3) & (~3));
+ };
+
+ return 0;
+}
+
+static mjson_element_t next_element(mjson_element_t element)
+{
+ size_t size;
+
+ RETURN_VAL_IF_FAIL(element, 0);
+
+ size = element_size(element);
+ assert(size>0);
+
+ return (mjson_element_t)((uint8_t*)element + size);
+}
+
+static void* parsectx_reserve_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ return (ctx->bjson_limit - ctx->bjson < size) ? 0 : ctx->bjson;
+}
+
+static void parsectx_advance_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ ctx->bjson += size;
+}
+
+static void* parsectx_allocate_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ void* ptr;
+
+ if (ctx->bjson_limit - ctx->bjson < size)
+ return 0;
+
+ ptr = ctx->bjson;
+ ctx->bjson += size;
+
+ return ptr;
+}
+
+//TODO: what about 64 bit code????
+static void parsectx_align4_output(mjson_parser_t* ctx)
+{
+ ctx->bjson = (uint8_t*)(((ptrdiff_t)ctx->bjson + 3) & (~3));
+}
+
+static void unicode_cp_to_utf8(uint32_t uni_cp, uint8_t* utf8char/*[6]*/, size_t* charlen)
+{
+ uint32_t first, i;
+
+ if (uni_cp < 0x80)
+ {
+ first = 0;
+ *charlen = 1;
+ }
+ else if (uni_cp < 0x800)
+ {
+ first = 0xc0;
+ *charlen = 2;
+ }
+ else if (uni_cp < 0x10000)
+ {
+ first = 0xe0;
+ *charlen = 3;
+ }
+ else if (uni_cp < 0x200000)
+ {
+ first = 0xf0;
+ *charlen = 4;
+ }
+ else if (uni_cp < 0x4000000)
+ {
+ first = 0xf8;
+ *charlen = 5;
+ }
+ else
+ {
+ first = 0xfc;
+ *charlen = 6;
+ }
+
+ for (i = *charlen - 1; i > 0; --i)
+ {
+ utf8char[i] = (uni_cp & 0x3f) | 0x80;
+ uni_cp >>= 6;
+ }
+ utf8char[0] = uni_cp | first;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Lexer+Parser code
+/////////////////////////////////////////////////////////////////////////////
+
+#line 491 "input_custom_mjson.--input(custom).re"
+
+
+static void parsectx_next_token(mjson_parser_t* context)
+{
+#define YYCTYPE uint8_t
+#define YYPEEK() (c>=e?0:*c)
+#define YYSKIP() ++c
+#define YYBACKUP() m = c
+#define YYRESTORE() c = m
+
+ uint8_t* c = context->next;
+ uint8_t* e = context->end;
+ uint8_t* m = NULL;
+ uint8_t* s;
+ int token = TOK_NONE;
+
+ assert(context);
+ RETURN_IF_FAIL(context->next != NULL);
+
+ while (TRUE)
+ {
+ s = c;
+
+
+#line 491 "<stdout>"
+ {
+ YYCTYPE yych;
+ unsigned int yyaccept = 0;
+
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy31;
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ': goto yy2;
+ case '"': goto yy30;
+ case '+':
+ case '-': goto yy22;
+ case ',': goto yy18;
+ case '.': goto yy24;
+ case '/': goto yy4;
+ case '0': goto yy20;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy23;
+ case ':': goto yy14;
+ case '=': goto yy16;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy29;
+ case '[': goto yy10;
+ case ']': goto yy12;
+ case 'f': goto yy27;
+ case 'n': goto yy28;
+ case 't': goto yy25;
+ case '{': goto yy6;
+ case '}': goto yy8;
+ default: goto yy33;
+ }
+yy2:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy126;
+yy3:
+#line 515 "input_custom_mjson.--input(custom).re"
+ {
+ continue;
+ }
+#line 589 "<stdout>"
+yy4:
+ yyaccept = 0;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '*': goto yy108;
+ case '/': goto yy110;
+ default: goto yy5;
+ }
+yy5:
+#line 622 "input_custom_mjson.--input(custom).re"
+ {
+ context->token = TOK_INVALID;
+ return;
+ }
+#line 606 "<stdout>"
+yy6:
+ YYSKIP ();
+#line 527 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_LEFT_CURLY_BRACKET;
+ goto done;
+ }
+#line 614 "<stdout>"
+yy8:
+ YYSKIP ();
+#line 532 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_RIGHT_CURLY_BRACKET;
+ goto done;
+ }
+#line 622 "<stdout>"
+yy10:
+ YYSKIP ();
+#line 537 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_LEFT_BRACKET;
+ goto done;
+ }
+#line 630 "<stdout>"
+yy12:
+ YYSKIP ();
+#line 542 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_RIGHT_BRACKET;
+ goto done;
+ }
+#line 638 "<stdout>"
+yy14:
+ YYSKIP ();
+#line 547 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_COLON;
+ goto done;
+ }
+#line 646 "<stdout>"
+yy16:
+ YYSKIP ();
+#line 552 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_EQUAL;
+ goto done;
+ }
+#line 654 "<stdout>"
+yy18:
+ YYSKIP ();
+#line 557 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_COMMA;
+ goto done;
+ }
+#line 662 "<stdout>"
+yy20:
+ YYSKIP ();
+ switch ((yych = YYPEEK ())) {
+ case '.':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'y':
+ case 'z': goto yy100;
+ case 'X':
+ case 'x': goto yy104;
+ default: goto yy21;
+ }
+yy21:
+#line 572 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_DEC_NUMBER;
+ goto done;
+ }
+#line 738 "<stdout>"
+yy22:
+ yyaccept = 0;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '.': goto yy95;
+ case '0': goto yy92;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy93;
+ default: goto yy5;
+ }
+yy23:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy71;
+yy24:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy63;
+ default: goto yy5;
+ }
+yy25:
+ YYSKIP ();
+ switch ((yych = YYPEEK ())) {
+ case 'r': goto yy59;
+ default: goto yy49;
+ }
+yy26:
+#line 597 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_IDENTIFIER;
+ goto done;
+ }
+#line 790 "<stdout>"
+yy27:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'a': goto yy54;
+ default: goto yy49;
+ }
+yy28:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'u': goto yy50;
+ default: goto yy49;
+ }
+yy29:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy49;
+yy30:
+ yyaccept = 0;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ if (yych <= 0x00) goto yy5;
+ goto yy35;
+yy31:
+ YYSKIP ();
+#line 612 "input_custom_mjson.--input(custom).re"
+ {
+ context->token = TOK_NONE;
+ return;
+ }
+#line 823 "<stdout>"
+yy33:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy5;
+yy34:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy35:
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '"': goto yy38;
+ case '\\': goto yy37;
+ default: goto yy34;
+ }
+yy36:
+ YYRESTORE ();
+ switch (yyaccept) {
+ case 0: goto yy5;
+ case 1: goto yy65;
+ case 2: goto yy74;
+ case 3: goto yy21;
+ default: goto yy120;
+ }
+yy37:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '"':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't': goto yy41;
+ case 'u': goto yy40;
+ default: goto yy36;
+ }
+yy38:
+ YYSKIP ();
+#line 602 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_NOESC_STRING;
+ goto done;
+ }
+#line 869 "<stdout>"
+yy40:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy45;
+ default: goto yy36;
+ }
+yy41:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '"': goto yy43;
+ case '\\': goto yy37;
+ default: goto yy41;
+ }
+yy43:
+ YYSKIP ();
+#line 607 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_STRING;
+ goto done;
+ }
+#line 914 "<stdout>"
+yy45:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy46;
+ default: goto yy36;
+ }
+yy46:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy47;
+ default: goto yy36;
+ }
+yy47:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy41;
+ default: goto yy36;
+ }
+yy48:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy49:
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy48;
+ default: goto yy26;
+ }
+yy50:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'l': goto yy51;
+ default: goto yy49;
+ }
+yy51:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'l': goto yy52;
+ default: goto yy49;
+ }
+yy52:
+ YYSKIP ();
+ switch ((yych = YYPEEK ())) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy48;
+ default: goto yy53;
+ }
+yy53:
+#line 592 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_NULL;
+ goto done;
+ }
+#line 1157 "<stdout>"
+yy54:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'l': goto yy55;
+ default: goto yy49;
+ }
+yy55:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 's': goto yy56;
+ default: goto yy49;
+ }
+yy56:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'e': goto yy57;
+ default: goto yy49;
+ }
+yy57:
+ YYSKIP ();
+ switch ((yych = YYPEEK ())) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy48;
+ default: goto yy58;
+ }
+yy58:
+#line 587 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_FALSE;
+ goto done;
+ }
+#line 1253 "<stdout>"
+yy59:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'u': goto yy60;
+ default: goto yy49;
+ }
+yy60:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'e': goto yy61;
+ default: goto yy49;
+ }
+yy61:
+ YYSKIP ();
+ switch ((yych = YYPEEK ())) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy48;
+ default: goto yy62;
+ }
+yy62:
+#line 582 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_TRUE;
+ goto done;
+ }
+#line 1342 "<stdout>"
+yy63:
+ yyaccept = 1;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy63;
+ case 'E':
+ case 'e': goto yy66;
+ default: goto yy65;
+ }
+yy65:
+#line 577 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_FLOAT_NUMBER;
+ goto done;
+ }
+#line 1369 "<stdout>"
+yy66:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '+':
+ case '-': goto yy67;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy68;
+ default: goto yy36;
+ }
+yy67:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy68;
+ default: goto yy36;
+ }
+yy68:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy68;
+ default: goto yy65;
+ }
+yy70:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy71:
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy70;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ case 'E':
+ case 'e': goto yy75;
+ default: goto yy21;
+ }
+yy72:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ default: goto yy74;
+ }
+yy74:
+#line 617 "input_custom_mjson.--input(custom).re"
+ {
+ context->token = TOK_INVALID;
+ return;
+ }
+#line 1566 "<stdout>"
+yy75:
+ yyaccept = 2;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '+':
+ case '-': goto yy87;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy88;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ default: goto yy74;
+ }
+yy76:
+ yyaccept = 1;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 'E':
+ case 'e': goto yy79;
+ default: goto yy78;
+ }
+yy77:
+ yyaccept = 1;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+yy78:
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy77;
+ case 'E':
+ case 'e': goto yy83;
+ default: goto yy65;
+ }
+yy79:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '+':
+ case '-': goto yy80;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy81;
+ default: goto yy36;
+ }
+yy80:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy81;
+ default: goto yy36;
+ }
+yy81:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy81;
+ default: goto yy65;
+ }
+yy83:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '+':
+ case '-': goto yy84;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy85;
+ default: goto yy36;
+ }
+yy84:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy85;
+ default: goto yy36;
+ }
+yy85:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy85;
+ default: goto yy65;
+ }
+yy87:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy90;
+ default: goto yy36;
+ }
+yy88:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy88;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ default: goto yy65;
+ }
+yy90:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy90;
+ default: goto yy65;
+ }
+yy92:
+ yyaccept = 3;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy97;
+ case 'E':
+ case 'e': goto yy96;
+ default: goto yy21;
+ }
+yy93:
+ yyaccept = 3;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy93;
+ case 'E':
+ case 'e': goto yy96;
+ default: goto yy21;
+ }
+yy95:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy63;
+ default: goto yy36;
+ }
+yy96:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '+':
+ case '-': goto yy87;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy90;
+ default: goto yy36;
+ }
+yy97:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy97;
+ case 'E':
+ case 'e': goto yy96;
+ default: goto yy36;
+ }
+yy99:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy100:
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy99;
+ case '8':
+ case '9': goto yy102;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ case 'E':
+ case 'e': goto yy75;
+ default: goto yy101;
+ }
+yy101:
+#line 562 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_OCT_NUMBER;
+ goto done;
+ }
+#line 2044 "<stdout>"
+yy102:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '.': goto yy76;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy102;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ case 'E':
+ case 'e': goto yy75;
+ default: goto yy74;
+ }
+yy104:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy106;
+ default: goto yy74;
+ }
+yy105:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy106:
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy105;
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '_':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z': goto yy72;
+ default: goto yy107;
+ }
+yy107:
+#line 567 "input_custom_mjson.--input(custom).re"
+ {
+ token = TOK_HEX_NUMBER;
+ goto done;
+ }
+#line 2260 "<stdout>"
+yy108:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '*': goto yy114;
+ default: goto yy108;
+ }
+yy110:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '\n': goto yy112;
+ default: goto yy110;
+ }
+yy112:
+ YYSKIP ();
+#line 519 "input_custom_mjson.--input(custom).re"
+ {
+ continue;
+ }
+#line 2283 "<stdout>"
+yy114:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '*': goto yy117;
+ case '/': goto yy119;
+ default: goto yy116;
+ }
+yy115:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy116:
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '*': goto yy122;
+ default: goto yy115;
+ }
+yy117:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '*': goto yy117;
+ case '/': goto yy121;
+ default: goto yy115;
+ }
+yy119:
+ YYSKIP ();
+yy120:
+#line 523 "input_custom_mjson.--input(custom).re"
+ {
+ continue;
+ }
+#line 2317 "<stdout>"
+yy121:
+ yyaccept = 4;
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy120;
+ case '*': goto yy122;
+ default: goto yy115;
+ }
+yy122:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '*': goto yy123;
+ case '/': goto yy119;
+ default: goto yy115;
+ }
+yy123:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '*': goto yy123;
+ case '/': goto yy121;
+ default: goto yy115;
+ }
+yy125:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy126:
+ switch (yych) {
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ': goto yy125;
+ default: goto yy3;
+ }
+ }
+#line 626 "input_custom_mjson.--input(custom).re"
+
+ }
+
+done:
+ context->token = token;
+ context->start = s;
+ context->next = c;
+
+#undef YYREADINPUT
+#undef YYCTYPE
+#undef YYCURSOR
+#undef YYMARKER
+}
+
+static int parse_number(mjson_parser_t *context)
+{
+ int num_parsed;
+ uint8_t bjson_id;
+ const char* format;
+ mjson_entry_t* bdata;
+
+ switch(context->token)
+ {
+ case TOK_OCT_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%o";
+ break;
+ case TOK_HEX_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%x";
+ break;
+ case TOK_DEC_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%d";
+ break;
+ case TOK_FLOAT_NUMBER:
+ bjson_id = MJSON_ID_FLOAT32;
+ format = "%f";
+ break;
+ default:
+ assert(!"unknown token");
+ }
+
+ bdata = (mjson_entry_t*)parsectx_allocate_output(context, (ptrdiff_t)sizeof(mjson_entry_t));
+
+ if (!bdata) return 0;
+
+ bdata->id = bjson_id;
+ num_parsed = sscanf((char*)context->start, format, &bdata->val_u32);
+ assert(num_parsed == 1);
+
+ parsectx_next_token(context);
+ return 1;
+}
+
+static int parse_string(mjson_parser_t *context, uint32_t id)
+{
+#define YYREADINPUT(c) (c>=e?0:*c)
+#define YYCTYPE uint8_t
+#define YYCURSOR c
+#define YYMARKER m
+
+ uint8_t* c = context->start+1;
+ uint8_t* e = context->next;
+ uint8_t* m = NULL;
+ uint8_t* s;
+
+ mjson_entry_t* bdata;
+ uint32_t ch = 0;
+ uint8_t* str_dst;
+ const uint8_t* str_src;
+ ptrdiff_t str_len;
+ size_t len;
+ int num_parsed;
+
+ assert(
+ context->token == TOK_STRING ||
+ context->token == TOK_NOESC_STRING ||
+ context->token == TOK_IDENTIFIER
+ );
+
+ bdata = (mjson_entry_t*)parsectx_allocate_output(context, (ptrdiff_t)sizeof(mjson_entry_t));
+
+ if (!bdata) return 0;
+
+ bdata->id = id;
+
+ if (context->token != TOK_STRING)
+ {
+ str_src = context->start;
+ str_len = context->next - context->start;
+
+ if (context->token==TOK_NOESC_STRING)
+ {
+ str_src += 1;
+ str_len -= 2;
+ }
+
+ bdata->val_u32 = str_len;
+
+ str_dst = (uint8_t*)parsectx_allocate_output(context, str_len + 1);
+
+ if (!str_dst) return 0;
+
+ memcpy(str_dst, str_src, str_len);
+ str_dst[str_len] = 0;
+
+ parsectx_align4_output(context);
+
+ parsectx_next_token(context);
+
+ return 1;
+ }
+
+ while (TRUE)
+ {
+ s = c;
+
+
+#line 2478 "<stdout>"
+ {
+ YYCTYPE yych;
+ yych = YYPEEK ();
+ switch (yych) {
+ case 0x00: goto yy135;
+ case '"': goto yy133;
+ case '\\': goto yy131;
+ default: goto yy129;
+ }
+yy129:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy146;
+yy130:
+#line 745 "input_custom_mjson.--input(custom).re"
+ {
+ str_dst = (uint8_t*)parsectx_allocate_output(context, c - s);
+
+ if (!str_dst) return 0;
+
+ memcpy(str_dst, s, c - s);
+
+ continue;
+ }
+#line 2503 "<stdout>"
+yy131:
+ YYSKIP ();
+ YYBACKUP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '"':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't': goto yy138;
+ case 'u': goto yy136;
+ default: goto yy132;
+ }
+yy132:
+#line 810 "input_custom_mjson.--input(custom).re"
+ {
+ assert(!"reachable");
+ }
+#line 2525 "<stdout>"
+yy133:
+ YYSKIP ();
+#line 801 "input_custom_mjson.--input(custom).re"
+ {
+ bdata->val_u32 = context->bjson - (uint8_t*)(bdata + 1);
+ *context->bjson++ = 0;
+ parsectx_align4_output(context);
+ parsectx_next_token(context);
+
+ return 1;
+ }
+#line 2537 "<stdout>"
+yy135:
+ YYSKIP ();
+ yych = YYPEEK ();
+ goto yy132;
+yy136:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy140;
+ default: goto yy137;
+ }
+yy137:
+ YYRESTORE ();
+ goto yy132;
+yy138:
+ YYSKIP ();
+#line 756 "input_custom_mjson.--input(custom).re"
+ {
+ char decoded = s[1];
+
+ switch (s[1])
+ {
+ case 'b':
+ decoded = '\b';
+ break;
+ case 'n':
+ decoded = '\n';
+ break;
+ case 'r':
+ decoded = '\r';
+ break;
+ case 't':
+ decoded = '\t';
+ break;
+ case 'f':
+ decoded = '\f';
+ break;
+ }
+
+ str_dst = (uint8_t*)parsectx_allocate_output(context, 1);
+
+ if (!str_dst) return 0;
+
+ *str_dst = decoded;
+
+ continue;
+ }
+#line 2606 "<stdout>"
+yy140:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy141;
+ default: goto yy137;
+ }
+yy141:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy142;
+ default: goto yy137;
+ }
+yy142:
+ YYSKIP ();
+ yych = YYPEEK ();
+ switch (yych) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy143;
+ default: goto yy137;
+ }
+yy143:
+ YYSKIP ();
+#line 787 "input_custom_mjson.--input(custom).re"
+ {
+ str_dst = (uint8_t*)parsectx_reserve_output(context, 6);
+
+ if (!str_dst) return 0;
+
+ num_parsed = sscanf((char*)(s + 2), "%4x", &ch);
+ assert(num_parsed == 1);
+ unicode_cp_to_utf8(ch, str_dst, &len);
+
+ parsectx_advance_output(context, len);
+
+ continue;
+ }
+#line 2707 "<stdout>"
+yy145:
+ YYSKIP ();
+ yych = YYPEEK ();
+yy146:
+ switch (yych) {
+ case 0x00:
+ case '"':
+ case '\\': goto yy130;
+ default: goto yy145;
+ }
+ }
+#line 813 "input_custom_mjson.--input(custom).re"
+
+ }
+
+#undef YYREADINPUT
+#undef YYCTYPE
+#undef YYCURSOR
+#undef YYMARKER
+
+ assert(!"reachable");
+ return 0;
+}
+
+static int parse_simple(mjson_parser_t *context)
+{
+ uint32_t* id;
+
+ assert(
+ context->token == TOK_NULL ||
+ context->token == TOK_FALSE ||
+ context->token == TOK_TRUE
+ );
+
+ id = (uint32_t*)parsectx_allocate_output(context, sizeof(uint32_t));
+ if (!id) return 0;
+
+ switch (context->token)
+ {
+ case TOK_NULL:
+ *id = MJSON_ID_NULL;
+ break;
+ case TOK_FALSE:
+ *id = MJSON_ID_FALSE;
+ break;
+ case TOK_TRUE:
+ *id = MJSON_ID_TRUE;
+ break;
+ }
+
+ parsectx_next_token(context);
+ return 1;
+}
+
+static int parse_value(mjson_parser_t *context)
+{
+ assert(context);
+
+ switch (context->token)
+ {
+ case TOK_NULL:
+ case TOK_FALSE:
+ case TOK_TRUE:
+ return parse_simple(context);
+
+ case TOK_OCT_NUMBER:
+ case TOK_HEX_NUMBER:
+ case TOK_DEC_NUMBER:
+ case TOK_FLOAT_NUMBER:
+ return parse_number(context);
+
+ case TOK_NOESC_STRING:
+ case TOK_STRING:
+ return parse_string(context, MJSON_ID_UTF8_STRING32);
+
+ case TOK_LEFT_CURLY_BRACKET:
+ parsectx_next_token(context);
+ return parse_key_value_pair(context, TOK_RIGHT_CURLY_BRACKET);
+
+ case TOK_LEFT_BRACKET:
+ parsectx_next_token(context);
+ return parse_value_list(context);
+ }
+
+ return 0;
+}
+
+static int parse_value_list(mjson_parser_t *context)
+{
+ mjson_entry_t* array;
+ uint8_t* data_start;
+ int expect_separator;
+
+ assert(context);
+
+ array = (mjson_entry_t*)parsectx_allocate_output(context, sizeof(mjson_entry_t));
+
+ if (!array) return 0;
+
+ array->id = MJSON_ID_ARRAY32;
+ data_start = context->bjson;
+
+ expect_separator = FALSE;
+
+ while (context->token != TOK_RIGHT_BRACKET)
+ {
+ if (expect_separator && context->token == TOK_COMMA)
+ parsectx_next_token(context);
+ else
+ expect_separator = TRUE;
+
+ if (!parse_value(context))
+ return 0;
+ }
+
+ array->val_u32 = context->bjson - data_start;
+
+ assert((array->val_u32 & 3) == 0);
+
+ parsectx_next_token(context);
+
+ return 1;
+}
+
+static int parse_key_value_pair(mjson_parser_t* context, int stop_token)
+{
+ mjson_entry_t* dictionary;
+ uint8_t* data_start;
+ int expect_separator;
+
+ assert(context);
+
+ dictionary = (mjson_entry_t*)parsectx_allocate_output(context, sizeof(mjson_entry_t));
+
+ if (!dictionary) return 0;
+
+ dictionary->id = MJSON_ID_DICT32;
+ data_start = context->bjson;
+
+ expect_separator = FALSE;
+ while (context->token != stop_token)
+ {
+ if (expect_separator && context->token == TOK_COMMA)
+ parsectx_next_token(context);
+ else
+ expect_separator = TRUE;
+
+ switch (context->token)
+ {
+ case TOK_IDENTIFIER:
+ case TOK_NOESC_STRING:
+ if (!parse_string(context, MJSON_ID_UTF8_KEY32))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ if (context->token != TOK_COLON && context->token != TOK_EQUAL)
+ return 0;
+
+ parsectx_next_token(context);
+
+ if (!parse_value(context))
+ return 0;
+ }
+
+ dictionary->val_u32 = context->bjson - data_start;
+
+ assert((dictionary->val_u32 & 3) == 0);
+
+ parsectx_next_token(context);
+
+ return 1;
+}
--- /dev/null
+#include <assert.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+/**
+ * mjson - modified json parser
+ * syntax changes:
+ * - no {} needed around the whole file
+ * - "=" is allowed instead of ":"
+ * - quotes around the key are optional
+ * - commas after values are optional
+ * - and c-style comments allowed
+ *
+ * intermediate storage is based on ideas from BJSON specification: http://bjson.org
+ *
+ * some code ideas are borrowed from another json parser: https://github.com/megous/sjson
+ */
+
+#ifndef __MJSON_H_INCLUDED__
+#define __MJSON_H_INCLUDED__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct _mjson_entry_t;
+
+typedef const struct _mjson_entry_t* mjson_element_t;
+
+enum mjson_element_id_t
+{
+ MJSON_ID_NULL = 0,
+ MJSON_ID_FALSE = 1,
+ MJSON_ID_EMPTY_STRING = 2,
+ MJSON_ID_TRUE = 3,
+
+ MJSON_ID_UINT32 = 4,
+ MJSON_ID_UINT64 = 5,
+
+ MJSON_ID_SINT32 = 6,
+ MJSON_ID_SINT64 = 7,
+
+ MJSON_ID_FLOAT32 = 8,
+ MJSON_ID_FLOAT64 = 9,
+
+ MJSON_ID_UTF8_KEY32 = 10,
+ MJSON_ID_UTF8_KEY64 = 11,
+
+ MJSON_ID_UTF8_STRING32 = 12,
+ MJSON_ID_UTF8_STRING64 = 13,
+
+ MJSON_ID_BINARY32 = 14,
+ MJSON_ID_BINARY64 = 15,
+
+ MJSON_ID_ARRAY32 = 16,
+ MJSON_ID_ARRAY64 = 17,
+
+ MJSON_ID_DICT32 = 18,
+ MJSON_ID_DICT64 = 19
+};
+
+int mjson_parse(const char *json_data, size_t json_data_size, void* storage_buf, size_t storage_buf_size, mjson_element_t* top_element);
+
+mjson_element_t mjson_get_top_element(void* storage_buf, size_t storage_buf_size);
+
+mjson_element_t mjson_get_element_first(mjson_element_t array);
+mjson_element_t mjson_get_element_next (mjson_element_t array, mjson_element_t current_value);
+mjson_element_t mjson_get_element (mjson_element_t array, int index);
+
+mjson_element_t mjson_get_member_first(mjson_element_t dictionary, mjson_element_t* value);
+mjson_element_t mjson_get_member_next (mjson_element_t dictionary, mjson_element_t current_key, mjson_element_t* next_value);
+mjson_element_t mjson_get_member (mjson_element_t dictionary, const char* name);
+
+int mjson_get_type(mjson_element_t element);
+
+const char* mjson_get_string(mjson_element_t element, const char* fallback);
+int32_t mjson_get_int (mjson_element_t element, int32_t fallback);
+float mjson_get_float (mjson_element_t element, float fallback);
+int mjson_get_bool (mjson_element_t element, int fallback);
+int mjson_is_null (mjson_element_t element);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+enum mjson_token_t
+{
+ TOK_NONE,
+ TOK_IDENTIFIER,
+ TOK_NOESC_STRING,
+ TOK_STRING,
+ TOK_OCT_NUMBER,
+ TOK_HEX_NUMBER,
+ TOK_DEC_NUMBER,
+ TOK_FLOAT_NUMBER,
+ TOK_COMMA,
+ TOK_COLON,
+ TOK_EQUAL,
+ TOK_LEFT_BRACKET,
+ TOK_RIGHT_BRACKET,
+ TOK_LEFT_CURLY_BRACKET,
+ TOK_RIGHT_CURLY_BRACKET,
+ TOK_FALSE,
+ TOK_TRUE,
+ TOK_NULL,
+ TOK_WHITESPACE,
+ TOK_INVALID,
+ TOK_COUNT
+};
+
+struct _mjson_parser_t
+{
+ int token;
+ uint8_t* start;
+ uint8_t* next;
+ uint8_t* end;
+ uint8_t* bjson;
+ uint8_t* bjson_limit;
+};
+
+struct _mjson_entry_t
+{
+ uint32_t id;
+ union
+ {
+ uint32_t val_u32;
+ int32_t val_s32;
+ float val_f32;
+ };
+};
+
+#define RETURN_VAL_IF_FAIL(cond, val) if (!(cond)) return (val)
+#define RETURN_IF_FAIL(cond) if (!(cond)) return
+#define MAX_UTF8_CHAR_LEN 6
+#define TRUE 1
+#define FALSE 0
+
+typedef struct _mjson_parser_t mjson_parser_t;
+typedef struct _mjson_entry_t mjson_entry_t;
+
+static void* parsectx_allocate_output(mjson_parser_t* ctx, ptrdiff_t size);
+
+static void parsectx_next_token (mjson_parser_t* context);
+
+static int parse_value_list (mjson_parser_t *context);
+static int parse_key_value_pair(mjson_parser_t *context, int stop_token);
+
+static mjson_element_t next_element(mjson_element_t element);
+
+int mjson_parse(const char *json_data, size_t json_data_size, void* storage_buf, size_t storage_buf_size, const mjson_entry_t** top_element)
+{
+ uint32_t* fourcc;
+ mjson_parser_t c = {
+ TOK_NONE, 0,
+ (uint8_t*)json_data, (uint8_t*)json_data + json_data_size,
+ (uint8_t*)storage_buf, (uint8_t*)storage_buf + storage_buf_size
+ };
+ int stop_token = TOK_NONE;
+
+ *top_element = 0;
+
+ fourcc = (uint32_t*)parsectx_allocate_output(&c, (ptrdiff_t)sizeof(uint32_t));
+
+ if (!fourcc) return 0;
+
+ *fourcc = '23JB';
+
+ parsectx_next_token(&c);
+
+ if (c.token == TOK_LEFT_BRACKET)
+ {
+ parsectx_next_token(&c);
+ if (!parse_value_list(&c))
+ return 0;
+ }
+ else
+ {
+ if (c.token == TOK_LEFT_CURLY_BRACKET)
+ {
+ stop_token = TOK_RIGHT_CURLY_BRACKET;
+ parsectx_next_token(&c);
+ }
+
+ if (!parse_key_value_pair(&c, stop_token))
+ return 0;
+ }
+
+ if (c.token != TOK_NONE)
+ return 0;
+
+ *top_element = (mjson_entry_t*)(fourcc + 1);
+
+ return 1;
+}
+
+mjson_element_t mjson_get_top_element(void* storage_buf, size_t storage_buf_size)
+{
+ mjson_element_t top = (mjson_element_t)storage_buf;
+
+ RETURN_VAL_IF_FAIL(top, NULL);
+ RETURN_VAL_IF_FAIL(top->id == MJSON_ID_DICT32 || top->id == MJSON_ID_ARRAY32, NULL);
+ RETURN_VAL_IF_FAIL(top->val_u32 <= storage_buf_size, NULL);
+
+ return top;
+}
+
+mjson_element_t mjson_get_element_first(mjson_element_t array)
+{
+ RETURN_VAL_IF_FAIL(array, NULL);
+ RETURN_VAL_IF_FAIL(array->id == MJSON_ID_ARRAY32, NULL);
+
+ return array + 1;
+}
+
+mjson_element_t mjson_get_element_next(mjson_element_t array, mjson_element_t current_value)
+{
+ mjson_element_t next = NULL;
+
+ RETURN_VAL_IF_FAIL(array, NULL);
+ RETURN_VAL_IF_FAIL(current_value, NULL);
+ RETURN_VAL_IF_FAIL(array->id == MJSON_ID_ARRAY32, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)array + array->val_u32 > (uint8_t*)current_value, NULL);
+
+ next = next_element(current_value);
+
+ RETURN_VAL_IF_FAIL((uint8_t*)array + array->val_u32 > (uint8_t*)next, NULL);
+
+ return next;
+}
+
+mjson_element_t mjson_get_element(mjson_element_t array, int index)
+{
+ mjson_element_t result;
+
+ result = mjson_get_element_first(array);
+ while (result && index--)
+ result = mjson_get_element_next(array, result);
+
+ return result;
+}
+
+mjson_element_t mjson_get_member_first(mjson_element_t dictionary, mjson_element_t* value)
+{
+ RETURN_VAL_IF_FAIL(dictionary, NULL);
+ RETURN_VAL_IF_FAIL(dictionary->id == MJSON_ID_DICT32, NULL);
+ RETURN_VAL_IF_FAIL((dictionary+1)->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ *value = next_element(dictionary+1);
+
+ return dictionary + 1;
+}
+
+mjson_element_t mjson_get_member_next(mjson_element_t dictionary, mjson_element_t current_key, mjson_element_t* next_value)
+{
+ mjson_element_t next_key = NULL;
+
+ RETURN_VAL_IF_FAIL(dictionary, NULL);
+ RETURN_VAL_IF_FAIL(dictionary->id == MJSON_ID_DICT32, NULL);
+ RETURN_VAL_IF_FAIL(current_key, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)dictionary + dictionary->val_u32 > (uint8_t*)current_key, NULL);
+ RETURN_VAL_IF_FAIL(current_key->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ next_key = next_element(current_key);
+ next_key = next_element(next_key);
+
+ RETURN_VAL_IF_FAIL(next_key, NULL);
+ RETURN_VAL_IF_FAIL((uint8_t*)dictionary + dictionary->val_u32 > (uint8_t*)next_key, NULL);
+ RETURN_VAL_IF_FAIL(next_key->id == MJSON_ID_UTF8_KEY32, NULL);
+
+ *next_value = next_element(next_key);
+
+ return next_key;
+}
+
+mjson_element_t mjson_get_member(mjson_element_t dictionary, const char* name)
+{
+ mjson_element_t key, result;
+
+ key = mjson_get_member_first(dictionary, &result);
+ while (key && strncmp(name, (char*)(key+1), key->val_u32) != 0)
+ result = mjson_get_member_next(dictionary, key, &result);
+
+ return result;
+}
+
+int mjson_get_type(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, MJSON_ID_NULL);
+
+ return element->id;
+}
+
+const char* mjson_get_string(mjson_element_t element, const char* fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_UTF8_STRING32 ||
+ element->id == MJSON_ID_UTF8_KEY32,
+ fallback);
+
+ return (const char*)(element+1);
+}
+
+int32_t mjson_get_int(mjson_element_t element, int32_t fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_SINT32, fallback);
+
+ return element->val_s32;
+}
+
+float mjson_get_float(mjson_element_t element, float fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_FLOAT32, fallback);
+
+ return element->val_f32;
+}
+
+int mjson_get_bool(mjson_element_t element, int fallback)
+{
+ RETURN_VAL_IF_FAIL(element, fallback);
+ RETURN_VAL_IF_FAIL(element->id == MJSON_ID_TRUE || element->id == MJSON_ID_FALSE, fallback);
+
+ return element->id == MJSON_ID_TRUE;
+}
+
+int mjson_is_null(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, TRUE);
+
+ return element->id == MJSON_ID_NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// API helpers
+/////////////////////////////////////////////////////////////////////////////
+
+static size_t element_size(mjson_element_t element)
+{
+ RETURN_VAL_IF_FAIL(element, 0);
+
+ switch(element->id)
+ {
+ case MJSON_ID_NULL:
+ case MJSON_ID_FALSE:
+ case MJSON_ID_EMPTY_STRING:
+ case MJSON_ID_TRUE:
+ return sizeof(uint32_t);
+
+ case MJSON_ID_UINT32:
+ case MJSON_ID_SINT32:
+ case MJSON_ID_FLOAT32:
+ return sizeof(mjson_entry_t);
+
+ case MJSON_ID_UTF8_KEY32:
+ case MJSON_ID_UTF8_STRING32:
+ return sizeof(mjson_entry_t) + ((element->val_u32 + 1 + 3) & (~3));
+
+ case MJSON_ID_BINARY32:
+ case MJSON_ID_ARRAY32:
+ case MJSON_ID_DICT32:
+ return sizeof(mjson_entry_t) + ((element->val_u32 + 3) & (~3));
+ };
+
+ return 0;
+}
+
+static mjson_element_t next_element(mjson_element_t element)
+{
+ size_t size;
+
+ RETURN_VAL_IF_FAIL(element, 0);
+
+ size = element_size(element);
+ assert(size>0);
+
+ return (mjson_element_t)((uint8_t*)element + size);
+}
+
+static void* parsectx_reserve_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ return (ctx->bjson_limit - ctx->bjson < size) ? 0 : ctx->bjson;
+}
+
+static void parsectx_advance_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ ctx->bjson += size;
+}
+
+static void* parsectx_allocate_output(mjson_parser_t* ctx, ptrdiff_t size)
+{
+ void* ptr;
+
+ if (ctx->bjson_limit - ctx->bjson < size)
+ return 0;
+
+ ptr = ctx->bjson;
+ ctx->bjson += size;
+
+ return ptr;
+}
+
+//TODO: what about 64 bit code????
+static void parsectx_align4_output(mjson_parser_t* ctx)
+{
+ ctx->bjson = (uint8_t*)(((ptrdiff_t)ctx->bjson + 3) & (~3));
+}
+
+static void unicode_cp_to_utf8(uint32_t uni_cp, uint8_t* utf8char/*[6]*/, size_t* charlen)
+{
+ uint32_t first, i;
+
+ if (uni_cp < 0x80)
+ {
+ first = 0;
+ *charlen = 1;
+ }
+ else if (uni_cp < 0x800)
+ {
+ first = 0xc0;
+ *charlen = 2;
+ }
+ else if (uni_cp < 0x10000)
+ {
+ first = 0xe0;
+ *charlen = 3;
+ }
+ else if (uni_cp < 0x200000)
+ {
+ first = 0xf0;
+ *charlen = 4;
+ }
+ else if (uni_cp < 0x4000000)
+ {
+ first = 0xf8;
+ *charlen = 5;
+ }
+ else
+ {
+ first = 0xfc;
+ *charlen = 6;
+ }
+
+ for (i = *charlen - 1; i > 0; --i)
+ {
+ utf8char[i] = (uni_cp & 0x3f) | 0x80;
+ uni_cp >>= 6;
+ }
+ utf8char[0] = uni_cp | first;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Lexer+Parser code
+/////////////////////////////////////////////////////////////////////////////
+
+/*!re2c
+ re2c:yyfill:enable = 0;
+ re2c:indent:top = 2;
+ re2c:indent:string = " ";
+
+ WS = [ \t\n\r]+;
+
+ S = [+-];
+ O = [0-7];
+ D = [0-9];
+ H = [a-fA-F0-9];
+ L = [a-zA-Z_];
+ E = [Ee] [+-]? D+;
+
+ HEX_NUMBER = ("0" [xX] H+);
+ OCT_NUMBER = ("0" O+);
+ DEC_NUMBER = (S? ("0"|([1-9]D*)));
+
+ FLOAT_NUMBER = (S? D+ E) | (S? D* "." D+ E?) | (S? D+ "." D* E?);
+
+ CHAR = [^\\"\000];
+ CTL = "\\" ["\\/bfnrt];
+ UNICODE = "\\u" H{4};
+ STRING = "\"" (CHAR|CTL|UNICODE)* "\"";
+ NOESC_STRING = "\"" (CHAR)* "\"";
+ IDENTIFIER = L (L|D)*;
+ SINGLELINE_COMMENT = "//" [^\n\000]* "\n";
+ MULTILINE_COMMENT = "\/*" [^*\000]* [*]+ ( [^\/\000] [^*\000]* [*]+ )* "\/";
+*/
+
+static void parsectx_next_token(mjson_parser_t* context)
+{
+#define YYCTYPE uint8_t
+#define YYPEEK() (c>=e?0:*c)
+#define YYSKIP() ++c
+#define YYBACKUP() m = c
+#define YYRESTORE() c = m
+
+ uint8_t* c = context->next;
+ uint8_t* e = context->end;
+ uint8_t* m = NULL;
+ uint8_t* s;
+ int token = TOK_NONE;
+
+ assert(context);
+ RETURN_IF_FAIL(context->next != NULL);
+
+ while (TRUE)
+ {
+ s = c;
+
+/*!re2c
+ WS {
+ continue;
+ }
+
+ SINGLELINE_COMMENT {
+ continue;
+ }
+
+ MULTILINE_COMMENT {
+ continue;
+ }
+
+ "{" {
+ token = TOK_LEFT_CURLY_BRACKET;
+ goto done;
+ }
+
+ "}" {
+ token = TOK_RIGHT_CURLY_BRACKET;
+ goto done;
+ }
+
+ "[" {
+ token = TOK_LEFT_BRACKET;
+ goto done;
+ }
+
+ "]" {
+ token = TOK_RIGHT_BRACKET;
+ goto done;
+ }
+
+ ":" {
+ token = TOK_COLON;
+ goto done;
+ }
+
+ "=" {
+ token = TOK_EQUAL;
+ goto done;
+ }
+
+ "," {
+ token = TOK_COMMA;
+ goto done;
+ }
+
+ OCT_NUMBER {
+ token = TOK_OCT_NUMBER;
+ goto done;
+ }
+
+ HEX_NUMBER {
+ token = TOK_HEX_NUMBER;
+ goto done;
+ }
+
+ DEC_NUMBER {
+ token = TOK_DEC_NUMBER;
+ goto done;
+ }
+
+ FLOAT_NUMBER {
+ token = TOK_FLOAT_NUMBER;
+ goto done;
+ }
+
+ "true" {
+ token = TOK_TRUE;
+ goto done;
+ }
+
+ "false" {
+ token = TOK_FALSE;
+ goto done;
+ }
+
+ "null" {
+ token = TOK_NULL;
+ goto done;
+ }
+
+ IDENTIFIER {
+ token = TOK_IDENTIFIER;
+ goto done;
+ }
+
+ NOESC_STRING {
+ token = TOK_NOESC_STRING;
+ goto done;
+ }
+
+ STRING {
+ token = TOK_STRING;
+ goto done;
+ }
+
+ [\000] {
+ context->token = TOK_NONE;
+ return;
+ }
+
+ (L|D)+ {
+ context->token = TOK_INVALID;
+ return;
+ }
+
+ . | "\n" {
+ context->token = TOK_INVALID;
+ return;
+ }
+*/
+ }
+
+done:
+ context->token = token;
+ context->start = s;
+ context->next = c;
+
+#undef YYREADINPUT
+#undef YYCTYPE
+#undef YYCURSOR
+#undef YYMARKER
+}
+
+static int parse_number(mjson_parser_t *context)
+{
+ int num_parsed;
+ uint8_t bjson_id;
+ const char* format;
+ mjson_entry_t* bdata;
+
+ switch(context->token)
+ {
+ case TOK_OCT_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%o";
+ break;
+ case TOK_HEX_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%x";
+ break;
+ case TOK_DEC_NUMBER:
+ bjson_id = MJSON_ID_SINT32;
+ format = "%d";
+ break;
+ case TOK_FLOAT_NUMBER:
+ bjson_id = MJSON_ID_FLOAT32;
+ format = "%f";
+ break;
+ default:
+ assert(!"unknown token");
+ }
+
+ bdata = (mjson_entry_t*)parsectx_allocate_output(context, (ptrdiff_t)sizeof(mjson_entry_t));
+
+ if (!bdata) return 0;
+
+ bdata->id = bjson_id;
+ num_parsed = sscanf((char*)context->start, format, &bdata->val_u32);
+ assert(num_parsed == 1);
+
+ parsectx_next_token(context);
+ return 1;
+}
+
+static int parse_string(mjson_parser_t *context, uint32_t id)
+{
+#define YYREADINPUT(c) (c>=e?0:*c)
+#define YYCTYPE uint8_t
+#define YYCURSOR c
+#define YYMARKER m
+
+ uint8_t* c = context->start+1;
+ uint8_t* e = context->next;
+ uint8_t* m = NULL;
+ uint8_t* s;
+
+ mjson_entry_t* bdata;
+ uint32_t ch = 0;
+ uint8_t* str_dst;
+ const uint8_t* str_src;
+ ptrdiff_t str_len;
+ size_t len;
+ int num_parsed;
+
+ assert(
+ context->token == TOK_STRING ||
+ context->token == TOK_NOESC_STRING ||
+ context->token == TOK_IDENTIFIER
+ );
+
+ bdata = (mjson_entry_t*)parsectx_allocate_output(context, (ptrdiff_t)sizeof(mjson_entry_t));
+
+ if (!bdata) return 0;
+
+ bdata->id = id;
+
+ if (context->token != TOK_STRING)
+ {
+ str_src = context->start;
+ str_len = context->next - context->start;
+
+ if (context->token==TOK_NOESC_STRING)
+ {
+ str_src += 1;
+ str_len -= 2;
+ }
+
+ bdata->val_u32 = str_len;
+
+ str_dst = (uint8_t*)parsectx_allocate_output(context, str_len + 1);
+
+ if (!str_dst) return 0;
+
+ memcpy(str_dst, str_src, str_len);
+ str_dst[str_len] = 0;
+
+ parsectx_align4_output(context);
+
+ parsectx_next_token(context);
+
+ return 1;
+ }
+
+ while (TRUE)
+ {
+ s = c;
+
+/*!re2c
+ CHAR+ {
+ str_dst = (uint8_t*)parsectx_allocate_output(context, c - s);
+
+ if (!str_dst) return 0;
+
+ memcpy(str_dst, s, c - s);
+
+ continue;
+ }
+
+
+ CTL {
+ char decoded = s[1];
+
+ switch (s[1])
+ {
+ case 'b':
+ decoded = '\b';
+ break;
+ case 'n':
+ decoded = '\n';
+ break;
+ case 'r':
+ decoded = '\r';
+ break;
+ case 't':
+ decoded = '\t';
+ break;
+ case 'f':
+ decoded = '\f';
+ break;
+ }
+
+ str_dst = (uint8_t*)parsectx_allocate_output(context, 1);
+
+ if (!str_dst) return 0;
+
+ *str_dst = decoded;
+
+ continue;
+ }
+
+ UNICODE {
+ str_dst = (uint8_t*)parsectx_reserve_output(context, 6);
+
+ if (!str_dst) return 0;
+
+ num_parsed = sscanf((char*)(s + 2), "%4x", &ch);
+ assert(num_parsed == 1);
+ unicode_cp_to_utf8(ch, str_dst, &len);
+
+ parsectx_advance_output(context, len);
+
+ continue;
+ }
+
+ "\"" {
+ bdata->val_u32 = context->bjson - (uint8_t*)(bdata + 1);
+ *context->bjson++ = 0;
+ parsectx_align4_output(context);
+ parsectx_next_token(context);
+
+ return 1;
+ }
+
+ . | "\n" | [\000] {
+ assert(!"reachable");
+ }
+*/
+ }
+
+#undef YYREADINPUT
+#undef YYCTYPE
+#undef YYCURSOR
+#undef YYMARKER
+
+ assert(!"reachable");
+ return 0;
+}
+
+static int parse_simple(mjson_parser_t *context)
+{
+ uint32_t* id;
+
+ assert(
+ context->token == TOK_NULL ||
+ context->token == TOK_FALSE ||
+ context->token == TOK_TRUE
+ );
+
+ id = (uint32_t*)parsectx_allocate_output(context, sizeof(uint32_t));
+ if (!id) return 0;
+
+ switch (context->token)
+ {
+ case TOK_NULL:
+ *id = MJSON_ID_NULL;
+ break;
+ case TOK_FALSE:
+ *id = MJSON_ID_FALSE;
+ break;
+ case TOK_TRUE:
+ *id = MJSON_ID_TRUE;
+ break;
+ }
+
+ parsectx_next_token(context);
+ return 1;
+}
+
+static int parse_value(mjson_parser_t *context)
+{
+ assert(context);
+
+ switch (context->token)
+ {
+ case TOK_NULL:
+ case TOK_FALSE:
+ case TOK_TRUE:
+ return parse_simple(context);
+
+ case TOK_OCT_NUMBER:
+ case TOK_HEX_NUMBER:
+ case TOK_DEC_NUMBER:
+ case TOK_FLOAT_NUMBER:
+ return parse_number(context);
+
+ case TOK_NOESC_STRING:
+ case TOK_STRING:
+ return parse_string(context, MJSON_ID_UTF8_STRING32);
+
+ case TOK_LEFT_CURLY_BRACKET:
+ parsectx_next_token(context);
+ return parse_key_value_pair(context, TOK_RIGHT_CURLY_BRACKET);
+
+ case TOK_LEFT_BRACKET:
+ parsectx_next_token(context);
+ return parse_value_list(context);
+ }
+
+ return 0;
+}
+
+static int parse_value_list(mjson_parser_t *context)
+{
+ mjson_entry_t* array;
+ uint8_t* data_start;
+ int expect_separator;
+
+ assert(context);
+
+ array = (mjson_entry_t*)parsectx_allocate_output(context, sizeof(mjson_entry_t));
+
+ if (!array) return 0;
+
+ array->id = MJSON_ID_ARRAY32;
+ data_start = context->bjson;
+
+ expect_separator = FALSE;
+
+ while (context->token != TOK_RIGHT_BRACKET)
+ {
+ if (expect_separator && context->token == TOK_COMMA)
+ parsectx_next_token(context);
+ else
+ expect_separator = TRUE;
+
+ if (!parse_value(context))
+ return 0;
+ }
+
+ array->val_u32 = context->bjson - data_start;
+
+ assert((array->val_u32 & 3) == 0);
+
+ parsectx_next_token(context);
+
+ return 1;
+}
+
+static int parse_key_value_pair(mjson_parser_t* context, int stop_token)
+{
+ mjson_entry_t* dictionary;
+ uint8_t* data_start;
+ int expect_separator;
+
+ assert(context);
+
+ dictionary = (mjson_entry_t*)parsectx_allocate_output(context, sizeof(mjson_entry_t));
+
+ if (!dictionary) return 0;
+
+ dictionary->id = MJSON_ID_DICT32;
+ data_start = context->bjson;
+
+ expect_separator = FALSE;
+ while (context->token != stop_token)
+ {
+ if (expect_separator && context->token == TOK_COMMA)
+ parsectx_next_token(context);
+ else
+ expect_separator = TRUE;
+
+ switch (context->token)
+ {
+ case TOK_IDENTIFIER:
+ case TOK_NOESC_STRING:
+ if (!parse_string(context, MJSON_ID_UTF8_KEY32))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ if (context->token != TOK_COLON && context->token != TOK_EQUAL)
+ return 0;
+
+ parsectx_next_token(context);
+
+ if (!parse_value(context))
+ return 0;
+ }
+
+ dictionary->val_u32 = context->bjson - data_start;
+
+ assert((dictionary->val_u32 & 3) == 0);
+
+ parsectx_next_token(context);
+
+ return 1;
+}