]> mj.ucw.cz Git - libucw.git/blob - ucw-json/json.h
JSON: Basic documentation
[libucw.git] / ucw-json / json.h
1 /*
2  *      UCW JSON Library
3  *
4  *      (c) 2015 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef _UCW_JSON_JSON_H
11 #define _UCW_JSON_JSON_H
12
13 #include <ucw/clists.h>
14 #include <ucw/slists.h>
15 #include <ucw/mempool.h>
16 #include <ucw/fastbuf.h>
17
18 #ifdef CONFIG_UCW_CLEAN_ABI
19 #define json_array_append ucw_json_array_append
20 #define json_delete ucw_json_delete
21 #define json_new ucw_json_new
22 #define json_new_array ucw_json_new_array
23 #define json_new_node ucw_json_new_node
24 #define json_new_object ucw_json_new_object
25 #define json_next_token ucw_json_next_token
26 #define json_next_value ucw_json_next_value
27 #define json_object_get ucw_json_object_get
28 #define json_object_set ucw_json_object_set
29 #define json_parse ucw_json_parse
30 #define json_peek_token ucw_json_peek_token
31 #define json_reset ucw_json_reset
32 #define json_set_input ucw_json_set_input
33 #define json_set_output ucw_json_set_output
34 #define json_write ucw_json_write
35 #define json_write_value ucw_json_write_value
36 #endif
37
38 /***
39  * === JSON library context
40  *
41  * FIXME: Document memory management
42  ***/
43
44 /**
45  * The context is represented a pointer to this structure.
46  * The fields marked with [*] are publicly accessible, the rest is private.
47  **/
48 struct json_context {
49   // Memory management
50   struct mempool *pool;
51   struct mempool_state init_state;
52
53   // Parser context
54   struct fastbuf *in_fb;
55   uint in_line;                         // [*] Current line number
56   uint in_column;                       // [*] Current column number
57   bool in_eof;                          //     End of file was encountered
58   struct json_node *next_token;
59   struct json_node *trivial_token;
60   int next_char;
61
62   // Formatter context
63   struct fastbuf *out_fb;
64   uint out_indent;
65   uint format_options;                  // [*] Formatting options (a combination of JSON_FORMAT_xxx)
66 };
67
68 /** Creates a new JSON context. **/
69 struct json_context *json_new(void);
70
71 /** Deletes a JSON context, deallocating all memory associated with it. **/
72 void json_delete(struct json_context *js);
73
74 /**
75  * Recycles a JSON context. All state is reset, allocated objects are freed.
76  * This is equivalent to mp_delete() followed by mp_new(), but it is faster
77  * and the address of the context is preserved.
78  **/
79 void json_reset(struct json_context *js);
80
81 /***
82  * === JSON values
83  *
84  * Each JSON value is represented by <<struct json_node,struct json_node>>,
85  * which is either an elementary value (null, boolean, number, string),
86  * or a container (array, object) pointing to other values.
87  *
88  * A value can belong to multiple containers simultaneously, so in general,
89  * the relationships between values need not form a tree, but a directed
90  * acyclic graph.
91  *
92  * You are allowed to read contents of nodes directly, but construction
93  * and modification of nodes must be always performed using the appropriate
94  * library functions.
95  ***/
96
97 /** Node types **/
98 enum json_node_type {
99   JSON_INVALID,
100   JSON_NULL,
101   JSON_BOOLEAN,
102   JSON_NUMBER,
103   JSON_STRING,
104   JSON_ARRAY,
105   JSON_OBJECT,
106   // These are not real nodes, but raw tokens.
107   // They are not present in the tree of values, but you may see them
108   // if you call json_next_token() and friends.
109   JSON_BEGIN_ARRAY,
110   JSON_END_ARRAY,
111   JSON_BEGIN_OBJECT,
112   JSON_END_OBJECT,
113   JSON_NAME_SEP,
114   JSON_VALUE_SEP,
115   JSON_EOF,
116 };
117
118 /** Each value is represented by a single node. **/
119 struct json_node {
120   enum json_node_type type;
121   union {                               // Data specific to individual value types
122     bool boolean;
123     double number;
124     const char *string;
125     struct json_node **elements;        // Arrays: Growing array of values
126     struct json_pair *pairs;            // Objects: Growing array of pairs
127   };
128 };
129
130 /** Attributes of objects are stored as (key, value) pairs of this format. **/
131 struct json_pair {
132   const char *key;
133   struct json_node *value;
134   // FIXME: Hash table
135 };
136
137 // Used internally
138 struct json_node *json_new_node(struct json_context *js, enum json_node_type type);
139
140 /** Creates a new null value. **/
141 static inline struct json_node *json_new_null(struct json_context *js)
142 {
143   return json_new_node(js, JSON_NULL);
144 }
145
146 /** Creates a new boolean value. **/
147 static inline struct json_node *json_new_bool(struct json_context *js, bool value)
148 {
149   struct json_node *n = json_new_node(js, JSON_BOOLEAN);
150   n->boolean = value;
151   return n;
152 }
153
154 /** Creates a new numeric value. **/
155 static inline struct json_node *json_new_number(struct json_context *js, double value)
156 {
157   struct json_node *n = json_new_node(js, JSON_NUMBER);
158   n->number = value;
159   return n;
160 }
161
162 /** Creates a new string value. The @value is kept only as a reference. **/
163 static inline struct json_node *json_new_string_ref(struct json_context *js, const char *value)
164 {
165   struct json_node *n = json_new_node(js, JSON_STRING);
166   n->string = value;
167   return n;
168 }
169
170 /** Creates a new string value, making a private copy of @value. **/
171 static inline struct json_node *json_new_string(struct json_context *js, const char *value)
172 {
173   return json_new_string_ref(js, mp_strdup(js->pool, value));
174 }
175
176 /** Creates a new array value with no elements. **/
177 struct json_node *json_new_array(struct json_context *js);
178
179 /** Appends a new element to the given array. **/
180 void json_array_append(struct json_node *array, struct json_node *elt);
181
182 /** Creates a new object value with no attributes. **/
183 struct json_node *json_new_object(struct json_context *js);
184
185 /**
186  * Adds a new (@key, @value) pair to the given object. If @key is already
187  * present, the pair is replaced. If @value is NULL, no new pair is created
188  * and a pre-existing pair is deleted.
189  *
190  * The @key is referenced by the object, you must not free it during
191  * the lifetime of the JSON context.
192  *
193  * FIXME: Add json_copy_key().
194  **/
195 void json_object_set(struct json_node *n, const char *key, struct json_node *value);
196
197 /** Returns the value associated with @key, or NULL if no such value exists. **/
198 struct json_node *json_object_get(struct json_node *n, const char *key);
199
200 /***
201  * === Parser
202  *
203  * The simplest way to parse a complete JSON file is to call json_parse(),
204  * which returns a value tree representing the contents of the file.
205  *
206  * Alternatively, you can read the input token by token: call json_set_input()
207  * and then repeat json_next_token(). Note that even in this mode, the tokens
208  * are kept in memory. (If you need to parse huge JSON files, please ask the
209  * maintainer of this library to improve memory allocation.)
210  ***/
211
212 /** Parses a JSON file from the given fastbuf stream. **/
213 struct json_node *json_parse(struct json_context *js, struct fastbuf *fb);
214
215 /** Selects the given fastbuf stream as parser input. **/
216 void json_set_input(struct json_context *js, struct fastbuf *in);
217
218 /** Reads the next token from the input. **/
219 struct json_node *json_next_token(struct json_context *js);
220
221 /** Reads the next token, but keeps it in the input. **/
222 struct json_node *json_peek_token(struct json_context *js);
223
224 /** Reads the next JSON value, including nested values. **/
225 struct json_node *json_next_value(struct json_context *js);
226
227 /***
228  * === Writer
229  *
230  * JSON files can be produced by simply calling json_write().
231  *
232  * If you want to generate the output on the fly (for example if it is huge),
233  * call json_set_output() and then iterate json_write_value().
234  *
235  * By default, we produce a single-line compact representation,
236  * but you can choose differently by setting the appropriate
237  * `format_options` in the `json_context`.
238  ***/
239
240 /** Writes a JSON file to the given fastbuf stream, containing the JSON value @n. **/
241 void json_write(struct json_context *js, struct fastbuf *fb, struct json_node *n);
242
243 /** Selects the given fastbuf stream as output. **/
244 void json_set_output(struct json_context *js, struct fastbuf *fb);
245
246 /** Writes a single JSON value to the output stream. **/
247 void json_write_value(struct json_context *js, struct json_node *n);
248
249 /** Formatting options. The `format_options` field in the context is a bitwise OR of these flags. **/
250 enum json_format_option {
251   JSON_FORMAT_ESCAPE_NONASCII = 1,      // Produce pure ASCII output by escaping all Unicode characters in strings
252   JSON_FORMAT_INDENT = 2,               // Produce pretty indented output
253 };
254
255 #endif