libwebsockets
Lightweight C library for HTML5 websockets
lws-lejp.h
Go to the documentation of this file.
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 
41  LEJP_IDLE = 0,
43  LEJP_M_P = 2,
57 };
58 
83 };
84 
85 #define LEJP_FLAG_CB_IS_VALUE 64
86 
90 
94 
96 
102  LEJPCB_VAL_STR_START = 11, /* notice handle separately */
105 
108 
111 
113 };
114 
115 /**
116  * _lejp_callback() - User parser actions
117  * \param ctx: LEJP context
118  * \param reason: Callback reason
119  *
120  * Your user callback is associated with the context at construction time,
121  * and receives calls as the parsing progresses.
122  *
123  * All of the callbacks may be ignored and just return 0.
124  *
125  * The reasons it might get called, found in @reason, are:
126  *
127  * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to
128  * perform one-time allocation for the life of the context.
129  *
130  * LEJPCB_DESTRUCTED: The context is being destructed... if you made any
131  * allocations at construction-time, you can free them now
132  *
133  * LEJPCB_START: Parsing is beginning at the first byte of input
134  *
135  * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or
136  * positive return code from lejp_parse indicating the
137  * amount of unused bytes left in the input buffer
138  *
139  * LEJPCB_FAILED: Parsing failed. You'll get a negative error code
140  * returned from lejp_parse
141  *
142  * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed,
143  * this callback occurs. You can find the new name at
144  * the end of ctx->path[]
145  *
146  * LEJPCB_VAL_TRUE: The "true" value appeared
147  *
148  * LEJPCB_VAL_FALSE: The "false" value appeared
149  *
150  * LEJPCB_VAL_NULL: The "null" value appeared
151  *
152  * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf
153  *
154  * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf
155  *
156  * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet
157  *
158  * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not
159  * the end of the string. We produce this to spill the
160  * intermediate buffer to the user code, so we can handle
161  * huge JSON strings using only the small buffer in the
162  * ctx. If the whole JSON string fits in the ctx buffer,
163  * you won't get these callbacks.
164  *
165  * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the
166  * string is in ctx->buf.
167  *
168  * LEJPCB_ARRAY_START: An array started
169  *
170  * LEJPCB_ARRAY_END: An array ended
171  *
172  * LEJPCB_OBJECT_START: An object started
173  *
174  * LEJPCB_OBJECT_END: An object ended
175  */
176 LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason);
177 
178 typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
179 
180 #ifndef LEJP_MAX_PARSING_STACK_DEPTH
181 #define LEJP_MAX_PARSING_STACK_DEPTH 8
182 #endif
183 #ifndef LEJP_MAX_DEPTH
184 #define LEJP_MAX_DEPTH 16
185 #endif
186 #ifndef LEJP_MAX_INDEX_DEPTH
187 #define LEJP_MAX_INDEX_DEPTH 12
188 #endif
189 #ifndef LEJP_MAX_PATH
190 #define LEJP_MAX_PATH 192
191 #endif
192 #ifndef LEJP_STRING_CHUNK
193 /* must be >= 30 to assemble floats */
194 #define LEJP_STRING_CHUNK 254
195 #endif
196 
197 enum num_flags {
198  LEJP_SEEN_MINUS = (1 << 0),
199  LEJP_SEEN_POINT = (1 << 1),
201  LEJP_SEEN_EXP = (1 << 3)
202 };
203 
204 struct _lejp_stack {
205  char s; /* lejp_state stack*/
206  char p; /* path length */
207  char i; /* index array length */
208  char b; /* user bitfield */
209 };
210 
212  void *user; /* private to the stack level */
213  signed char (*callback)(struct lejp_ctx *ctx, char reason);
214  const char * const *paths;
218 };
219 
220 struct lejp_ctx {
221 
222  /* sorted by type for most compact alignment
223  *
224  * pointers
225  */
226  void *user;
227 
228  /* arrays */
229 
231  struct _lejp_stack st[LEJP_MAX_DEPTH];
232  uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
233  uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
236 
237  /* size_t */
238 
239  size_t path_stride; /* 0 means default ptr size, else stride */
240 
241  /* int */
242 
244 
245  /* short */
246 
248 #define LEJP_FLAG_FEAT_OBJECT_INDEXES (1 << 0)
249 #define LEJP_FLAG_FEAT_LEADING_WC (1 << 1)
250 #define LEJP_FLAG_LATEST
254 
255  /* char */
256 
260  uint8_t sp; /* stack head */
261  uint8_t ipos; /* index stack depth */
266  uint8_t pst_sp; /* parsing stack head */
268 };
269 
270 LWS_VISIBLE LWS_EXTERN void
272  signed char (*callback)(struct lejp_ctx *ctx, char reason),
273  void *user, const char * const *paths, unsigned char paths_count);
274 
275 LWS_VISIBLE LWS_EXTERN void
276 lejp_destruct(struct lejp_ctx *ctx);
277 
278 LWS_VISIBLE LWS_EXTERN int
279 lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
280 
281 LWS_VISIBLE LWS_EXTERN void
283  signed char (*callback)(struct lejp_ctx *ctx, char reason));
284 
285 /*
286  * push the current paths / paths_count and lejp_cb to a stack in the ctx, and
287  * start using the new ones
288  */
289 LWS_VISIBLE LWS_EXTERN int
290 lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
291  unsigned char paths_count, lejp_callback lejp_cb);
292 
293 /*
294  * pop the previously used paths / paths_count and lejp_cb, and continue
295  * parsing using those as before
296  */
297 LWS_VISIBLE LWS_EXTERN int
299 
300 /* exported for use when reevaluating a path for use with a subcontext */
301 LWS_VISIBLE LWS_EXTERN void
303 
304 LWS_VISIBLE LWS_EXTERN int
305 lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
306 
307 LWS_VISIBLE LWS_EXTERN const char *
309 //@}