]> git.evergreen-ils.org Git - OpenSRF.git/blob - include/opensrf/osrf_json.h
New JSON parser -- simpler, faster, and more robust in the
[OpenSRF.git] / include / opensrf / osrf_json.h
1 /*
2 Copyright (C) 2006  Georgia Public Library Service 
3 Bill Erickson <billserickson@gmail.com>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 */
15
16 #ifndef JSON_H
17 #define JSON_H
18
19 #include <opensrf/utils.h>
20 #include <opensrf/osrf_list.h>
21 #include <opensrf/osrf_hash.h>
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 /* parser states */
28 #define JSON_STATE_IN_OBJECT    0x1
29 #define JSON_STATE_IN_ARRAY             0x2
30 #define JSON_STATE_IN_STRING    0x4
31 #define JSON_STATE_IN_UTF               0x8
32 #define JSON_STATE_IN_ESCAPE    0x10
33 #define JSON_STATE_IN_KEY               0x20
34 #define JSON_STATE_IN_NULL              0x40
35 #define JSON_STATE_IN_TRUE              0x80
36 #define JSON_STATE_IN_FALSE             0x100
37 #define JSON_STATE_IN_NUMBER    0x200
38 #define JSON_STATE_IS_INVALID   0x400
39 #define JSON_STATE_IS_DONE              0x800
40 #define JSON_STATE_START_COMMEN 0x1000
41 #define JSON_STATE_IN_COMMENT   0x2000
42 #define JSON_STATE_END_COMMENT  0x4000
43
44
45 /* object and array (container) states are pushed onto a stack so we
46  * can keep track of the object nest.  All other states are
47  * simply stored in the state field of the parser */
48 #define JSON_STATE_SET(ctx,s) ctx->state |= s; /* set a state */
49 #define JSON_STATE_REMOVE(ctx,s) ctx->state &= ~s; /* unset a state */
50 #define JSON_STATE_CHECK(ctx,s) (ctx->state & s) ? 1 : 0 /* check if a state is set */
51 #define JSON_STATE_POP(ctx) osrfListPop( ctx->stateStack ); /* remove a state from the stack */
52 #define JSON_STATE_PUSH(ctx, state) osrfListPush( ctx->stateStack,(void*) state );/* push a state on the stack */
53 #define JSON_STATE_PEEK(ctx) osrfListGetIndex(ctx->stateStack, ctx->stateStack->size -1) /* check which container type we're currently in */
54 #define JSON_STATE_CHECK_STACK(ctx, s) (JSON_STATE_PEEK(ctx) == (void*) s ) ? 1 : 0  /* compare stack values */
55
56 /* JSON types */
57 #define JSON_HASH       0
58 #define JSON_ARRAY      1
59 #define JSON_STRING     2
60 #define JSON_NUMBER     3
61 #define JSON_NULL       4       
62 #define JSON_BOOL       5
63
64 #define JSON_PARSE_LAST_CHUNK 0x1 /* this is the last part of the string we're parsing */
65
66 #define JSON_PARSE_FLAG_CHECK(ctx, f) (ctx->flags & f) ? 1 : 0 /* check if a parser state is set */
67
68 #ifndef JSON_CLASS_KEY
69 #define JSON_CLASS_KEY "__c"
70 #endif
71 #ifndef JSON_DATA_KEY
72 #define JSON_DATA_KEY "__p"
73 #endif
74
75
76 struct jsonParserContextStruct {
77         int state;                                              /* what are we currently parsing */
78         const char* chunk;                              /* the chunk we're currently parsing */
79         int index;                                              /* where we are in parsing the current chunk */
80         int chunksize;                                  /* the size of the current chunk */
81         int flags;                                              /* parser flags */
82         osrfList* stateStack;           /* represents the nest of object/array states */
83         growing_buffer* buffer;         /* used to hold JSON strings, number, true, false, and null sequences */
84         growing_buffer* utfbuf;         /* holds the current unicode characters */
85         void* userData;                         /* opaque user pointer.  we ignore this */
86         const struct jsonParserHandlerStruct* handler; /* the event handler struct */
87 };
88 typedef struct jsonParserContextStruct jsonParserContext;
89
90 struct jsonParserHandlerStruct {
91         void (*handleStartObject)       (void* userData);
92         void (*handleObjectKey)         (void* userData, char* key);
93         void (*handleEndObject)         (void* userData);
94         void (*handleStartArray)        (void* userData);
95         void (*handleEndArray)          (void* userData);
96         void (*handleNull)                      (void* userData);
97         void (*handleString)                    (void* userData, char* string);
98         void (*handleBool)                      (void* userData, int boolval);
99         void (*handleNumber)            (void* userData, const char* numstr);
100         void (*handleError)                     (void* userData, char* err, ...);
101 };
102 typedef struct jsonParserHandlerStruct jsonParserHandler;
103
104 struct _jsonObjectStruct {
105         unsigned long size;     /* number of sub-items */
106         char* classname;                /* optional class hint (not part of the JSON spec) */
107         int type;                               /* JSON type */
108         struct _jsonObjectStruct* parent;       /* who we're attached to */
109         union __jsonValue {     /* cargo */
110                 osrfHash*       h;              /* object container */
111                 osrfList*       l;              /* array container */
112                 char*           s;              /* string */
113                 int                     b;              /* bool */
114 //              double  n;              /* number */
115                 double  n;              /* number */
116         } value;
117 };
118 typedef struct _jsonObjectStruct jsonObject;
119
120 struct _jsonIteratorStruct {
121         jsonObject* obj; /* the object we're traversing */
122         osrfHashIterator* hashItr; /* the iterator for this hash */
123         char* key; /* if this object is an object, the current key */
124         unsigned long index; /* if this object is an array, the index */
125 };
126 typedef struct _jsonIteratorStruct jsonIterator;
127
128
129
130 /** 
131  * Allocates a new parser context object
132  * @param handler The event handler struct
133  * @param userData Opaque user pointer which is available in callbacks
134  * and ignored by the parser
135  * @return An allocated parser context, NULL on error
136  */
137 jsonParserContext* jsonNewParser( const jsonParserHandler* handler, void* userData);
138
139 /**
140  * Deallocates a parser context
141  * @param ctx The context object
142  */
143 void jsonParserFree( jsonParserContext* ctx );
144
145 /**
146  * Parse a chunk of data.
147  * @param ctx The parser context
148  * @param data The data to parse
149  * @param datalen The size of the chunk to parser
150  * @param flags Reserved
151  */
152 int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags );
153
154
155 /**
156  * Parses a JSON string;
157  * @param str The string to parser
158  * @return The resulting JSON object or NULL on error
159  */
160 jsonObject* jsonParseString( const char* str );
161 jsonObject* jsonParseStringRaw( const char* str );
162
163 jsonObject* jsonParseStringFmt( const char* str, ... );
164
165 /**
166  * Similar to jsonParseString(), jsonParseStringRaw() and
167  * jsonParseStringFmt(), but with stricter and more robust
168  * syntax validation
169  */
170 jsonObject* jsonParse( const char* s );
171 jsonObject* jsonParseRaw( const char* s );
172 jsonObject* jsonParseFmt( const char* str, ... );
173
174
175 /**
176  * Parses a JSON string;
177  * @param str The string to parser
178  * @return The resulting JSON object or NULL on error
179  */
180 jsonObject* jsonParseStringHandleError( void (*errorHandler) (const char*), char* str, ... );
181
182
183
184 /**
185  * Creates a new json object
186  * @param data The string data this object will hold if 
187  * this object happens to be a JSON_STRING, NULL otherwise
188  * @return The allocated json object.  Must be freed with 
189  * jsonObjectFree()
190  */
191 jsonObject* jsonNewObject(const char* data);
192 jsonObject* jsonNewObjectFmt(const char* data, ...);
193
194 /**
195  * Creates a new object of the given type
196  */
197 jsonObject* jsonNewObjectType(int type);
198
199 /**
200  * Creates a new number object from a double
201  */
202 jsonObject* jsonNewNumberObject( double num );
203
204 /**
205  * Creates a new number object from a numeric string
206  */
207 jsonObject* jsonNewNumberStringObject( const char* numstr );
208
209 /**
210  * Creates a new json bool
211  */
212 jsonObject* jsonNewBoolObject(int val);
213
214 /**
215  * Deallocates an object
216  */
217 void jsonObjectFree( jsonObject* o );
218
219 /**
220  * Returns all unused jsonObjects to the heap
221  */
222 void jsonObjectFreeUnused( void );
223
224 /**
225  * Forces the given object to become an array (if it isn't already one) 
226  * and pushes the new object into the array
227  */
228 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
229
230 /**
231  * Forces the given object to become a hash (if it isn't already one)
232  * and assigns the new object to the key of the hash
233  */
234 unsigned long jsonObjectSetKey(
235                 jsonObject* o, const char* key, jsonObject* newo);
236
237
238 /**
239  * Turns the object into a JSON string.  The string must be freed by the caller */
240 char* jsonObjectToJSON( const jsonObject* obj );
241 char* jsonObjectToJSONRaw( const jsonObject* obj );
242
243
244 /**
245  * Retrieves the object at the given key
246  */
247 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
248 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
249
250
251
252
253
254 /** Allocates a new iterator 
255         @param obj The object over which to iterate.
256 */
257 jsonIterator* jsonNewIterator(const jsonObject* obj);
258
259
260 /** 
261         De-allocates an iterator 
262         @param iter The iterator object to free
263 */
264 void jsonIteratorFree(jsonIterator* iter);
265
266 /** 
267         Returns the object_node currently pointed to by the iterator
268         and increments the pointer to the next node
269         @param iter The iterator in question.
270  */
271 jsonObject* jsonIteratorNext(jsonIterator* iter);
272
273
274 /** 
275         @param iter The iterator.
276         @return True if there is another node after the current node.
277  */
278 int jsonIteratorHasNext(const jsonIterator* iter);
279
280
281 /** 
282         Returns a pointer to the object at the given index.  This call is
283         only valid if the object has a type of JSON_ARRAY.
284         @param obj The object
285         @param index The position within the object
286         @return The object at the given index.
287 */
288 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
289
290
291 /* removes (and deallocates) the object at the given index (if one exists) and inserts 
292  * the new one.  returns the size on success, -1 on error 
293  * If obj is NULL, inserts a new object into the list with is_null set to true
294  */
295 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
296
297 /* removes and deallocates the object at the given index, replacing
298    it with a NULL pointer
299  */
300 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
301
302 /* removes (but does not deallocate) the object at the given index,
303  * replacing it with a NULL pointer; returns a pointer to the object removed
304  */
305 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
306
307 /* removes (and deallocates) the object with key 'key' if it exists */
308 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
309
310 /* returns a pointer to the string data held by this object if this object
311         is a string.  Otherwise returns NULL*/
312 char* jsonObjectGetString(const jsonObject*);
313
314 double jsonObjectGetNumber( const jsonObject* obj );
315
316 /* sets the string data */
317 void jsonObjectSetString(jsonObject* dest, const char* string);
318
319 /* sets the number value for the object */
320 void jsonObjectSetNumber(jsonObject* dest, double num);
321 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
322
323 /* sets the class hint for this object */
324 void jsonObjectSetClass(jsonObject* dest, const char* classname );
325 const char* jsonObjectGetClass(const jsonObject* dest);
326
327 int jsonBoolIsTrue( const jsonObject* boolObj );
328
329 void jsonSetBool(jsonObject* bl, int val);
330
331 jsonObject* jsonObjectClone( const jsonObject* o );
332
333
334 /* tries to extract the string data from an object.
335         if object       -> NULL (the C NULL)
336         if array                ->      NULL  
337         if null         -> NULL 
338         if bool         -> NULL
339         if string/number the string version of either of those
340         The caller is responsible for freeing the returned string
341         */
342 char* jsonObjectToSimpleString( const jsonObject* o );
343
344 /**
345  Allocate a buffer and format a specified numeric value into it,
346  with up to 30 decimal digits of precision.   Caller is responsible
347  for freeing the buffer.
348  **/
349 char* doubleToString( double num );
350
351 /**
352  Return 1 if the string is numeric, otherwise return 0.
353  This validation follows the rules defined by the grammar at:
354  http://www.json.org/
355  **/
356 int jsonIsNumeric( const char* s );
357
358 /**
359  Allocate and reformat a numeric string into one that is valid
360  by JSON rules.  If the string is not numeric, return NULL.
361  Caller is responsible for freeing the buffer.
362  **/
363 char* jsonScrubNumber( const char* s );
364
365 /* provides an XPATH style search interface (e.g. /some/node/here) and 
366         return the object at that location if one exists.  Naturally,  
367         every element in the path must be a proper object ("hash" / {}).
368         Returns NULL if the specified node is not found 
369         Note also that the object returned is a clone and
370         must be freed by the caller
371 */
372 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
373
374
375 /* formats a JSON string from printing.  User must free returned string */
376 char* jsonFormatString( const char* jsonString );
377
378 /* sets the error handler for all parsers */
379 void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*));
380
381 /* ------------------------------------------------------------------------- */
382 /**
383  * The following methods provide a facility for serializing and
384  * deserializing "classed" JSON objects.  To give a JSON object a 
385  * class, simply call jsonObjectSetClass().  
386  * Then, calling jsonObjectEncodeClass() will convert the JSON
387  * object (and any sub-objects) to a JSON object with class 
388  * wrapper objects like so:
389  * { _c : "classname", _d : <json_thing> }
390  * In this example _c is the class key and _d is the data (object)
391  * key.  The keys are defined by the constants 
392  * OSRF_JSON_CLASS_KEY and OSRF_JSON_DATA_KEY
393  * To revive a serialized object, simply call
394  * jsonObjectDecodeClass()
395  */
396
397
398 /** Converts a class-wrapped object into an object with the
399  * classname set
400  * Caller must free the returned object 
401  */ 
402 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
403
404
405 /** Converts an object with a classname into a
406  * class-wrapped (serialized) object
407  * Caller must free the returned object 
408  */ 
409 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
410
411 /* ------------------------------------------------------------------------- */
412
413
414 /**
415  *      Generates an XML representation of a JSON object */
416 char* jsonObjectToXML(const jsonObject*);
417
418
419 /*
420  * Builds a JSON object from the provided XML 
421  */
422 jsonObject* jsonXMLToJSONObject(const char* xml);
423
424 #ifdef __cplusplus
425 }
426 #endif
427
428 #endif