123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170 |
- /*
- * Copyright (C) 2009-2011 Vincent Hanquez <vincent@snarc.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; version 2.1 or version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * SPDX-License-Identifier: GPL-3.0+
- * License-Filename: LICENSE
- */
- /*
- * the class, states and state transition tables has been inspired by the JSON_parser.c
- * available at http://json.org, but are quite different on the way that the
- * parser handles its parse buffer and contains significant differences that affect
- * the JSON compliance.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include "json.h"
- #ifdef _MSC_VER
- #define inline _inline
- #endif
- #ifdef TRACING_ENABLE
- #include <stdio.h>
- #define TRACING(fmt, ...) fprintf(stderr, "tracing: " fmt, ##__VA_ARGS__)
- #else
- #define TRACING(fmt, ...) ((void) 0)
- #endif
- enum classes {
- C_SPACE, /* space */
- C_NL, /* newline */
- C_WHITE, /* tab, CR */
- C_LCURB, C_RCURB, /* object opening/closing */
- C_LSQRB, C_RSQRB, /* array opening/closing */
- /* syntax symbols */
- C_COLON,
- C_COMMA,
- C_QUOTE, /* " */
- C_BACKS, /* \ */
- C_SLASH, /* / */
- C_PLUS,
- C_MINUS,
- C_DOT,
- C_ZERO, C_DIGIT, /* digits */
- C_a, C_b, C_c, C_d, C_e, C_f, C_l, C_n, C_r, C_s, C_t, C_u, /* nocaps letters */
- C_ABCDF, C_E, /* caps letters */
- C_OTHER, /* all other */
- C_STAR, /* star in C style comment */
- C_HASH, /* # for YAML comment */
- C_ERROR = 0xfe,
- };
- /* map from character < 128 to classes. from 128 to 256 all C_OTHER */
- static uint8_t character_class[128] = {
- C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
- C_ERROR, C_WHITE, C_NL, C_ERROR, C_ERROR, C_WHITE, C_ERROR, C_ERROR,
- C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
- C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
- C_SPACE, C_OTHER, C_QUOTE, C_HASH, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
- C_OTHER, C_OTHER, C_STAR, C_PLUS, C_COMMA, C_MINUS, C_DOT, C_SLASH,
- C_ZERO, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
- C_DIGIT, C_DIGIT, C_COLON, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
- C_OTHER, C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E, C_ABCDF, C_OTHER,
- C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
- C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
- C_OTHER, C_OTHER, C_OTHER, C_LSQRB, C_BACKS, C_RSQRB, C_OTHER, C_OTHER,
- C_OTHER, C_a, C_b, C_c, C_d, C_e, C_f, C_OTHER,
- C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_l, C_OTHER, C_n, C_OTHER,
- C_OTHER, C_OTHER, C_r, C_s, C_t, C_u, C_OTHER, C_OTHER,
- C_OTHER, C_OTHER, C_OTHER, C_LCURB, C_OTHER, C_RCURB, C_OTHER, C_OTHER
- };
- /* only the first 36 ascii characters need an escape */
- static char const *character_escape[] = {
- "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", /* 0-7 */
- "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", /* 8-f */
- "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", /* 10-17 */
- "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", /* 18-1f */
- "\x20", "\x21", "\\\"", "\x23", "\x24", "\x25", "\x26", "\x27", /* 20-27 */
- "\x28", "\x29", "\x2a", "\x2b", "\x2c", "\x2d", "\x2e", "\x2f", /* 28-2f */
- "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", /* 30-37 */
- "\x38", "\x39", "\x3a", "\x3b", "\x3c", "\x3d", "\x3e", "\x3f", /* 38-3f */
- "\x40", "\x41", "\x42", "\x43", "\x44", "\x45", "\x46", "\x47", /* 40-47 */
- "\x48", "\x49", "\x4a", "\x4b", "\x4c", "\x4d", "\x4e", "\x4f", /* 48-4f */
- "\x50", "\x51", "\x52", "\x53", "\x54", "\x55", "\x56", "\x57", /* 50-57 */
- "\x58", "\x59", "\x5a", "\x5b", "\\\\", "\x5d", "\x5e", "\x5f", /* 58-5f */
- "\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", /* 60-67 */
- "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", /* 68-6f */
- "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", /* 70-77 */
- "\x78", "\x79", "\x7a", "\x7b", "\x7c", "\x7d", "\x7e", "\\u007f", /* 78-7f */
- "\\u0080", "\\u0081", "\\u0082", "\\u0083", "\\u0084", "\\u0085", "\\u0086", "\\u0087", /* 80-87 */
- "\\u0088", "\\u0089", "\\u008a", "\\u008b", "\\u008c", "\\u008d", "\\u008e", "\\u008f", /* 88-8f */
- "\\u0090", "\\u0091", "\\u0092", "\\u0093", "\\u0094", "\\u0095", "\\u0096", "\\u0097", /* 90-97 */
- "\\u0098", "\\u0099", "\\u009a", "\\u009b", "\\u009c", "\\u009d", "\\u009e", "\\u009f", /* 98-9f */
- "\\u00a0", "\\u00a1", "\\u00a2", "\\u00a3", "\\u00a4", "\\u00a5", "\\u00a6", "\\u00a7", /* a0-a7 */
- "\\u00a8", "\\u00a9", "\\u00aa", "\\u00ab", "\\u00ac", "\\u00ad", "\\u00ae", "\\u00af", /* a8-af */
- "\\u00b0", "\\u00b1", "\\u00b2", "\\u00b3", "\\u00b4", "\\u00b5", "\\u00b6", "\\u00b7", /* b0-b7 */
- "\\u00b8", "\\u00b9", "\\u00ba", "\\u00bb", "\\u00bc", "\\u00bd", "\\u00be", "\\u00bf", /* b8-bf */
- "\\u00c0", "\\u00c1", "\\u00c2", "\\u00c3", "\\u00c4", "\\u00c5", "\\u00c6", "\\u00c7", /* c0-c7 */
- "\\u00c8", "\\u00c9", "\\u00ca", "\\u00cb", "\\u00cc", "\\u00cd", "\\u00ce", "\\u00cf", /* c8-cf */
- "\\u00d0", "\\u00d1", "\\u00d2", "\\u00d3", "\\u00d4", "\\u00d5", "\\u00d6", "\\u00d7", /* d0-d7 */
- "\\u00d8", "\\u00d9", "\\u00da", "\\u00db", "\\u00dc", "\\u00dd", "\\u00de", "\\u00df", /* d8-df */
- "\\u00e0", "\\u00e1", "\\u00e2", "\\u00e3", "\\u00e4", "\\u00e5", "\\u00e6", "\\u00e7", /* e0-e7 */
- "\\u00e8", "\\u00e9", "\\u00ea", "\\u00eb", "\\u00ec", "\\u00ed", "\\u00ee", "\\u00ef", /* e8-ef */
- "\\u00f0", "\\u00f1", "\\u00f2", "\\u00f3", "\\u00f4", "\\u00f5", "\\u00f6", "\\u00f7", /* f0-f7 */
- "\\u00f8", "\\u00f9", "\\u00fa", "\\u00fb", "\\u00fc", "\\u00fd", "\\u00fe", "\\u00ff", /* f8-ff */
- };
- /* define all states and actions that will be taken on each transition.
- *
- * states are defined first because of the fact they are use as index in the
- * transitions table. they usually contains either a number or a prefix _
- * for simple state like string, object, value ...
- *
- * actions are defined starting from 0x80. state error is defined as 0xff
- */
- enum states {
- STATE_GO, /* start */
- STATE_OK, /* ok */
- STATE__O, /* object */
- STATE__K, /* key */
- STATE_CO, /* colon */
- STATE__V, /* value */
- STATE__A, /* array */
- STATE__S, /* string */
- STATE_E0, /* escape */
- STATE_U1, STATE_U2, STATE_U3, STATE_U4, /* unicode states */
- STATE_M0, STATE_Z0, STATE_I0, /* number states */
- STATE_R1, STATE_R2, /* real states (after-dot digits) */
- STATE_X1, STATE_X2, STATE_X3, /* exponant states */
- STATE_T1, STATE_T2, STATE_T3, /* true constant states */
- STATE_F1, STATE_F2, STATE_F3, STATE_F4, /* false constant states */
- STATE_N1, STATE_N2, STATE_N3, /* null constant states */
- STATE_C1, STATE_C2, STATE_C3, /* C-comment states */
- STATE_Y1, /* YAML-comment state */
- STATE_D1, STATE_D2, /* multi unicode states */
- };
- /* the following are actions that need to be taken */
- enum actions {
- STATE_KS = 0x80, /* key separator */
- STATE_SP, /* comma separator */
- STATE_AB, /* array begin */
- STATE_AE, /* array ending */
- STATE_OB, /* object begin */
- STATE_OE, /* object end */
- STATE_CB, /* C-comment begin */
- STATE_YB, /* YAML-comment begin */
- STATE_CE, /* YAML/C comment end */
- STATE_FA, /* false */
- STATE_TR, /* true */
- STATE_NU, /* null */
- STATE_DE, /* double detected by exponent */
- STATE_DF, /* double detected by . */
- STATE_SE, /* string end */
- STATE_MX, /* integer detected by minus */
- STATE_ZX, /* integer detected by zero */
- STATE_IX, /* integer detected by 1-9 */
- STATE_UC, /* Unicode character read */
- };
- /* error state */
- #define STATE___ 0xff
- #define NR_STATES (STATE_D2 + 1)
- #define NR_CLASSES (C_HASH + 1)
- #define IS_STATE_ACTION(s) ((s) & 0x80)
- #define S(x) STATE_##x
- #define PT_(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a1,b1,c1,d1,e1,f1,g1,h1) \
- { S(a),S(b),S(c),S(d),S(e),S(f),S(g),S(h),S(i),S(j),S(k),S(l),S(m),S(n), \
- S(o),S(p),S(q),S(r),S(s),S(t),S(u),S(v),S(w),S(x),S(y),S(z),S(a1),S(b1), \
- S(c1),S(d1),S(e1),S(f1),S(g1),S(h1) }
- /* map from the (previous state+new character class) to the next parser transition */
- static const uint8_t state_transition_table[NR_STATES][NR_CLASSES] = {
- /* white ABCDF other */
- /* sp nl | { } [ ] : , " \ / + - . 0 19 a b c d e f l n r s t u | E | * # */
- /*GO*/ PT_(GO, GO, GO, OB, __, AB, __, __, __, __, __, CB, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*OK*/ PT_(OK, OK, OK, __, OE, __, AE, __, SP, __, __, CB, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*_O*/ PT_(_O, _O, _O, __, OE, __, __, __, __, _S, __, CB, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*_K*/ PT_(_K, _K, _K, __, __, __, __, __, __, _S, __, CB, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*CO*/ PT_(CO, CO, CO, __, __, __, __, KS, __, __, __, CB, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*_V*/ PT_(_V, _V, _V, OB, __, AB, __, __, __, _S, __, CB, __, MX, __, ZX, IX, __, __, __, __, __, F1, __, N1, __, __, T1,
- __, __, __, __, __, YB),
- /*_A*/ PT_(_A, _A, _A, OB, __, AB, AE, __, __, _S, __, CB, __, MX, __, ZX, IX, __, __, __, __, __, F1, __, N1, __, __, T1,
- __, __, __, __, __, YB),
- /****************************************************************************************************************/
- /*_S*/ PT_(_S, __, __, _S, _S, _S, _S, _S, _S, SE, E0, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S, _S,
- _S, _S, _S, _S, _S, _S),
- /*E0*/ PT_(__, __, __, __, __, __, __, __, __, _S, _S, _S, __, __, __, __, __, __, _S, __, __, __, _S, __, _S, _S, __, _S,
- U1, __, __, __, __, __),
- /*U1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, U2, U2, U2, U2, U2, U2, U2, U2, __, __, __, __, __,
- __, U2, U2, __, __, __),
- /*U2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, U3, U3, U3, U3, U3, U3, U3, U3, __, __, __, __, __,
- __, U3, U3, __, __, __),
- /*U3*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, U4, U4, U4, U4, U4, U4, U4, U4, __, __, __, __, __,
- __, U4, U4, __, __, __),
- /*U4*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, UC, UC, UC, UC, UC, UC, UC, UC, __, __, __, __, __,
- __, UC, UC, __, __, __),
- /****************************************************************************************************************/
- /*M0*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, Z0, I0, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*Z0*/ PT_(OK, OK, OK, __, OE, __, AE, __, SP, __, __, CB, __, __, DF, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, YB),
- /*I0*/ PT_(OK, OK, OK, __, OE, __, AE, __, SP, __, __, CB, __, __, DF, I0, I0, __, __, __, __, DE, __, __, __, __, __, __,
- __, __, DE, __, __, YB),
- /*R1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, R2, R2, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*R2*/ PT_(OK, OK, OK, __, OE, __, AE, __, SP, __, __, CB, __, __, __, R2, R2, __, __, __, __, X1, __, __, __, __, __, __,
- __, __, X1, __, __, YB),
- /*X1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, X2, X2, __, X3, X3, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*X2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, X3, X3, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*X3*/ PT_(OK, OK, OK, __, OE, __, AE, __, SP, __, __, __, __, __, __, X3, X3, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /****************************************************************************************************************/
- /*T1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, T2, __, __,
- __, __, __, __, __, __),
- /*T2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- T3, __, __, __, __, __),
- /*T3*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, TR, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*F1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, F2, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*F2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, F3, __, __, __, __,
- __, __, __, __, __, __),
- /*F3*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, F4, __,
- __, __, __, __, __, __),
- /*F4*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, FA, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*N1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- N2, __, __, __, __, __),
- /*N2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, N3, __, __, __, __,
- __, __, __, __, __, __),
- /*N3*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, NU, __, __, __, __,
- __, __, __, __, __, __),
- /****************************************************************************************************************/
- /*C1*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, C2, __),
- /*C2*/ PT_(C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2,
- C2, C2, C2, C2, C3, C2),
- /*C3*/ PT_(C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, CE, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2,
- C2, C2, C2, C2, C3, C2),
- /*Y1*/ PT_(Y1, CE, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1, Y1,
- Y1, Y1, Y1, Y1, Y1, Y1),
- /*D1*/ PT_(__, __, __, __, __, __, __, __, __, __, D2, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- __, __, __, __, __, __),
- /*D2*/ PT_(__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- U1, __, __, __, __, __),
- };
- #undef S
- #undef PT_
- /* map from (previous state+new character class) to the buffer policy. ignore=0/append=1/escape=2 */
- static const uint8_t buffer_policy_table[NR_STATES][NR_CLASSES] = {
- /* white ABCDF other */
- /* sp nl | { } [ ] : , " \ / + - . 0 19 a b c d e f l n r s t u | E | * # */
- /*GO*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*OK*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*_O*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*_K*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*CO*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*_V*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*_A*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /**************************************************************************************************************/
- /*_S*/ { 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /*E0*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0 },
- /*U1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
- /*U2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
- /*U3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
- /*U4*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
- /**************************************************************************************************************/
- /*M0*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*Z0*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*I0*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
- /*R1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*R2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
- /*X1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*X2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*X3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /**************************************************************************************************************/
- /*T1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*T2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*T3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*F1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*F2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*F3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*F4*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*N1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*N2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*N3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /**************************************************************************************************************/
- /*C1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*C2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*C3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*Y1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*D1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /*D2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- };
- #define __ 0xff
- static const uint8_t utf8_header_table[256] = {
- /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 80 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 90 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* a0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* b0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* c0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- /* d0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- /* e0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- /* f0 */ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, __, __,
- };
- static const uint8_t utf8_continuation_table[256] = {
- /*__0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 10 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 20 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 30 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 40 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 50 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 60 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 70 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* c0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* d0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* e0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- /* f0 */ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
- };
- #undef __
- #define MODE_ARRAY 0
- #define MODE_OBJECT 1
- static inline void *memory_realloc(void *(*realloc_fct)(void *, size_t), void *ptr, size_t size)
- {
- if (realloc_fct) {
- return (realloc_fct(ptr, size));
- } else {
- return (realloc(ptr, size));
- }
- }
- static inline void *memory_calloc(void *(*calloc_fct)(size_t, size_t), size_t nmemb, size_t size)
- {
- if (calloc_fct) {
- return (calloc_fct(nmemb, size));
- } else {
- return (calloc(nmemb, size));
- }
- }
- static inline void memory_free(void (*free_fct)(void *ptr), void *ptr)
- {
- if (free_fct) {
- free_fct(ptr);
- } else {
- free(ptr);
- }
- }
- #define parser_free(parser, n) memory_free(parser->config.user_free, n)
- #define parser_calloc(parser, n, s) memory_calloc(parser->config.user_calloc, n, s)
- #define parser_realloc(parser, n, s) memory_realloc(parser->config.user_realloc, n, s)
- static int state_grow(json_parser * parser)
- {
- uint32_t newsize = parser->stack_size * 2;
- void *ptr = NULL;
- if (parser->config.max_nesting != 0)
- return JSON_ERROR_NESTING_LIMIT;
- ptr = parser_realloc(parser, parser->stack, newsize * sizeof(uint8_t));
- if (!ptr)
- return JSON_ERROR_NO_MEMORY;
- parser->stack = ptr;
- parser->stack_size = newsize;
- return 0;
- }
- static int state_push(json_parser * parser, int mode)
- {
- if (parser->stack_offset >= parser->stack_size) {
- int ret = state_grow(parser);
- if (ret)
- return ret;
- }
- parser->stack[parser->stack_offset++] = mode;
- return 0;
- }
- static int state_pop(json_parser * parser, int mode)
- {
- if (parser->stack_offset == 0)
- return JSON_ERROR_POP_EMPTY;
- parser->stack_offset--;
- if (parser->stack[parser->stack_offset] != mode)
- return JSON_ERROR_POP_UNEXPECTED_MODE;
- return 0;
- }
- static int buffer_grow(json_parser * parser)
- {
- uint32_t newsize;
- void *ptr;
- uint32_t max = parser->config.max_data;
- if (max > 0 && parser->buffer_size == max)
- return JSON_ERROR_DATA_LIMIT;
- newsize = parser->buffer_size * 2;
- if (max > 0 && newsize > max)
- newsize = max;
- ptr = parser_realloc(parser, parser->buffer, newsize * sizeof(char));
- if (!ptr)
- return JSON_ERROR_NO_MEMORY;
- parser->buffer = ptr;
- parser->buffer_size = newsize;
- return 0;
- }
- static int buffer_push(json_parser * parser, unsigned char c)
- {
- int ret;
- if (parser->buffer_offset + 1 >= parser->buffer_size) {
- ret = buffer_grow(parser);
- if (ret)
- return ret;
- }
- parser->buffer[parser->buffer_offset++] = c;
- return 0;
- }
- static int do_callback_withbuf(json_parser * parser, int type)
- {
- if (!parser->callback)
- return 0;
- parser->buffer[parser->buffer_offset] = '\0';
- return (*parser->callback) (parser->userdata, type, parser->buffer, parser->buffer_offset);
- }
- static int do_callback(json_parser * parser, int type)
- {
- if (!parser->callback)
- return 0;
- return (*parser->callback) (parser->userdata, type, NULL, 0);
- }
- static int do_buffer(json_parser * parser)
- {
- int ret = 0;
- switch (parser->type) {
- case JSON_KEY:
- case JSON_STRING:
- case JSON_FLOAT:
- case JSON_INT:
- case JSON_NULL:
- case JSON_TRUE:
- case JSON_FALSE:
- ret = do_callback_withbuf(parser, parser->type);
- if (ret)
- return ret;
- break;
- default:
- break;
- }
- parser->buffer_offset = 0;
- return ret;
- }
- static const uint8_t hextable[] = {
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
- 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- };
- #define hex(c) (hextable[(uint8_t) c])
- /* high surrogate range from d800 to dbff */
- /* low surrogate range dc00 to dfff */
- #define IS_HIGH_SURROGATE(uc) (((uc) & 0xfc00) == 0xd800)
- #define IS_LOW_SURROGATE(uc) (((uc) & 0xfc00) == 0xdc00)
- /* transform an unicode [0-9A-Fa-f]{4} sequence into a proper value */
- static int decode_unicode_char(json_parser * parser)
- {
- uint32_t uval;
- char *b = parser->buffer;
- int offset = parser->buffer_offset;
- uval = (hex(b[offset - 4]) << 12) | (hex(b[offset - 3]) << 8)
- | (hex(b[offset - 2]) << 4) | hex(b[offset - 1]);
- parser->buffer_offset -= 4;
- /* fast case */
- if (!parser->unicode_multi && uval < 0x80) {
- b[parser->buffer_offset++] = (char)uval;
- return 0;
- }
- if (parser->unicode_multi) {
- if (!IS_LOW_SURROGATE(uval))
- return JSON_ERROR_UNICODE_MISSING_LOW_SURROGATE;
- uval = 0x10000 + ((parser->unicode_multi & 0x3ff) << 10) + (uval & 0x3ff);
- b[parser->buffer_offset++] = (char)((uval >> 18) | 0xf0);
- b[parser->buffer_offset++] = (char)(((uval >> 12) & 0x3f) | 0x80);
- b[parser->buffer_offset++] = (char)(((uval >> 6) & 0x3f) | 0x80);
- b[parser->buffer_offset++] = (char)((uval & 0x3f) | 0x80);
- parser->unicode_multi = 0;
- return 0;
- }
- if (IS_LOW_SURROGATE(uval))
- return JSON_ERROR_UNICODE_UNEXPECTED_LOW_SURROGATE;
- if (IS_HIGH_SURROGATE(uval)) {
- parser->unicode_multi = uval;
- return 0;
- }
- if (uval < 0x800) {
- b[parser->buffer_offset++] = (char)((uval >> 6) | 0xc0);
- b[parser->buffer_offset++] = (char)((uval & 0x3f) | 0x80);
- } else {
- b[parser->buffer_offset++] = (char)((uval >> 12) | 0xe0);
- b[parser->buffer_offset++] = (char)(((uval >> 6) & 0x3f) | 0x80);
- b[parser->buffer_offset++] = (char)(((uval >> 0) & 0x3f) | 0x80);
- }
- return 0;
- }
- static int buffer_push_escape(json_parser * parser, unsigned char next)
- {
- char c = '\0';
- switch (next) {
- case 'b':
- c = '\b';
- break;
- case 'f':
- c = '\f';
- break;
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case '"':
- c = '"';
- break;
- case '/':
- c = '/';
- break;
- case '\\':
- c = '\\';
- break;
- }
- /* push the escaped character */
- return buffer_push(parser, c);
- }
- #define CHK(f) do { ret = f; if (ret) return ret; } while(0)
- static int act_uc(json_parser * parser)
- {
- int ret;
- CHK(decode_unicode_char(parser));
- parser->state = (parser->unicode_multi) ? STATE_D1 : STATE__S;
- return 0;
- }
- static int act_yb(json_parser * parser)
- {
- if (!parser->config.allow_yaml_comments)
- return JSON_ERROR_COMMENT_NOT_ALLOWED;
- parser->save_state = parser->state;
- return 0;
- }
- static int act_cb(json_parser * parser)
- {
- if (!parser->config.allow_c_comments)
- return JSON_ERROR_COMMENT_NOT_ALLOWED;
- parser->save_state = parser->state;
- return 0;
- }
- static int act_ce(json_parser * parser)
- {
- parser->state = (parser->save_state > STATE__A) ? STATE_OK : parser->save_state;
- return 0;
- }
- static int act_ob(json_parser * parser)
- {
- int ret;
- CHK(do_callback(parser, JSON_OBJECT_BEGIN));
- CHK(state_push(parser, MODE_OBJECT));
- parser->expecting_key = 1;
- return 0;
- }
- static int act_oe(json_parser * parser)
- {
- int ret;
- CHK(state_pop(parser, MODE_OBJECT));
- CHK(do_callback(parser, JSON_OBJECT_END));
- parser->expecting_key = 0;
- return 0;
- }
- static int act_ab(json_parser * parser)
- {
- int ret;
- CHK(do_callback(parser, JSON_ARRAY_BEGIN));
- CHK(state_push(parser, MODE_ARRAY));
- return 0;
- }
- static int act_ae(json_parser * parser)
- {
- int ret;
- CHK(state_pop(parser, MODE_ARRAY));
- CHK(do_callback(parser, JSON_ARRAY_END));
- return 0;
- }
- static int act_se(json_parser * parser)
- {
- int ret;
- CHK(do_callback_withbuf(parser, (parser->expecting_key) ? JSON_KEY : JSON_STRING));
- parser->buffer_offset = 0;
- parser->state = (parser->expecting_key) ? STATE_CO : STATE_OK;
- parser->expecting_key = 0;
- return 0;
- }
- static int act_sp(json_parser * parser)
- {
- if (parser->stack_offset == 0)
- return JSON_ERROR_COMMA_OUT_OF_STRUCTURE;
- if (parser->stack[parser->stack_offset - 1] == MODE_OBJECT) {
- parser->expecting_key = 1;
- parser->state = STATE__K;
- } else
- parser->state = STATE__V;
- return 0;
- }
- struct action_descr {
- int (*call)(json_parser * parser);
- uint8_t type;
- uint8_t state; /* 0 if we let the callback set the value it want */
- uint8_t dobuffer;
- };
- static struct action_descr actions_map[] = {
- { NULL, JSON_NONE, STATE__V, 0 }, /* KS */
- { act_sp, JSON_NONE, 0, 1 }, /* SP */
- { act_ab, JSON_NONE, STATE__A, 0 }, /* AB */
- { act_ae, JSON_NONE, STATE_OK, 1 }, /* AE */
- { act_ob, JSON_NONE, STATE__O, 0 }, /* OB */
- { act_oe, JSON_NONE, STATE_OK, 1 }, /* OE */
- { act_cb, JSON_NONE, STATE_C1, 1 }, /* CB */
- { act_yb, JSON_NONE, STATE_Y1, 1 }, /* YB */
- { act_ce, JSON_NONE, 0, 0 }, /* CE */
- { NULL, JSON_FALSE, STATE_OK, 0 }, /* FA */
- { NULL, JSON_TRUE, STATE_OK, 0 }, /* TR */
- { NULL, JSON_NULL, STATE_OK, 0 }, /* NU */
- { NULL, JSON_FLOAT, STATE_X1, 0 }, /* DE */
- { NULL, JSON_FLOAT, STATE_R1, 0 }, /* DF */
- { act_se, JSON_NONE, 0, 0 }, /* SE */
- { NULL, JSON_INT, STATE_M0, 0 }, /* MX */
- { NULL, JSON_INT, STATE_Z0, 0 }, /* ZX */
- { NULL, JSON_INT, STATE_I0, 0 }, /* IX */
- { act_uc, JSON_NONE, 0, 0 }, /* UC */
- };
- static int do_action(json_parser * parser, int next_state)
- {
- struct action_descr *descr = &actions_map[next_state & ~0x80];
- if (descr->call) {
- int ret;
- if (descr->dobuffer)
- CHK(do_buffer(parser));
- CHK((descr->call) (parser));
- }
- if (descr->state)
- parser->state = descr->state;
- parser->type = descr->type;
- return 0;
- }
- /** json_parser_init initialize a parser structure taking a config,
- * a config and its userdata.
- * return JSON_ERROR_NO_MEMORY if memory allocation failed or SUCCESS.
- */
- int json_parser_init(json_parser * parser, json_config * config, json_parser_callback callback, void *userdata)
- {
- memset(parser, 0, sizeof(*parser));
- if (config)
- memcpy(&parser->config, config, sizeof(json_config));
- parser->callback = callback;
- parser->userdata = userdata;
- /* initialise parsing stack and state */
- parser->stack_offset = 0;
- parser->state = STATE_GO;
- /* initialize the parse stack */
- parser->stack_size = (parser->config.max_nesting > 0)
- ? parser->config.max_nesting : LIBJSON_DEFAULT_STACK_SIZE;
- parser->stack = parser_calloc(parser, parser->stack_size, sizeof(parser->stack[0]));
- if (!parser->stack) { /* gcc-10 -fanalyzer sys memory leak here */
- return JSON_ERROR_NO_MEMORY;
- }
- /* initialize the parse buffer */
- parser->buffer_size = (parser->config.buffer_initial_size > 0)
- ? parser->config.buffer_initial_size : LIBJSON_DEFAULT_BUFFER_SIZE;
- if (parser->config.max_data > 0 && parser->buffer_size > parser->config.max_data)
- parser->buffer_size = parser->config.max_data;
- parser->buffer = parser_calloc(parser, parser->buffer_size, sizeof(char));
- if (!parser->buffer) {
- parser_free(parser, parser->stack);
- return JSON_ERROR_NO_MEMORY;
- }
- return 0;
- }
- /** json_parser_free freed memory structure allocated by the parser */
- int json_parser_free(json_parser * parser)
- {
- if (!parser)
- return 0;
- parser_free(parser, parser->stack);
- parser_free(parser, parser->buffer);
- parser->stack = NULL;
- parser->buffer = NULL;
- return 0;
- }
- /** json_parser_is_done return 0 is the parser isn't in a finish state. !0 if it is */
- int json_parser_is_done(json_parser * parser)
- {
- /* need to compare the state to !GO to not accept empty document */
- return parser->stack_offset == 0 && parser->state != STATE_GO;
- }
- /** json_parser_string append a string s with a specific length to the parser
- * return 0 if everything went ok, a JSON_ERROR_* otherwise.
- * the user can supplied a valid processed pointer that will
- * be fill with the number of processed characters before returning */
- int json_parser_string(json_parser * parser, const char *s, uint32_t length, uint32_t * processed)
- {
- int ret;
- int next_class, next_state;
- int buffer_policy;
- uint32_t i;
- ret = 0;
- for (i = 0; i < length; i++) {
- unsigned char ch = s[i];
- ret = 0;
- if (parser->utf8_multibyte_left > 0) {
- if (utf8_continuation_table[ch] != 0) {
- ret = JSON_ERROR_UTF8;
- break;
- }
- next_class = C_OTHER;
- parser->utf8_multibyte_left--;
- } else {
- parser->utf8_multibyte_left = utf8_header_table[ch];
- if (parser->utf8_multibyte_left == 0xff) {
- ret = JSON_ERROR_UTF8;
- break;
- }
- next_class = (parser->utf8_multibyte_left > 0) ? C_OTHER : character_class[ch];
- if (next_class == C_ERROR) {
- ret = JSON_ERROR_BAD_CHAR;
- break;
- }
- }
- next_state = state_transition_table[parser->state][next_class];
- buffer_policy = buffer_policy_table[parser->state][next_class];
- TRACING("addchar %d (current-state=%d, next-state=%d, buf-policy=%d)\n", ch, parser->state, next_state, buffer_policy);
- if (next_state == STATE___) {
- ret = JSON_ERROR_UNEXPECTED_CHAR;
- break;
- }
- /* add char to buffer */
- if (buffer_policy) {
- ret = (buffer_policy == 2)
- ? buffer_push_escape(parser, ch)
- : buffer_push(parser, ch);
- if (ret)
- break;
- }
- /* move to the next level */
- if (IS_STATE_ACTION(next_state))
- ret = do_action(parser, next_state);
- else
- parser->state = next_state;
- if (ret)
- break;
- }
- if (processed)
- *processed = i;
- return ret;
- }
- /** json_parser_char append one single char to the parser
- * return 0 if everything went ok, a JSON_ERROR_* otherwise */
- int json_parser_char(json_parser * parser, unsigned char ch)
- {
- return json_parser_string(parser, (char *)&ch, 1, NULL);
- }
- /** json_print_init initialize a printer context. always succeed */
- int json_print_init(json_printer * printer, json_printer_callback callback, void *userdata)
- {
- memset(printer, '\0', sizeof(*printer));
- printer->callback = callback;
- printer->userdata = userdata;
- printer->indentstr = "\t";
- printer->indentlevel = 0;
- printer->enter_object = 1;
- printer->first = 1;
- return 0;
- }
- /** json_print_free free a printer context
- * doesn't do anything now, but in future print_init could allocate memory */
- int json_print_free(json_printer * printer)
- {
- memset(printer, '\0', sizeof(*printer));
- return 0;
- }
- /* escape a C string to be a JSON valid string on the wire.
- * XXX: it doesn't do unicode verification. yet?. */
- static int print_string(json_printer * printer, const char *data, uint32_t length)
- {
- uint32_t i;
- if (printer->callback == NULL) {
- printf("%s(): nil printer->callback\n", __func__);
- return (0);
- }
- printer->callback(printer->userdata, "\"", 1);
- for (i = 0; i < length; i++) {
- unsigned char c = data[i];
- if (c < 36) {
- char const *esc = character_escape[c];
- printer->callback(printer->userdata, esc, strlen(esc));
- } else if (c == '\\') {
- printer->callback(printer->userdata, "\\\\", 2);
- } else
- printer->callback(printer->userdata, data + i, 1);
- }
- printer->callback(printer->userdata, "\"", 1);
- return 0;
- }
- static int print_binary_string(json_printer * printer, const char *data, uint32_t length)
- {
- uint32_t i;
- printer->callback(printer->userdata, "\"", 1);
- for (i = 0; i < length; i++) {
- unsigned char c = data[i];
- char const *esc = character_escape[c];
- printer->callback(printer->userdata, esc, strlen(esc));
- }
- printer->callback(printer->userdata, "\"", 1);
- return 0;
- }
- static int print_indent(json_printer * printer)
- {
- int i;
- printer->callback(printer->userdata, "\n", 1);
- for (i = 0; i < printer->indentlevel; i++)
- printer->callback(printer->userdata, printer->indentstr, strlen(printer->indentstr));
- return 0;
- }
- static int json_print_mode(json_printer * printer, int type, const char *data, uint32_t length, int pretty)
- {
- int enterobj = printer->enter_object;
- if (!enterobj && !printer->afterkey && (type != JSON_ARRAY_END && type != JSON_OBJECT_END)) {
- printer->callback(printer->userdata, ",", 1);
- if (pretty)
- print_indent(printer);
- }
- if (pretty && (enterobj && !printer->first && (type != JSON_ARRAY_END && type != JSON_OBJECT_END))) {
- print_indent(printer);
- }
- printer->first = 0;
- printer->enter_object = 0;
- printer->afterkey = 0;
- switch (type) {
- case JSON_ARRAY_BEGIN:
- printer->callback(printer->userdata, "[", 1);
- printer->indentlevel++;
- printer->enter_object = 1;
- break;
- case JSON_OBJECT_BEGIN:
- printer->callback(printer->userdata, "{", 1);
- printer->indentlevel++;
- printer->enter_object = 1;
- break;
- case JSON_ARRAY_END:
- case JSON_OBJECT_END:
- printer->indentlevel--;
- if (pretty && !enterobj)
- print_indent(printer);
- printer->callback(printer->userdata, (type == JSON_OBJECT_END) ? "}" : "]", 1);
- break;
- case JSON_INT:
- printer->callback(printer->userdata, data, length);
- break;
- case JSON_FLOAT:
- printer->callback(printer->userdata, data, length);
- break;
- case JSON_NULL:
- printer->callback(printer->userdata, "null", 4);
- break;
- case JSON_TRUE:
- printer->callback(printer->userdata, "true", 4);
- break;
- case JSON_FALSE:
- printer->callback(printer->userdata, "false", 5);
- break;
- case JSON_KEY:
- print_string(printer, data, length);
- printer->callback(printer->userdata, ": ", (pretty) ? 2 : 1);
- printer->afterkey = 1;
- break;
- case JSON_STRING:
- print_string(printer, data, length);
- break;
- case JSON_BSTRING:
- print_binary_string(printer, data, length);
- break;
- default:
- break;
- }
- return 0;
- }
- /** json_print_pretty pretty print the passed argument (type/data/length). */
- int json_print_pretty(json_printer * printer, int type, const char *data, uint32_t length)
- {
- if (data == NULL) {
- printf("%s(): nil data\n", __func__);
- return (0);
- }
- if (length == 0) {
- printf("%s(): zero length\n", __func__);
- return (0);
- }
- return json_print_mode(printer, type, data, length, 1);
- }
- /** json_print_raw prints without eye candy the passed argument (type/data/length). */
- int json_print_raw(json_printer * printer, int type, const char *data, uint32_t length)
- {
- return json_print_mode(printer, type, data, length, 0);
- }
- /** json_print_args takes multiple types and pass them to the printer function */
- int json_print_args(json_printer * printer, int (*f)(json_printer *, int, const char *, uint32_t), ...)
- {
- va_list ap;
- char *data;
- int32_t length;
- int type, ret;
- ret = 0;
- va_start(ap, f);
- while ((type = va_arg(ap, int)) != -1) {
- switch (type) {
- case JSON_ARRAY_BEGIN:
- case JSON_ARRAY_END:
- case JSON_OBJECT_BEGIN:
- case JSON_OBJECT_END:
- case JSON_NULL:
- case JSON_TRUE:
- case JSON_FALSE:
- ret = (*f) (printer, type, NULL, 0);
- break;
- case JSON_INT:
- case JSON_FLOAT:
- case JSON_KEY:
- case JSON_STRING:
- data = va_arg(ap, char *);
- length = va_arg(ap, int32_t);
- if (length == -1)
- length = strlen(data);
- ret = (*f) (printer, type, data, length);
- break;
- }
- if (ret)
- break;
- }
- va_end(ap);
- return ret;
- }
- static int dom_push(struct json_parser_dom *ctx, void *val)
- {
- if (ctx->stack_offset == ctx->stack_size) {
- void *ptr;
- uint32_t newsize = ctx->stack_size * 2;
- ptr = memory_realloc(ctx->user_realloc, ctx->stack, newsize);
- if (!ptr)
- return JSON_ERROR_NO_MEMORY;
- ctx->stack = ptr;
- ctx->stack_size = newsize;
- }
- ctx->stack[ctx->stack_offset].val = val;
- ctx->stack[ctx->stack_offset].key = NULL;
- ctx->stack[ctx->stack_offset].key_length = 0;
- ctx->stack_offset++;
- return 0;
- }
- static int dom_pop(struct json_parser_dom *ctx, void **val)
- {
- ctx->stack_offset--;
- *val = ctx->stack[ctx->stack_offset].val;
- return 0;
- }
- /* XXX todo should use parser_calloc and parser_free also below */
- int json_parser_dom_init(json_parser_dom * dom,
- json_parser_dom_create_structure create_structure,
- json_parser_dom_create_data create_data, json_parser_dom_append append)
- {
- memset(dom, 0, sizeof(*dom));
- dom->stack_size = 1024;
- dom->stack_offset = 0;
- dom->stack = memory_calloc(dom->user_calloc, dom->stack_size, sizeof(*(dom->stack)));
- if (!dom->stack) { /* gcc-10 -fanalyzer memory leak here */
- return JSON_ERROR_NO_MEMORY;
- }
- dom->append = append;
- dom->create_structure = create_structure;
- dom->create_data = create_data;
- return 0;
- }
- int json_parser_dom_free(json_parser_dom * dom)
- {
- free(dom->stack);
- return 0;
- }
- int json_parser_dom_callback(void *userdata, int type, const char *data, uint32_t length)
- {
- struct json_parser_dom *ctx = userdata;
- void *v;
- struct stack_elem *stack = NULL;
- switch (type) {
- case JSON_ARRAY_BEGIN:
- case JSON_OBJECT_BEGIN:
- v = ctx->create_structure(ctx->stack_offset, type == JSON_OBJECT_BEGIN);
- if (!v)
- return JSON_ERROR_CALLBACK;
- dom_push(ctx, v);
- break;
- case JSON_OBJECT_END:
- case JSON_ARRAY_END:
- dom_pop(ctx, &v);
- if (ctx->stack_offset > 0) {
- stack = &(ctx->stack[ctx->stack_offset - 1]);
- ctx->append(stack->val, stack->key, stack->key_length, v);
- free(stack->key);
- } else
- ctx->root_structure = v;
- break;
- case JSON_KEY:
- stack = &(ctx->stack[ctx->stack_offset - 1]);
- stack->key = memory_calloc(ctx->user_calloc, length + 1, sizeof(char));
- if (!stack->key)
- return JSON_ERROR_NO_MEMORY;
- stack->key_length = length;
- memcpy(stack->key, data, length);
- break;
- case JSON_STRING:
- case JSON_INT:
- case JSON_FLOAT:
- case JSON_NULL:
- case JSON_TRUE:
- case JSON_FALSE:
- stack = &(ctx->stack[ctx->stack_offset - 1]);
- v = ctx->create_data(type, data, length);
- if (!v)
- return JSON_ERROR_CALLBACK;
- if (ctx->append(stack->val, stack->key, stack->key_length, v))
- return JSON_ERROR_CALLBACK;
- free(stack->key);
- break;
- }
- return 0;
- }
- /* end. */
|