-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathjparse.3
379 lines (378 loc) · 12.2 KB
/
jparse.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
.\" section 3 man page for jparse
.\"
.\" This man page was first written by Cody Boone Ferguson for the IOCCC
.\" in 2023.
.\"
.\" Humour impairment is not virtue nor is it a vice, it's just plain
.\" wrong: almost as wrong as JSON spec mis-features and C++ obfuscation! :-)
.\"
.\" "Share and Enjoy!"
.\" -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-)
.\"
.TH jparse 3 "17 January 2025" "jparse"
.SH NAME
.BR parse_json() \|,
.BR parse_json_str() \|,
.BR parse_json_stream() \|,
.BR parse_json_file() \|,
.BR json_tree_free(tree() \|,
.BR json_dbg_allowed() \|,
.BR json_warn_allowed() \|,
.BR json_err_allowed() \|,
.BR json_dbg()
\- JSON parsing library
.SH SYNOPSIS
\fB#include <jparse/jparse.h>\fP
.sp
.B "extern const char *const jparse_library_version; /* jparse library version format: major.minor YYYY-MM-DD */"
.br
.B "extern const char *const jparse_utils_version; /* jparse utils (util.c) version format: major.minor YYYY-MM-DD */"
.br
.B "extern const char *const jparse_utf8_version; /* jparse utf8 version format: major.minor YYYY-MM-DD */"
.br
.B "extern const char *const jparse_version; /* jparse tool version format: major.minor YYYY-MM-DD */"
.sp
\fB#define VALID_JSON_NODE(item) ((item) != NULL && (((item)->parsed == true) || ((item)->converted == true)))\fP
.br
\fB#define PARSED_JSON_NODE(item) ((item) != NULL && ((item)->parsed == true))\fP
.br
\fB#define CONVERTED_PARSED_JSON_NODE(item) ((item) != NULL && (((item)->parsed == true) && ((item)->converted == true)))\fP
.br
\fB#define CONVERTED_JSON_NODE(item) ((item) != NULL && (item)->converted == true)\fP
.sp
.B "extern struct json *parse_json(char const *ptr, size_t len, char const *filename, bool *is_valid);"
.br
.B "extern struct json *parse_json_str(char const *ptr, size_t len, bool *is_valid);"
.br
.B "extern struct json *parse_json_stream(FILE *stream, char const *filename, bool *is_valid);"
.br
.B "extern struct json *parse_json_file(char const *filename, bool *is_valid);"
.sp
.B "extern void json_tree_free(struct json *node, unsigned int max_depth, ...);"
.sp
.B "extern char const *json_get_type_str(struct json *node, bool encoded);"
.sp
.B "extern bool json_dbg_allowed(int json_dbg_lvl);"
.br
.B "extern bool json_warn_allowed(void);"
.br
.B "extern bool json_err_allowed(void);"
.br
.B "extern void json_dbg(int json_dbg_lvl, char const *name, const char *fmt, ...)"
.SH DESCRIPTION
The
.B jparse
library provides a way for C applications to parse JSON in a file (including stdin) or a string, returning a tree (a
.B struct json *\&
\c tree)
of the parsed JSON that one may then traverse or manipulate in many ways.
The functions to actually parse the JSON, as well as debug output functions (although not in great detail but rather just what they are), are described in this man page.
.SS Parsing functions
The function
.BR parse_json ()
parses a JSON string
.I ptr
of length
.IR len .
The
.I ptr
is a pointer to the start of the JSON data, so that one may scan part of a document, should they wish.
The function will scan up to
.I len
bytes so that one may scan part of a document or string, which might have other kinds of data, in other words is only partly JSON.
This function takes a
.I filename
arg which is used for messages, in particular error messages.
If the wrong filename is specified, it will affect output as this function will not try and open the file; for that, use the function
.BR parse_json_file (),
described later.
.PP
If
.I filename
is not NULL and is an empty string, then it will set the filename to
.BR \*(lq-\*(rq ,
indicating that the input comes from stdin.
If it is a NULL pointer, the filename in the parser extra data will be set to NULL, and messages will not show a filename.
.PP
The variable
.BR is_valid ,
which is a pointer to a bool, must not be NULL, and it is an error if it is.
Its purpose, along with the return value, is to indicate to the caller if the JSON is invalid.
If in the calling function
.B is_valid
is false after calling this function, then the
.B struct json *
returned should be NULL, although it is best practice to check if the
.B struct json *
is NULL and if
.B is_valid
is false.
The function will return the parsed JSON as a tree of type
.BR struct\ json\ * .
If
.B ptr
is NULL or if the block cannot be scanned, a blank JSON tree is returned instead.
.PP
The function
.BR parse_json_str ()
is like
.BR parse_json ()
except that it does not take a filename; instead it passes in a NULL filename to
.BR parse_json (),
which affects the error message to not say it is a filename: rather it is a string, as described above.
The function
.BR parse_json_str ()
is essentially a wrapper to
.BR parse_json ()
where the filename arg is a NULL string, to simplify parsing a string.
.sp
The function
.BR parse_json_stream ()
is like
.BR parse_json ()
except that it parses an entire
.B FILE *
and does not accept a number of bytes to scan.
The
.I filename
is for messages and is not used to determine what file to open as the stream should already be open.
If you wish to do that you should use the
.BR parse_json_file ()
function instead, which takes a filename and the
.B is_valid
variable.
Unless
.I stream
is
.B stdin
the state of it should be considered unsafe to use after the return of the function as it will be closed.
.PP
The
.BR parse_json_file ()
function will try and open the filename given in
.B filename
and then, as long as it can be opened, pass the
.B FILE *
to
.BR parse_json_stream ().
.SS Freeing the struct json * tree
.PP
After you are done with working with the tree, you should free it, using the
.BR json_tree_free ()
function, which takes a
.B struct json *
and a maximum depth to descend.
The macro
.BR JSON_DEFAULT_MAX_DEPTH ,
which is defined as 256, is a good value to use; on the other hand, if you do need an infinite depth, you can use
.BR JSON_INFINITE_DEPTH ,
which is 0.
After you use this function, you should still free the tree with
.BR free (3),
and then set the pointer to NULL.
.SS Matching functions
The
.BR json_get_type_str ()
returns a
.B char const *
with what was matched in the parser.
Depending on if the
.I encoded
boolean is true or not, it returns the encoded or decoded string, assuming the JSON node type has a distinction.
If the type is an object, array, elements or some unknown value (i.e. \fBJTYPE_OBJECT\fP, \fBJTYPE_ARRAY\fP, \fBJTYPE_ELEMENTS\fP or something unexpected, a NULL pointer is returned, so the caller should be aware of this before trying to print it, unless they know for a fact the type is valid.
.SS Debug, warn and error functions
.PP
The function
.BR json_dbg_allowed ()
will return true if debug output would be displayed at the verbosity level
.IR json_dbg_lvl .
.br
The functions
.BR json_warn_allowed ()
and
.BR json_err_allowed ()
will return true if warnings and error output is allowed, respectively.
.sp
The function
.BR json_dbg ()
allows for your application to give debug information to the user.
The
.I json_dbg_lvl
is the verbosity level which, along with the
.I dbg_output_allowed
boolean, will determine if the output is to be printed.
As long as
.I dbg_output_allowed
is true and
.I json_dbg_lvl
is either
.B JSON_DBG_FORCED
or <= the
.I json_verbosity_level
then the output will be displayed.
The
.I name
is the name you wish to provide to the function, whether it be your application name or the function name that called it.
The
.I fmt
is a
.BR printf (3)
style format argument.
.SS The json struct
.PP
The
.I json
structure is defined as:
.sp
.in +4n
.nf
struct json
{
enum item_type type; /* union item specifier */
union json_union {
.in +4n
struct json_number number; /* JTYPE_NUMBER - value is number (integer or floating point) */
struct json_string string; /* JTYPE_STRING - value is a string */
struct json_boolean boolean; /* JTYPE_BOOL - value is a JSON boolean */
struct json_null null; /* JTYPE_NULL - value is a JSON null value */
struct json_member member; /* JTYPE_MEMBER - value is a JSON member: name : value */
struct json_object object; /* JTYPE_OBJECT - value is a JSON { members } */
struct json_array array; /* JTYPE_ARRAY - value is a JSON [ elements ] */
struct json_elements elements; /* JTYPE_ELEMENTS - zero or more JSON values */
} item;
.in -4n
/*
* JSON parse tree links
*/
struct json *parent; /* parent node in the JSON parse tree, or NULL if tree root or unlinked */
};
.SS Checking for converted and/or parsed JSON nodes
.PP
Each JSON node struct has two booleans:
.B converted
and
.B parsed\c
\&.
The
.B converted
boolean indicates that the item could be converted whereas the
.B parsed
boolean indicates that the item could be parsed but it might or might not be converted.
It might be that it could not be converted but is parsable if it is a number string but the number is too big for the C types.
In this case the JSON can still be valid but the value is not converted.
This macro is used in the conversion routines and it is an error if both conversion and parsing fails.
If
.B converted
is true then
.B parsed
should be true too.
.PP
The macro
.B VALID_JSON_NODE
checks that either of the JSON node booleans,
.B converted
and
.B parsed\c
\&, are true.
.PP
The macro
.B PARSED_JSON_NODE
checks that the node's
.B parsed
boolean is true.
.PP
The macro
.B CONVERTED_PARSED_JSON_NODE
checks that the node's
.B converted
boolean is true and that the
.B parsed
boolean is true.
.PP
The macro
.B CONVERTED_JSON_NODE
checks that the node's
.B converted
boolean is true.
.SS Version strings
The string
.BR jparse_library_version ,
which points to
.BR JPARSE_LIBRARY_VERSION ,
is the current version of the jparse library itself.
The string
.BR jparse_utils_version ,
which points to
.BR JPARSE_UTILS_VERSION ,
is the current jparse utils (util.c) version.
The string
.BR jparse_utf8_version ,
which points to
.BR JPARSE_UTF8_VERSION ,
is the current jparse UTF\-8 version.
The string
.BR jparse_version ,
which points to
.BR JPARSE_VERSION ,
is the current version of the
.B jparse
tool.
.SH RETURN VALUE
.PP
The functions
.BR parse_json (),
.BR parse_json_str (),
.BR parse_json_stream ()
and
.BR parse_json_file ()
return a
.B struct json *
which is either blank (unset type) or, if the parse was successful, a tree of the entire parsed JSON.
Otherwise, if the JSON is invalid, a NULL pointer is returned, and the bool
.B is_valid
in the calling function is set to false (this also happens if an unset type is returned).
Certain error conditions will prevent the function from returning.
.PP
The functions
.BR json_dbg_allowed (),
.BR json_warn_allowed (),
and
.BR json_err_allowed ()
will return true if debug, warn or error messages are allowed, respectively, and otherwise false.
.SH NOTES
.PP
This JSON parser was written as a collaboration between Cody Boone Ferguson and Landon Curt Noll, one of the IOCCC Judges, to support
IOCCC28 and beyond.
.PP
For more detailed history that goes beyond this humble man page we recommend you check
.BR jparse (1),
the
.IR README.md ,
and the GitHub git log as well as reading the source code (or not :\-) ).
Understand that by source we refer to the
.I jparse.l
and
.I jparse.y
files: we do NOT recommend you read the generated code!
This is because doing so might give you nightmares and cause other horrible symptoms. :-)
See the apology at the top of the generated files or look directly at
.I sorry.tm.ca.h
instead.
.SS Valid JSON
In the case that a value cannot be converted but it is valid JSON the parser will still successfully validate the JSON.
This might happen if, for example, a number is too big for the C types, but it is still valid JSON; in this case the parse tree is valid and not NULL.
See the macros in the
.B Checking for converted and/or parsed JSON nodes
section above for details.
.PP
.SH BUGS
Although error reporting does have locations it is only line numbers and columns.
Additionally the column can be misleading because of characters that take up more than one column but are counted as just one (say, because of tabs).
.sp
Although the scanner and parser are re-entrant only one parse at one time in a process has been tested.
.sp
If it's not clear this means that having more than one parse active in the same process at the same time is not tested so even though it should be okay there might be some issues that have yet to be discovered.
.SH SEE ALSO
.BR jparse (1),
.BR jstrdecode (1),
.BR jstrencode (1)