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>
17 #include <opensrf/osrf_json_utils.h>
19 static jsonObject* _jsonObjectEncodeClass( const jsonObject* obj, int ignoreClass );
21 static char* _tabs(int count) {
22 growing_buffer* buf = buffer_init(24);
24 for(i=0;i<count;i++) OSRF_BUFFER_ADD(buf, " ");
25 return buffer_release(buf);
28 char* jsonFormatString( const char* string ) {
29 if(!string) return strdup("");
31 growing_buffer* buf = buffer_init(64);
37 for(i=0; i!= strlen(string); i++) {
40 if( c == '{' || c == '[' ) {
43 buffer_fadd( buf, "%c\n%s", c, tab);
46 } else if( c == '}' || c == ']' ) {
49 buffer_fadd( buf, "\n%s%c", tab, c);
52 if(string[i+1] != ',') {
54 buffer_fadd( buf, "%s", tab );
58 } else if( c == ',' ) {
61 buffer_fadd(buf, ",\n%s", tab);
64 } else { buffer_add_char(buf, c); }
68 return buffer_release(buf);
73 jsonObject* jsonObjectDecodeClass( const jsonObject* obj ) {
74 if(!obj) return jsonNewObject(NULL);
76 jsonObject* newObj = NULL;
77 const jsonObject* classObj = NULL;
78 const jsonObject* payloadObj = NULL;
81 if( obj->type == JSON_HASH ) {
83 /* are we a special class object? */
84 if( (classObj = jsonObjectGetKeyConst( obj, JSON_CLASS_KEY )) ) {
86 /* do we have a payload */
87 if( (payloadObj = jsonObjectGetKeyConst( obj, JSON_DATA_KEY )) ) {
88 newObj = jsonObjectDecodeClass( payloadObj );
89 jsonObjectSetClass( newObj, jsonObjectGetString(classObj) );
91 } else { /* class is defined but there is no payload */
95 } else { /* we're a regular hash */
97 jsonIterator* itr = jsonNewIterator(obj);
99 newObj = jsonNewObjectType(JSON_HASH);
100 while( (tmp = jsonIteratorNext(itr)) ) {
101 jsonObject* o = jsonObjectDecodeClass(tmp);
102 jsonObjectSetKey( newObj, itr->key, o );
104 jsonIteratorFree(itr);
109 if( obj->type == JSON_ARRAY ) { /* we're an array */
110 newObj = jsonNewObjectType(JSON_ARRAY);
111 for( i = 0; i != obj->size; i++ ) {
112 jsonObject* tmp = jsonObjectDecodeClass(jsonObjectGetIndex( obj, i ) );
113 jsonObjectSetIndex( newObj, i, tmp );
116 } else { /* not an aggregate type */
117 newObj = jsonObjectClone(obj);
124 jsonObject* jsonObjectEncodeClass( const jsonObject* obj ) {
125 return _jsonObjectEncodeClass( obj, 0 );
128 static jsonObject* _jsonObjectEncodeClass( const jsonObject* obj, int ignoreClass ) {
130 //if(!obj) return NULL;
131 if(!obj) return jsonNewObject(NULL);
132 jsonObject* newObj = NULL;
134 if( obj->classname && ! ignoreClass ) {
135 newObj = jsonNewObjectType(JSON_HASH);
137 jsonObjectSetKey( newObj,
138 JSON_CLASS_KEY, jsonNewObject(obj->classname) );
140 jsonObjectSetKey( newObj,
141 JSON_DATA_KEY, _jsonObjectEncodeClass(obj, 1));
143 } else if( obj->type == JSON_HASH ) {
145 jsonIterator* itr = jsonNewIterator(obj);
147 newObj = jsonNewObjectType(JSON_HASH);
149 while( (tmp = jsonIteratorNext(itr)) ) {
150 jsonObjectSetKey( newObj, itr->key,
151 _jsonObjectEncodeClass(tmp, 0));
153 jsonIteratorFree(itr);
155 } else if( obj->type == JSON_ARRAY ) {
157 newObj = jsonNewObjectType(JSON_ARRAY);
159 for( i = 0; i != obj->size; i++ ) {
160 jsonObjectSetIndex( newObj, i,
161 _jsonObjectEncodeClass(jsonObjectGetIndex( obj, i ), 0 ));
165 newObj = jsonObjectClone(obj);
171 jsonObject* jsonParseFile( char* filename ) {
172 if(!filename) return NULL;
173 char* data = file_to_string(filename);
174 jsonObject* o = jsonParseString(data);
181 jsonObject* jsonObjectFindPath( const jsonObject* obj, char* format, ...) {
182 if(!obj || !format || strlen(format) < 1) return NULL;
184 VA_LIST_TO_STRING(format);
188 char* tt; /* strtok storage */
190 /* copy the path before strtok_r destroys it */
191 char* pathcopy = strdup(buf);
193 /* grab the root of the path */
194 token = strtok_r(t, "/", &tt);
195 if(!token) return NULL;
197 /* special case where path starts with // (start anywhere) */
198 if(strlen(pathcopy) > 2 && pathcopy[0] == '/' && pathcopy[1] == '/') {
199 jsonObject* it = _jsonObjectFindPathRecurse(obj, token, pathcopy + 1);
208 obj = jsonObjectGetKeyConst(obj, token);
209 } while( (token = strtok_r(NULL, "/", &tt)) && obj);
211 return jsonObjectClone(obj);
214 /* --------------------------------------------------------------- */
218 jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path) {
220 if(!obj || ! root || !path) return NULL;
222 /* collect all of the potential objects */
223 jsonObject* arr = __jsonObjectFindPathRecurse(obj, root);
225 /* container for fully matching objects */
226 jsonObject* newarr = jsonParseString("[]");
229 /* path is just /root or /root/ */
230 if( strlen(root) + 2 >= strlen(path) ) {
235 /* gather all of the sub-objects that match the full path */
236 for( i = 0; i < arr->size; i++ ) {
237 const jsonObject* a = jsonObjectGetIndex(arr, i);
238 jsonObject* thing = jsonObjectFindPath(a , path + strlen(root) + 1);
240 if(thing) { //jsonObjectPush(newarr, thing);
241 if(thing->type == JSON_ARRAY) {
243 for( i = 0; i != thing->size; i++ )
244 jsonObjectPush(newarr, jsonObjectClone(jsonObjectGetIndex(thing,i)));
245 jsonObjectFree(thing);
248 jsonObjectPush(newarr, thing);
258 jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root) {
260 jsonObject* arr = jsonParseString("[]");
265 /* if the current object has a node that matches, add it */
267 const jsonObject* o = jsonObjectGetKeyConst(obj, root);
268 if(o) jsonObjectPush( arr, jsonObjectClone(o) );
270 jsonObject* tmp = NULL;
271 jsonObject* childarr;
272 jsonIterator* itr = jsonNewIterator(obj);
274 /* recurse through the children and find all potential nodes */
275 while( (tmp = jsonIteratorNext(itr)) ) {
276 childarr = __jsonObjectFindPathRecurse(tmp, root);
277 if(childarr && childarr->size > 0) {
278 for( i = 0; i!= childarr->size; i++ ) {
279 jsonObjectPush( arr, jsonObjectClone(jsonObjectGetIndex(childarr, i)) );
282 jsonObjectFree(childarr);
285 jsonIteratorFree(itr);