1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25 /** \defgroup lejp JSON parser 26 * ##JSON parsing related functions 27 * \ingroup lwsapi 28 * 29 * LEJP is an extremely lightweight JSON stream parser included in lws. 30 */ 31 //@{ 32 struct lejp_ctx; 33 34 #if !defined(LWS_ARRAY_SIZE) 35 #define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0])) 36 #endif 37 #define LEJP_FLAG_WS_KEEP 64 38 #define LEJP_FLAG_WS_COMMENTLINE 32 39 40 enum lejp_states { 41 LEJP_IDLE = 0, 42 LEJP_MEMBERS = 1, 43 LEJP_M_P = 2, 44 LEJP_MP_STRING = LEJP_FLAG_WS_KEEP | 3, 45 LEJP_MP_STRING_ESC = LEJP_FLAG_WS_KEEP | 4, 46 LEJP_MP_STRING_ESC_U1 = LEJP_FLAG_WS_KEEP | 5, 47 LEJP_MP_STRING_ESC_U2 = LEJP_FLAG_WS_KEEP | 6, 48 LEJP_MP_STRING_ESC_U3 = LEJP_FLAG_WS_KEEP | 7, 49 LEJP_MP_STRING_ESC_U4 = LEJP_FLAG_WS_KEEP | 8, 50 LEJP_MP_DELIM = 9, 51 LEJP_MP_VALUE = 10, 52 LEJP_MP_VALUE_NUM_INT = LEJP_FLAG_WS_KEEP | 11, 53 LEJP_MP_VALUE_NUM_EXP = LEJP_FLAG_WS_KEEP | 12, 54 LEJP_MP_VALUE_TOK = LEJP_FLAG_WS_KEEP | 13, 55 LEJP_MP_COMMA_OR_END = 14, 56 LEJP_MP_ARRAY_END = 15, 57 }; 58 59 enum lejp_reasons { 60 LEJP_CONTINUE = -1, 61 LEJP_REJECT_IDLE_NO_BRACE = -2, 62 LEJP_REJECT_MEMBERS_NO_CLOSE = -3, 63 LEJP_REJECT_MP_NO_OPEN_QUOTE = -4, 64 LEJP_REJECT_MP_STRING_UNDERRUN = -5, 65 LEJP_REJECT_MP_ILLEGAL_CTRL = -6, 66 LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC = -7, 67 LEJP_REJECT_ILLEGAL_HEX = -8, 68 LEJP_REJECT_MP_DELIM_MISSING_COLON = -9, 69 LEJP_REJECT_MP_DELIM_BAD_VALUE_START = -10, 70 LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC = -11, 71 LEJP_REJECT_MP_VAL_NUM_FORMAT = -12, 72 LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP = -13, 73 LEJP_REJECT_MP_VAL_TOK_UNKNOWN = -14, 74 LEJP_REJECT_MP_C_OR_E_UNDERF = -15, 75 LEJP_REJECT_MP_C_OR_E_NOTARRAY = -16, 76 LEJP_REJECT_MP_ARRAY_END_MISSING = -17, 77 LEJP_REJECT_STACK_OVERFLOW = -18, 78 LEJP_REJECT_MP_DELIM_ISTACK = -19, 79 LEJP_REJECT_NUM_TOO_LONG = -20, 80 LEJP_REJECT_MP_C_OR_E_NEITHER = -21, 81 LEJP_REJECT_UNKNOWN = -22, 82 LEJP_REJECT_CALLBACK = -23 83 }; 84 85 #define LEJP_FLAG_CB_IS_VALUE 64 86 87 enum lejp_callbacks { 88 LEJPCB_CONSTRUCTED = 0, 89 LEJPCB_DESTRUCTED = 1, 90 91 LEJPCB_START = 2, 92 LEJPCB_COMPLETE = 3, 93 LEJPCB_FAILED = 4, 94 95 LEJPCB_PAIR_NAME = 5, 96 97 LEJPCB_VAL_TRUE = LEJP_FLAG_CB_IS_VALUE | 6, 98 LEJPCB_VAL_FALSE = LEJP_FLAG_CB_IS_VALUE | 7, 99 LEJPCB_VAL_NULL = LEJP_FLAG_CB_IS_VALUE | 8, 100 LEJPCB_VAL_NUM_INT = LEJP_FLAG_CB_IS_VALUE | 9, 101 LEJPCB_VAL_NUM_FLOAT = LEJP_FLAG_CB_IS_VALUE | 10, 102 LEJPCB_VAL_STR_START = 11, /* notice handle separately */ 103 LEJPCB_VAL_STR_CHUNK = LEJP_FLAG_CB_IS_VALUE | 12, 104 LEJPCB_VAL_STR_END = LEJP_FLAG_CB_IS_VALUE | 13, 105 106 LEJPCB_ARRAY_START = 14, 107 LEJPCB_ARRAY_END = 15, 108 109 LEJPCB_OBJECT_START = 16, 110 LEJPCB_OBJECT_END = 17, 111 }; 112 113 /** 114 * _lejp_callback() - User parser actions 115 * \param ctx: LEJP context 116 * \param reason: Callback reason 117 * 118 * Your user callback is associated with the context at construction time, 119 * and receives calls as the parsing progresses. 120 * 121 * All of the callbacks may be ignored and just return 0. 122 * 123 * The reasons it might get called, found in @reason, are: 124 * 125 * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to 126 * perform one-time allocation for the life of the context. 127 * 128 * LEJPCB_DESTRUCTED: The context is being destructed... if you made any 129 * allocations at construction-time, you can free them now 130 * 131 * LEJPCB_START: Parsing is beginning at the first byte of input 132 * 133 * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or 134 * positive return code from lejp_parse indicating the 135 * amount of unused bytes left in the input buffer 136 * 137 * LEJPCB_FAILED: Parsing failed. You'll get a negative error code 138 * returned from lejp_parse 139 * 140 * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed, 141 * this callback occurs. You can find the new name at 142 * the end of ctx->path[] 143 * 144 * LEJPCB_VAL_TRUE: The "true" value appeared 145 * 146 * LEJPCB_VAL_FALSE: The "false" value appeared 147 * 148 * LEJPCB_VAL_NULL: The "null" value appeared 149 * 150 * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf 151 * 152 * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf 153 * 154 * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet 155 * 156 * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not 157 * the end of the string. We produce this to spill the 158 * intermediate buffer to the user code, so we can handle 159 * huge JSON strings using only the small buffer in the 160 * ctx. If the whole JSON string fits in the ctx buffer, 161 * you won't get these callbacks. 162 * 163 * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the 164 * string is in ctx->buf. 165 * 166 * LEJPCB_ARRAY_START: An array started 167 * 168 * LEJPCB_ARRAY_END: An array ended 169 * 170 * LEJPCB_OBJECT_START: An object started 171 * 172 * LEJPCB_OBJECT_END: An object ended 173 */ 174 LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason); 175 176 typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason); 177 178 #ifndef LEJP_MAX_PARSING_STACK_DEPTH 179 #define LEJP_MAX_PARSING_STACK_DEPTH 5 180 #endif 181 #ifndef LEJP_MAX_DEPTH 182 #define LEJP_MAX_DEPTH 12 183 #endif 184 #ifndef LEJP_MAX_INDEX_DEPTH 185 #define LEJP_MAX_INDEX_DEPTH 8 186 #endif 187 #ifndef LEJP_MAX_PATH 188 #define LEJP_MAX_PATH 128 189 #endif 190 #ifndef LEJP_STRING_CHUNK 191 /* must be >= 30 to assemble floats */ 192 #define LEJP_STRING_CHUNK 254 193 #endif 194 195 enum num_flags { 196 LEJP_SEEN_MINUS = (1 << 0), 197 LEJP_SEEN_POINT = (1 << 1), 198 LEJP_SEEN_POST_POINT = (1 << 2), 199 LEJP_SEEN_EXP = (1 << 3) 200 }; 201 202 struct _lejp_stack { 203 char s; /* lejp_state stack*/ 204 char p; /* path length */ 205 char i; /* index array length */ 206 char b; /* user bitfield */ 207 }; 208 209 struct _lejp_parsing_stack { 210 void *user; /* private to the stack level */ 211 signed char (*callback)(struct lejp_ctx *ctx, char reason); 212 const char * const *paths; 213 uint8_t count_paths; 214 uint8_t ppos; 215 uint8_t path_match; 216 }; 217 218 struct lejp_ctx { 219 220 /* sorted by type for most compact alignment 221 * 222 * pointers 223 */ 224 void *user; 225 226 /* arrays */ 227 228 struct _lejp_parsing_stack pst[LEJP_MAX_PARSING_STACK_DEPTH]; 229 struct _lejp_stack st[LEJP_MAX_DEPTH]; 230 uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */ 231 uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */ 232 char path[LEJP_MAX_PATH]; 233 char buf[LEJP_STRING_CHUNK + 1]; 234 235 /* size_t */ 236 237 size_t path_stride; /* 0 means default ptr size, else stride */ 238 239 /* int */ 240 241 uint32_t line; 242 243 /* short */ 244 245 uint16_t uni; 246 247 /* char */ 248 249 uint8_t npos; 250 uint8_t dcount; 251 uint8_t f; 252 uint8_t sp; /* stack head */ 253 uint8_t ipos; /* index stack depth */ 254 uint8_t count_paths; 255 uint8_t path_match; 256 uint8_t path_match_len; 257 uint8_t wildcount; 258 uint8_t pst_sp; /* parsing stack head */ 259 uint8_t outer_array; 260 }; 261 262 LWS_VISIBLE LWS_EXTERN void 263 lejp_construct(struct lejp_ctx *ctx, 264 signed char (*callback)(struct lejp_ctx *ctx, char reason), 265 void *user, const char * const *paths, unsigned char paths_count); 266 267 LWS_VISIBLE LWS_EXTERN void 268 lejp_destruct(struct lejp_ctx *ctx); 269 270 LWS_VISIBLE LWS_EXTERN int 271 lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len); 272 273 LWS_VISIBLE LWS_EXTERN void 274 lejp_change_callback(struct lejp_ctx *ctx, 275 signed char (*callback)(struct lejp_ctx *ctx, char reason)); 276 277 /* 278 * push the current paths / paths_count and lejp_cb to a stack in the ctx, and 279 * start using the new ones 280 */ 281 LWS_VISIBLE LWS_EXTERN int 282 lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths, 283 unsigned char paths_count, lejp_callback lejp_cb); 284 285 /* 286 * pop the previously used paths / paths_count and lejp_cb, and continue 287 * parsing using those as before 288 */ 289 LWS_VISIBLE LWS_EXTERN int 290 lejp_parser_pop(struct lejp_ctx *ctx); 291 292 /* exported for use when reevaluating a path for use with a subcontext */ 293 LWS_VISIBLE LWS_EXTERN void 294 lejp_check_path_match(struct lejp_ctx *ctx); 295 296 LWS_VISIBLE LWS_EXTERN int 297 lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len); 298 299 LWS_VISIBLE LWS_EXTERN const char * 300 lejp_error_to_string(int e); 301 //@} 302