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