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
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
LEJPCB_USER_START
= 32,
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),
200
LEJP_SEEN_POST_POINT
= (1 << 2),
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
211
struct
_lejp_parsing_stack
{
212
void
*
user
;
/* private to the stack level */
213
signed
char
(*
callback
)(
struct
lejp_ctx
*ctx,
char
reason);
214
const
char
*
const
*
paths
;
215
uint8_t
count_paths
;
216
uint8_t
ppos
;
217
uint8_t
path_match
;
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
230
struct
_lejp_parsing_stack
pst
[
LEJP_MAX_PARSING_STACK_DEPTH
];
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 */
234
char
path
[
LEJP_MAX_PATH
];
235
char
buf
[
LEJP_STRING_CHUNK
+ 1];
236
237
/* size_t */
238
239
size_t
path_stride
;
/* 0 means default ptr size, else stride */
240
241
/* int */
242
243
uint32_t
line
;
244
245
/* short */
246
247
uint16_t
uni
;
248
#
define
LEJP_FLAG_FEAT_OBJECT_INDEXES
(
1
<<
0
)
249
#
define
LEJP_FLAG_FEAT_LEADING_WC
(
1
<<
1
)
250
#
define
LEJP_FLAG_LATEST
251
(
LEJP_FLAG_FEAT_OBJECT_INDEXES
|
252
LEJP_FLAG_FEAT_LEADING_WC
)
253
uint16_t
flags
;
254
255
/* char */
256
257
uint8_t
npos
;
258
uint8_t
dcount
;
259
uint8_t
f
;
260
uint8_t
sp
;
/* stack head */
261
uint8_t
ipos
;
/* index stack depth */
262
uint8_t
count_paths
;
263
uint8_t
path_match
;
264
uint8_t
path_match_len
;
265
uint8_t
wildcount
;
266
uint8_t
pst_sp
;
/* parsing stack head */
267
uint8_t
outer_array
;
268
};
269
270
LWS_VISIBLE LWS_EXTERN
void
271
lejp_construct
(
struct
lejp_ctx
*ctx,
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
282
lejp_change_callback
(
struct
lejp_ctx
*ctx,
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
298
lejp_parser_pop
(
struct
lejp_ctx
*ctx);
299
300
/* exported for use when reevaluating a path for use with a subcontext */
301
LWS_VISIBLE LWS_EXTERN
void
302
lejp_check_path_match
(
struct
lejp_ctx
*ctx);
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
*
308
lejp_error_to_string
(
int
e);
309
//@}
include
libwebsockets
lws-lejp.h
Generated on Fri Jun 17 2022 04:56:33 for libwebsockets by
1.9.1