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