2 Copyright (C) 2006 Georgia Public Library Service
3 Bill Erickson <billserickson@gmail.com>
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.
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.
19 #include <opensrf/utils.h>
20 #include <opensrf/osrf_list.h>
21 #include <opensrf/osrf_hash.h>
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
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 */
64 #define JSON_PARSE_LAST_CHUNK 0x1 /* this is the last part of the string we're parsing */
66 #define JSON_PARSE_FLAG_CHECK(ctx, f) (ctx->flags & f) ? 1 : 0 /* check if a parser state is set */
68 #ifndef JSON_CLASS_KEY
69 #define JSON_CLASS_KEY "__c"
72 #define JSON_DATA_KEY "__p"
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 */
88 typedef struct jsonParserContextStruct jsonParserContext;
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, ...);
102 typedef struct jsonParserHandlerStruct jsonParserHandler;
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 */
114 // double n; /* number */
115 double n; /* number */
118 typedef struct _jsonObjectStruct jsonObject;
120 struct _jsonIteratorStruct {
121 jsonObject* obj; /* the object we're traversing */
122 osrfHashIterator* hashItr; /* the iterator for this hash */
123 const char* key; /* if this object is a hash, the current key */
124 unsigned long index; /* if this object is an array, the index */
126 typedef struct _jsonIteratorStruct jsonIterator;
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
137 jsonParserContext* jsonNewParser( const jsonParserHandler* handler, void* userData);
140 * Deallocates a parser context
141 * @param ctx The context object
143 void jsonParserFree( jsonParserContext* ctx );
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
152 int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags );
156 * Parses a JSON string;
157 * @param str The string to parser
158 * @return The resulting JSON object or NULL on error
160 jsonObject* jsonParseString( const char* str );
161 jsonObject* jsonParseStringRaw( const char* str );
163 jsonObject* jsonParseStringFmt( const char* str, ... );
166 * Similar to jsonParseString(), jsonParseStringRaw() and
167 * jsonParseStringFmt(), but with stricter and more robust
170 jsonObject* jsonParse( const char* s );
171 jsonObject* jsonParseRaw( const char* s );
172 jsonObject* jsonParseFmt( const char* str, ... );
176 * Parses a JSON string;
177 * @param str The string to parser
178 * @return The resulting JSON object or NULL on error
180 jsonObject* jsonParseStringHandleError( void (*errorHandler) (const char*), char* str, ... );
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
191 jsonObject* jsonNewObject(const char* data);
192 jsonObject* jsonNewObjectFmt(const char* data, ...);
195 * Creates a new object of the given type
197 jsonObject* jsonNewObjectType(int type);
200 * Creates a new number object from a double
202 jsonObject* jsonNewNumberObject( double num );
205 * Creates a new number object from a numeric string
207 jsonObject* jsonNewNumberStringObject( const char* numstr );
210 * Creates a new json bool
212 jsonObject* jsonNewBoolObject(int val);
215 * Deallocates an object
217 void jsonObjectFree( jsonObject* o );
220 * Returns all unused jsonObjects to the heap
222 void jsonObjectFreeUnused( void );
225 * Forces the given object to become an array (if it isn't already one)
226 * and pushes the new object into the array
228 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
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
234 unsigned long jsonObjectSetKey(
235 jsonObject* o, const char* key, jsonObject* newo);
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 );
245 * Retrieves the object at the given key
247 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
248 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
254 /** Allocates a new iterator
255 @param obj The object over which to iterate.
257 jsonIterator* jsonNewIterator(const jsonObject* obj);
261 De-allocates an iterator
262 @param iter The iterator object to free
264 void jsonIteratorFree(jsonIterator* iter);
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.
271 jsonObject* jsonIteratorNext(jsonIterator* iter);
275 @param iter The iterator.
276 @return True if there is another node after the current node.
278 int jsonIteratorHasNext(const jsonIterator* iter);
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.
288 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
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
295 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
297 /* removes and deallocates the object at the given index, replacing
298 it with a NULL pointer
300 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
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
305 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
307 /* removes (and deallocates) the object with key 'key' if it exists */
308 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
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*);
314 double jsonObjectGetNumber( const jsonObject* obj );
316 /* sets the string data */
317 void jsonObjectSetString(jsonObject* dest, const char* string);
319 /* sets the number value for the object */
320 void jsonObjectSetNumber(jsonObject* dest, double num);
321 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
323 /* sets the class hint for this object */
324 void jsonObjectSetClass(jsonObject* dest, const char* classname );
325 const char* jsonObjectGetClass(const jsonObject* dest);
327 int jsonBoolIsTrue( const jsonObject* boolObj );
329 void jsonSetBool(jsonObject* bl, int val);
331 jsonObject* jsonObjectClone( const jsonObject* o );
334 /* tries to extract the string data from an object.
335 if object -> NULL (the C NULL)
339 if string/number the string version of either of those
340 The caller is responsible for freeing the returned string
342 char* jsonObjectToSimpleString( const jsonObject* o );
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.
349 char* doubleToString( double num );
352 Return 1 if the string is numeric, otherwise return 0.
353 This validation follows the rules defined by the grammar at:
356 int jsonIsNumeric( const char* s );
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.
363 char* jsonScrubNumber( const char* s );
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
372 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
375 /* formats a JSON string from printing. User must free returned string */
376 char* jsonFormatString( const char* jsonString );
378 /* sets the error handler for all parsers */
379 void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*));
381 /* ------------------------------------------------------------------------- */
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()
398 /** Converts a class-wrapped object into an object with the
400 * Caller must free the returned object
402 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
405 /** Converts an object with a classname into a
406 * class-wrapped (serialized) object
407 * Caller must free the returned object
409 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
411 /* ------------------------------------------------------------------------- */
415 * Generates an XML representation of a JSON object */
416 char* jsonObjectToXML(const jsonObject*);
420 * Builds a JSON object from the provided XML
422 jsonObject* jsonXMLToJSONObject(const char* xml);