libwebsockets
Lightweight C library for HTML5 websockets
lws-lejp.h
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 
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 
173 LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason);
174 
175 typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
176 
177 #ifndef LEJP_MAX_PARSING_STACK_DEPTH
178 #define LEJP_MAX_PARSING_STACK_DEPTH 5
179 #endif
180 #ifndef LEJP_MAX_DEPTH
181 #define LEJP_MAX_DEPTH 12
182 #endif
183 #ifndef LEJP_MAX_INDEX_DEPTH
184 #define LEJP_MAX_INDEX_DEPTH 5
185 #endif
186 #ifndef LEJP_MAX_PATH
187 #define LEJP_MAX_PATH 128
188 #endif
189 #ifndef LEJP_STRING_CHUNK
190 /* must be >= 30 to assemble floats */
191 #define LEJP_STRING_CHUNK 254
192 #endif
193 
194 enum num_flags {
195  LEJP_SEEN_MINUS = (1 << 0),
196  LEJP_SEEN_POINT = (1 << 1),
197  LEJP_SEEN_POST_POINT = (1 << 2),
198  LEJP_SEEN_EXP = (1 << 3)
199 };
200 
201 struct _lejp_stack {
202  char s; /* lejp_state stack*/
203  char p; /* path length */
204  char i; /* index array length */
205  char b; /* user bitfield */
206 };
207 
209  void *user; /* private to the stack level */
210  signed char (*callback)(struct lejp_ctx *ctx, char reason);
211  const char * const *paths;
212  uint8_t count_paths;
213  uint8_t ppos;
214  uint8_t path_match;
215 };
216 
217 struct lejp_ctx {
218 
219  /* sorted by type for most compact alignment
220  *
221  * pointers
222  */
223  void *user;
224 
225  /* arrays */
226 
227  struct _lejp_parsing_stack pst[LEJP_MAX_PARSING_STACK_DEPTH];
228  struct _lejp_stack st[LEJP_MAX_DEPTH];
229  uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
230  uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
231  char path[LEJP_MAX_PATH];
232  char buf[LEJP_STRING_CHUNK + 1];
233 
234  /* size_t */
235 
236  size_t path_stride; /* 0 means default ptr size, else stride */
237 
238  /* int */
239 
240  uint32_t line;
241 
242  /* short */
243 
244  uint16_t uni;
245 
246  /* char */
247 
248  uint8_t npos;
249  uint8_t dcount;
250  uint8_t f;
251  uint8_t sp; /* stack head */
252  uint8_t ipos; /* index stack depth */
253  uint8_t count_paths;
254  uint8_t path_match;
255  uint8_t path_match_len;
256  uint8_t wildcount;
257  uint8_t pst_sp; /* parsing stack head */
258 };
259 
260 LWS_VISIBLE LWS_EXTERN void
261 lejp_construct(struct lejp_ctx *ctx,
262  signed char (*callback)(struct lejp_ctx *ctx, char reason),
263  void *user, const char * const *paths, unsigned char paths_count);
264 
265 LWS_VISIBLE LWS_EXTERN void
266 lejp_destruct(struct lejp_ctx *ctx);
267 
268 LWS_VISIBLE LWS_EXTERN int
269 lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
270 
271 LWS_VISIBLE LWS_EXTERN void
272 lejp_change_callback(struct lejp_ctx *ctx,
273  signed char (*callback)(struct lejp_ctx *ctx, char reason));
274 
275 /*
276  * push the current paths / paths_count and lejp_cb to a stack in the ctx, and
277  * start using the new ones
278  */
279 LWS_VISIBLE LWS_EXTERN int
280 lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
281  unsigned char paths_count, lejp_callback lejp_cb);
282 
283 /*
284  * pop the previously used paths / paths_count and lejp_cb, and continue
285  * parsing using those as before
286  */
287 LWS_VISIBLE LWS_EXTERN int
288 lejp_parser_pop(struct lejp_ctx *ctx);
289 
290 /* exported for use when reevaluating a path for use with a subcontext */
291 LWS_VISIBLE LWS_EXTERN void
292 lejp_check_path_match(struct lejp_ctx *ctx);
293 
294 LWS_VISIBLE LWS_EXTERN int
295 lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
296 
297 LWS_VISIBLE LWS_EXTERN const char *
298 lejp_error_to_string(int e);
Definition: lws-lejp.h:201
Definition: lws-lejp.h:217
LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason)
Definition: lws-lejp.h:208