forked from vincenthz/libjson
-
Notifications
You must be signed in to change notification settings - Fork 0
/
json.h
227 lines (189 loc) · 7.4 KB
/
json.h
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
/*
* Copyright (C) 2009-2011 Vincent Hanquez <vincent@snarc.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 or version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef JSON_H
#define JSON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#if defined(_MSC_VER) && (_MSC_VER < 1600)
// MSVC does not include stdint.h before version 10.0
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
#define JSON_MAJOR 1
#define JSON_MINOR 0
#define JSON_VERSION (JSON_MAJOR * 100 + JSON_MINOR)
typedef enum
{
JSON_NONE,
JSON_ARRAY_BEGIN,
JSON_OBJECT_BEGIN,
JSON_ARRAY_END,
JSON_OBJECT_END,
JSON_INT,
JSON_FLOAT,
JSON_STRING,
JSON_KEY,
JSON_TRUE,
JSON_FALSE,
JSON_NULL,
JSON_BSTRING,
} json_type;
typedef enum
{
/* SUCCESS = 0 */
/* running out of memory */
JSON_ERROR_NO_MEMORY = 1,
/* character < 32, except space newline tab */
JSON_ERROR_BAD_CHAR,
/* trying to pop more object/array than pushed on the stack */
JSON_ERROR_POP_EMPTY,
/* trying to pop wrong type of mode. popping array in object mode, vice versa */
JSON_ERROR_POP_UNEXPECTED_MODE,
/* reach nesting limit on stack */
JSON_ERROR_NESTING_LIMIT,
/* reach data limit on buffer */
JSON_ERROR_DATA_LIMIT,
/* comment are not allowed with current configuration */
JSON_ERROR_COMMENT_NOT_ALLOWED,
/* unexpected char in the current parser context */
JSON_ERROR_UNEXPECTED_CHAR,
/* unicode low surrogate missing after high surrogate */
JSON_ERROR_UNICODE_MISSING_LOW_SURROGATE,
/* unicode low surrogate missing without previous high surrogate */
JSON_ERROR_UNICODE_UNEXPECTED_LOW_SURROGATE,
/* found a comma not in structure (array/object) */
JSON_ERROR_COMMA_OUT_OF_STRUCTURE,
/* callback returns error */
JSON_ERROR_CALLBACK,
/* utf8 stream is invalid */
JSON_ERROR_UTF8,
} json_error;
#define LIBJSON_DEFAULT_STACK_SIZE 256
#define LIBJSON_DEFAULT_BUFFER_SIZE 4096
typedef int (*json_parser_callback)(void *userdata, int type, const char *data, uint32_t length);
typedef int (*json_printer_callback)(void *userdata, const char *s, uint32_t length);
typedef struct {
uint32_t buffer_initial_size;
uint32_t max_nesting;
uint32_t max_data;
int allow_c_comments;
int allow_yaml_comments;
void * (*user_calloc)(size_t nmemb, size_t size);
void * (*user_realloc)(void *ptr, size_t size);
} json_config;
typedef struct json_parser {
json_config config;
/* SAJ callback */
json_parser_callback callback;
void *userdata;
/* parser state */
uint8_t state;
uint8_t save_state;
uint8_t expecting_key;
uint8_t utf8_multibyte_left;
uint16_t unicode_multi;
json_type type;
/* state stack */
uint8_t *stack;
uint32_t stack_offset;
uint32_t stack_size;
/* parse buffer */
char *buffer;
uint32_t buffer_size;
uint32_t buffer_offset;
} json_parser;
typedef struct json_printer {
json_printer_callback callback;
void *userdata;
char *indentstr;
int indentlevel;
int afterkey;
int enter_object;
int first;
} json_printer;
/** json_parser_init initialize a parser structure taking a config,
* a config and its userdata.
* return JSON_ERROR_NO_MEMORY if memory allocation failed or SUCCESS. */
int json_parser_init(json_parser *parser, json_config *cfg,
json_parser_callback callback, void *userdata);
/** json_parser_free freed memory structure allocated by the parser */
int json_parser_free(json_parser *parser);
/** json_parser_string append a string s with a specific length to the parser
* return 0 if everything went ok, a JSON_ERROR_* otherwise.
* the user can supplied a valid processed pointer that will
* be fill with the number of processed characters before returning */
int json_parser_string(json_parser *parser, const char *string,
uint32_t length, uint32_t *processed);
/** json_parser_char append one single char to the parser
* return 0 if everything went ok, a JSON_ERROR_* otherwise */
int json_parser_char(json_parser *parser, unsigned char next_char);
/** json_parser_is_done return 0 is the parser isn't in a finish state. !0 if it is */
int json_parser_is_done(json_parser *parser);
/** json_print_init initialize a printer context. always succeed */
int json_print_init(json_printer *printer, json_printer_callback callback, void *userdata);
/** json_print_free free a printer context
* doesn't do anything now, but in future print_init could allocate memory */
int json_print_free(json_printer *printer);
/** json_print_pretty pretty print the passed argument (type/data/length). */
int json_print_pretty(json_printer *printer, int type, const char *data, uint32_t length);
/** json_print_raw prints without eye candy the passed argument (type/data/length). */
int json_print_raw(json_printer *printer, int type, const char *data, uint32_t length);
/** json_print_args takes multiple types and pass them to the printer function
* array, object and constants doesn't take a string and length argument.
* int, float, key, string need to be followed by a pointer to char and then a length.
* if the length argument is -1, then the strlen function will use on the string argument.
* the function call should always be terminated by -1 */
int json_print_args(json_printer *, int (*f)(json_printer *, int, const char *, uint32_t), ...);
/** callback from the parser_dom callback to create object and array */
typedef void * (*json_parser_dom_create_structure)(int, int);
/** callback from the parser_dom callback to create data values */
typedef void * (*json_parser_dom_create_data)(int, const char *, uint32_t);
/** callback from the parser helper callback to append a value to an object or array value
* append(parent, key, key_length, val); */
typedef int (*json_parser_dom_append)(void *, char *, uint32_t, void *);
/** the json_parser_dom permits to create a DOM like tree easily through the
* use of 3 callbacks where the user can choose the representation of the JSON values */
typedef struct json_parser_dom
{
/* object stack */
struct stack_elem { void *val; char *key; uint32_t key_length; } *stack;
uint32_t stack_size;
uint32_t stack_offset;
/* overridable memory allocator */
void * (*user_calloc)(size_t nmemb, size_t size);
void * (*user_realloc)(void *ptr, size_t size);
/* returned root structure (object or array) */
void *root_structure;
/* callbacks */
json_parser_dom_create_structure create_structure;
json_parser_dom_create_data create_data;
json_parser_dom_append append;
} json_parser_dom;
/** initialize a parser dom structure with the necessary callbacks */
int json_parser_dom_init(json_parser_dom *helper,
json_parser_dom_create_structure create_structure,
json_parser_dom_create_data create_data,
json_parser_dom_append append);
/** free memory allocated by the DOM callback helper */
int json_parser_dom_free(json_parser_dom *ctx);
/** helper to parser callback that arrange parsing events into comprehensive JSON data structure */
int json_parser_dom_callback(void *userdata, int type, const char *data, uint32_t length);
#ifdef __cplusplus
}
#endif
#endif /* JSON_H */