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.
16 #include <opensrf/osrf_json.h>
18 jsonObject* _jsonObjectEncodeClass( jsonObject* obj, int ignoreClass );
21 jsonObject* jsonObjectFindPath( const jsonObject* obj, char* path, ...);
22 jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path);
23 jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root);
26 static char* __tabs(int count) {
27 growing_buffer* buf = buffer_init(24);
29 for(i=0;i<count;i++) OSRF_BUFFER_ADD(buf, " ");
30 return buffer_release(buf);
33 char* jsonFormatString( const char* string ) {
34 if(!string) return strdup("");
36 growing_buffer* buf = buffer_init(64);
42 for(i=0; i!= strlen(string); i++) {
45 if( c == '{' || c == '[' ) {
47 tab = __tabs(++depth);
48 buffer_fadd( buf, "%c\n%s", c, tab);
51 } else if( c == '}' || c == ']' ) {
53 tab = __tabs(--depth);
54 buffer_fadd( buf, "\n%s%c", tab, c);
57 if(string[i+1] != ',') {
59 buffer_fadd( buf, "%s", tab );
63 } else if( c == ',' ) {
66 buffer_fadd(buf, ",\n%s", tab);
69 } else { buffer_add_char(buf, c); }
73 return buffer_release(buf);
78 jsonObject* jsonObjectDecodeClass( jsonObject* obj ) {
79 if(!obj) return jsonNewObject(NULL);
81 jsonObject* newObj = NULL;
82 jsonObject* classObj = NULL;
83 jsonObject* payloadObj = NULL;
86 if( obj->type == JSON_HASH ) {
88 /* are we a special class object? */
89 if( (classObj = jsonObjectGetKey( obj, JSON_CLASS_KEY )) ) {
91 /* do we have a payload */
92 if( (payloadObj = jsonObjectGetKey( obj, JSON_DATA_KEY )) ) {
93 newObj = jsonObjectDecodeClass( payloadObj );
94 jsonObjectSetClass( newObj, jsonObjectGetString(classObj) );
96 } else { /* class is defined but there is no payload */
100 } else { /* we're a regular hash */
102 jsonIterator* itr = jsonNewIterator(obj);
104 newObj = jsonNewObjectType(JSON_HASH);
105 while( (tmp = jsonIteratorNext(itr)) ) {
106 jsonObject* o = jsonObjectDecodeClass(tmp);
107 jsonObjectSetKey( newObj, itr->key, o );
109 jsonIteratorFree(itr);
114 if( obj->type == JSON_ARRAY ) { /* we're an array */
115 newObj = jsonNewObjectType(JSON_ARRAY);
116 for( i = 0; i != obj->size; i++ ) {
117 jsonObject* tmp = jsonObjectDecodeClass(jsonObjectGetIndex( obj, i ) );
118 jsonObjectSetIndex( newObj, i, tmp );
121 } else { /* not an aggregate type */
122 newObj = jsonObjectClone(obj);
129 jsonObject* jsonObjectEncodeClass( jsonObject* obj ) {
130 return _jsonObjectEncodeClass( obj, 0 );
133 jsonObject* _jsonObjectEncodeClass( jsonObject* obj, int ignoreClass ) {
135 //if(!obj) return NULL;
136 if(!obj) return jsonNewObject(NULL);
137 jsonObject* newObj = NULL;
139 if( obj->classname && ! ignoreClass ) {
140 newObj = jsonNewObjectType(JSON_HASH);
142 jsonObjectSetKey( newObj,
143 JSON_CLASS_KEY, jsonNewObject(obj->classname) );
145 jsonObjectSetKey( newObj,
146 JSON_DATA_KEY, _jsonObjectEncodeClass(obj, 1));
148 } else if( obj->type == JSON_HASH ) {
150 jsonIterator* itr = jsonNewIterator(obj);
152 newObj = jsonNewObjectType(JSON_HASH);
154 while( (tmp = jsonIteratorNext(itr)) ) {
155 jsonObjectSetKey( newObj, itr->key,
156 _jsonObjectEncodeClass(tmp, 0));
158 jsonIteratorFree(itr);
160 } else if( obj->type == JSON_ARRAY ) {
162 newObj = jsonNewObjectType(JSON_ARRAY);
164 for( i = 0; i != obj->size; i++ ) {
165 jsonObjectSetIndex( newObj, i,
166 _jsonObjectEncodeClass(jsonObjectGetIndex( obj, i ), 0 ));
170 newObj = jsonObjectClone(obj);
176 jsonObject* jsonParseFile( char* filename ) {
177 if(!filename) return NULL;
178 char* data = file_to_string(filename);
179 jsonObject* o = jsonParseString(data);
186 jsonObject* jsonObjectFindPath( const jsonObject* obj, char* format, ...) {
187 if(!obj || !format || strlen(format) < 1) return NULL;
189 VA_LIST_TO_STRING(format);
193 char* tt; /* strtok storage */
195 /* copy the path before strtok_r destroys it */
196 char* pathcopy = strdup(buf);
198 /* grab the root of the path */
199 token = strtok_r(t, "/", &tt);
200 if(!token) return NULL;
202 /* special case where path starts with // (start anywhere) */
203 if(strlen(pathcopy) > 2 && pathcopy[0] == '/' && pathcopy[1] == '/') {
204 jsonObject* it = _jsonObjectFindPathRecurse(obj, token, pathcopy + 1);
213 obj = jsonObjectGetKey(obj, token);
214 } while( (token = strtok_r(NULL, "/", &tt)) && obj);
216 return jsonObjectClone(obj);
219 /* --------------------------------------------------------------- */
223 jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path) {
225 if(!obj || ! root || !path) return NULL;
227 /* collect all of the potential objects */
228 jsonObject* arr = __jsonObjectFindPathRecurse(obj, root);
230 /* container for fully matching objects */
231 jsonObject* newarr = jsonParseString("[]");
234 /* path is just /root or /root/ */
235 if( strlen(root) + 2 >= strlen(path) ) {
240 /* gather all of the sub-objects that match the full path */
241 for( i = 0; i < arr->size; i++ ) {
242 jsonObject* a = jsonObjectGetIndex(arr, i);
243 jsonObject* thing = jsonObjectFindPath(a , path + strlen(root) + 1);
245 if(thing) { //jsonObjectPush(newarr, thing);
246 if(thing->type == JSON_ARRAY) {
248 for( i = 0; i != thing->size; i++ )
249 jsonObjectPush(newarr, jsonObjectClone(jsonObjectGetIndex(thing,i)));
250 jsonObjectFree(thing);
253 jsonObjectPush(newarr, thing);
263 jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root) {
265 jsonObject* arr = jsonParseString("[]");
270 /* if the current object has a node that matches, add it */
272 jsonObject* o = jsonObjectGetKey(obj, root);
273 if(o) jsonObjectPush( arr, jsonObjectClone(o) );
275 jsonObject* tmp = NULL;
276 jsonObject* childarr;
277 jsonIterator* itr = jsonNewIterator(obj);
279 /* recurse through the children and find all potential nodes */
280 while( (tmp = jsonIteratorNext(itr)) ) {
281 childarr = __jsonObjectFindPathRecurse(tmp, root);
282 if(childarr && childarr->size > 0) {
283 for( i = 0; i!= childarr->size; i++ ) {
284 jsonObjectPush( arr, jsonObjectClone(jsonObjectGetIndex(childarr, i)) );
287 jsonObjectFree(childarr);
290 jsonIteratorFree(itr);