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//@{
32struct lejp_ctx;
33struct lwsac;
34
35#if !defined(LWS_ARRAY_SIZE)
36#define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
37#endif
38#define LEJP_FLAG_WS_KEEP 64
39#define LEJP_FLAG_WS_COMMENTLINE 32
40
41enum lejp_states {
42 LEJP_IDLE = 0,
43 LEJP_MEMBERS = 1,
44 LEJP_M_P = 2,
45 LEJP_MP_STRING = LEJP_FLAG_WS_KEEP | 3,
46 LEJP_MP_STRING_ESC = LEJP_FLAG_WS_KEEP | 4,
47 LEJP_MP_STRING_ESC_U1 = LEJP_FLAG_WS_KEEP | 5,
48 LEJP_MP_STRING_ESC_U2 = LEJP_FLAG_WS_KEEP | 6,
49 LEJP_MP_STRING_ESC_U3 = LEJP_FLAG_WS_KEEP | 7,
50 LEJP_MP_STRING_ESC_U4 = LEJP_FLAG_WS_KEEP | 8,
51 LEJP_MP_DELIM = 9,
52 LEJP_MP_VALUE = 10,
53 LEJP_MP_VALUE_NUM_INT = LEJP_FLAG_WS_KEEP | 11,
54 LEJP_MP_VALUE_NUM_EXP = LEJP_FLAG_WS_KEEP | 12,
55 LEJP_MP_VALUE_TOK = LEJP_FLAG_WS_KEEP | 13,
56 LEJP_MP_COMMA_OR_END = 14,
57 LEJP_MP_ARRAY_END = 15,
58};
59
60enum lejp_reasons {
61 LEJP_CONTINUE = -1,
62 LEJP_REJECT_IDLE_NO_BRACE = -2,
63 LEJP_REJECT_MEMBERS_NO_CLOSE = -3,
64 LEJP_REJECT_MP_NO_OPEN_QUOTE = -4,
65 LEJP_REJECT_MP_STRING_UNDERRUN = -5,
66 LEJP_REJECT_MP_ILLEGAL_CTRL = -6,
67 LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC = -7,
68 LEJP_REJECT_ILLEGAL_HEX = -8,
69 LEJP_REJECT_MP_DELIM_MISSING_COLON = -9,
70 LEJP_REJECT_MP_DELIM_BAD_VALUE_START = -10,
71 LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC = -11,
72 LEJP_REJECT_MP_VAL_NUM_FORMAT = -12,
73 LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP = -13,
74 LEJP_REJECT_MP_VAL_TOK_UNKNOWN = -14,
75 LEJP_REJECT_MP_C_OR_E_UNDERF = -15,
76 LEJP_REJECT_MP_C_OR_E_NOTARRAY = -16,
77 LEJP_REJECT_MP_ARRAY_END_MISSING = -17,
78 LEJP_REJECT_STACK_OVERFLOW = -18,
79 LEJP_REJECT_MP_DELIM_ISTACK = -19,
80 LEJP_REJECT_NUM_TOO_LONG = -20,
81 LEJP_REJECT_MP_C_OR_E_NEITHER = -21,
82 LEJP_REJECT_UNKNOWN = -22,
83 LEJP_REJECT_CALLBACK = -23
84};
85
86#define LEJP_FLAG_CB_IS_VALUE 64
87
88enum lejp_callbacks {
89 LEJPCB_CONSTRUCTED = 0,
90 LEJPCB_DESTRUCTED = 1,
91
92 LEJPCB_START = 2,
93 LEJPCB_COMPLETE = 3,
94 LEJPCB_FAILED = 4,
95
96 LEJPCB_PAIR_NAME = 5,
97
98 LEJPCB_VAL_TRUE = LEJP_FLAG_CB_IS_VALUE | 6,
99 LEJPCB_VAL_FALSE = LEJP_FLAG_CB_IS_VALUE | 7,
100 LEJPCB_VAL_NULL = LEJP_FLAG_CB_IS_VALUE | 8,
101 LEJPCB_VAL_NUM_INT = LEJP_FLAG_CB_IS_VALUE | 9,
102 LEJPCB_VAL_NUM_FLOAT = LEJP_FLAG_CB_IS_VALUE | 10,
103 LEJPCB_VAL_STR_START = 11, /* notice handle separately */
104 LEJPCB_VAL_STR_CHUNK = LEJP_FLAG_CB_IS_VALUE | 12,
105 LEJPCB_VAL_STR_END = LEJP_FLAG_CB_IS_VALUE | 13,
106
107 LEJPCB_ARRAY_START = 14,
108 LEJPCB_ARRAY_END = 15,
109
110 LEJPCB_OBJECT_START = 16,
111 LEJPCB_OBJECT_END = 17,
112
113 LEJPCB_USER_START = 32,
114};
115
116/**
117 * _lejp_callback() - User parser actions
118 * \param ctx: LEJP context
119 * \param reason: Callback reason
120 *
121 * Your user callback is associated with the context at construction time,
122 * and receives calls as the parsing progresses.
123 *
124 * All of the callbacks may be ignored and just return 0.
125 *
126 * The reasons it might get called, found in @reason, are:
127 *
128 * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to
129 * perform one-time allocation for the life of the context.
130 *
131 * LEJPCB_DESTRUCTED: The context is being destructed... if you made any
132 * allocations at construction-time, you can free them now
133 *
134 * LEJPCB_START: Parsing is beginning at the first byte of input
135 *
136 * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or
137 * positive return code from lejp_parse indicating the
138 * amount of unused bytes left in the input buffer
139 *
140 * LEJPCB_FAILED: Parsing failed. You'll get a negative error code
141 * returned from lejp_parse
142 *
143 * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed,
144 * this callback occurs. You can find the new name at
145 * the end of ctx->path[]
146 *
147 * LEJPCB_VAL_TRUE: The "true" value appeared
148 *
149 * LEJPCB_VAL_FALSE: The "false" value appeared
150 *
151 * LEJPCB_VAL_NULL: The "null" value appeared
152 *
153 * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf
154 *
155 * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf
156 *
157 * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet
158 *
159 * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not
160 * the end of the string. We produce this to spill the
161 * intermediate buffer to the user code, so we can handle
162 * huge JSON strings using only the small buffer in the
163 * ctx. If the whole JSON string fits in the ctx buffer,
164 * you won't get these callbacks.
165 *
166 * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the
167 * string is in ctx->buf.
168 *
169 * LEJPCB_ARRAY_START: An array started
170 *
171 * LEJPCB_ARRAY_END: An array ended
172 *
173 * LEJPCB_OBJECT_START: An object started
174 *
175 * LEJPCB_OBJECT_END: An object ended
176 */
177LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason);
178
179typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
180
181#ifndef LEJP_MAX_PARSING_STACK_DEPTH
182#define LEJP_MAX_PARSING_STACK_DEPTH 10
183#endif
184#ifndef LEJP_MAX_DEPTH
185#define LEJP_MAX_DEPTH 16
186#endif
187#ifndef LEJP_MAX_INDEX_DEPTH
188#define LEJP_MAX_INDEX_DEPTH 12
189#endif
190#ifndef LEJP_MAX_PATH
191#define LEJP_MAX_PATH 192
192#endif
193#ifndef LEJP_STRING_CHUNK
194/* must be >= 30 to assemble floats */
195#define LEJP_STRING_CHUNK 254
196#endif
197
198enum num_flags {
199 LEJP_SEEN_MINUS = (1 << 0),
200 LEJP_SEEN_POINT = (1 << 1),
201 LEJP_SEEN_POST_POINT = (1 << 2),
202 LEJP_SEEN_EXP = (1 << 3)
203};
204
205struct _lejp_stack {
206 char s; /* lejp_state stack*/
207 char p; /* path length */
208 char i; /* index array length */
209 char b; /* user bitfield */
210};
211
212struct _lejp_parsing_stack {
213 void *user; /* private to the stack level */
214 signed char (*callback)(struct lejp_ctx *ctx, char reason);
215 const char * const *paths;
216 uint8_t count_paths;
217 uint8_t ppos;
218 uint8_t path_match;
219};
220
221typedef struct lejp_string_piece {
222 struct lejp_string_piece *next;
223 const char *piece;
224 size_t len;
225} lejp_string_piece_t;
226
227typedef struct {
228 lejp_string_piece_t *sph;
229 lejp_string_piece_t **sp_next;
230 int pieces;
231 size_t asl;
232 char *fp;
233} lejp_string_unifier_t;
234
235struct lejp_ctx {
236
237 /* sorted by type for most compact alignment
238 *
239 * pointers
240 */
241 void *user;
242
243 /* arrays */
244
245 struct _lejp_parsing_stack pst[LEJP_MAX_PARSING_STACK_DEPTH];
246 struct _lejp_stack st[LEJP_MAX_DEPTH];
247 uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
248 uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
249 char path[LEJP_MAX_PATH];
250 char buf[LEJP_STRING_CHUNK + 1];
251
252 lejp_string_unifier_t su;
253
254 /* size_t */
255
256 size_t path_stride; /* 0 means default ptr size, else stride */
257
258 /* int */
259
260 uint32_t line;
261
262 /* short */
263
264 uint16_t uni;
265#define LEJP_FLAG_FEAT_OBJECT_INDEXES (1 << 0)
266#define LEJP_FLAG_FEAT_LEADING_WC (1 << 1)
267#define LEJP_FLAG_LATEST \
268 (LEJP_FLAG_FEAT_OBJECT_INDEXES | \
269 LEJP_FLAG_FEAT_LEADING_WC)
270 uint16_t flags;
271
272 /* char */
273
274 uint8_t npos;
275 uint8_t dcount;
276 uint8_t f;
277 uint8_t sp; /* stack head */
278 uint8_t ipos; /* index stack depth */
279 uint8_t count_paths;
280 uint8_t path_match;
281 uint8_t path_match_len;
282 uint8_t wildcount;
283 uint8_t pst_sp; /* parsing stack head */
284 uint8_t outer_array;
285};
286
287LWS_VISIBLE LWS_EXTERN void
288lejp_construct(struct lejp_ctx *ctx,
289 signed char (*callback)(struct lejp_ctx *ctx, char reason),
290 void *user, const char * const *paths, unsigned char paths_count);
291
292LWS_VISIBLE LWS_EXTERN void
293lejp_destruct(struct lejp_ctx *ctx);
294
295LWS_VISIBLE LWS_EXTERN int
296lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
297
298LWS_VISIBLE LWS_EXTERN void
299lejp_change_callback(struct lejp_ctx *ctx,
300 signed char (*callback)(struct lejp_ctx *ctx, char reason));
301
302/*
303 * push the current paths / paths_count and lejp_cb to a stack in the ctx, and
304 * start using the new ones
305 */
306LWS_VISIBLE LWS_EXTERN int
307lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
308 unsigned char paths_count, lejp_callback lejp_cb);
309
310/*
311 * pop the previously used paths / paths_count and lejp_cb, and continue
312 * parsing using those as before
313 */
314LWS_VISIBLE LWS_EXTERN int
315lejp_parser_pop(struct lejp_ctx *ctx);
316
317/* exported for use when reevaluating a path for use with a subcontext */
318LWS_VISIBLE LWS_EXTERN void
319lejp_check_path_match(struct lejp_ctx *ctx);
320
321LWS_VISIBLE LWS_EXTERN int
322lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
323
324LWS_VISIBLE LWS_EXTERN const char *
325lejp_error_to_string(int e);
326
327LWS_VISIBLE LWS_EXTERN int
328lejp_string_unify(struct lejp_ctx *ctx, struct lwsac **ac);
329
330LWS_VISIBLE LWS_EXTERN int
331lejp_string_unify_part(struct lejp_ctx *ctx, struct lwsac **ac, char reason);
332//@}
333