From bc74c7dd7be1c6d356b6abf921df53f06105dd71 Mon Sep 17 00:00:00 2001 From: erickson Date: Thu, 25 Aug 2005 03:27:36 +0000 Subject: [PATCH] added basic xpath support to JSON added some utility functions git-svn-id: svn://svn.open-ils.org/ILS/trunk@1722 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- OpenSRF/src/objson/json_parser.c | 11 ++++ OpenSRF/src/objson/json_parser.h | 1 + OpenSRF/src/objson/object.c | 109 +++++++++++++++++++++++++++++++ OpenSRF/src/objson/object.h | 15 +++++ OpenSRF/src/utils/utils.c | 61 ++++++++++++----- OpenSRF/src/utils/utils.h | 10 +++ 6 files changed, 190 insertions(+), 17 deletions(-) diff --git a/OpenSRF/src/objson/json_parser.c b/OpenSRF/src/objson/json_parser.c index a3e4692374..9f3221dbdb 100644 --- a/OpenSRF/src/objson/json_parser.c +++ b/OpenSRF/src/objson/json_parser.c @@ -722,3 +722,14 @@ int json_handle_error(char* string, unsigned long* index, char* err_msg) { } +object* json_parse_file(char* filename) { + if(!filename) return NULL; + char* data = file_to_string(filename); + object* o = json_parse_string(data); + free(data); + return o; +} + + + + diff --git a/OpenSRF/src/objson/json_parser.h b/OpenSRF/src/objson/json_parser.h index 5fb7d6bfa2..a2a6ec6158 100644 --- a/OpenSRF/src/objson/json_parser.h +++ b/OpenSRF/src/objson/json_parser.h @@ -33,6 +33,7 @@ GNU General Public License for more details. */ object* json_parse_string(char* string); +object* json_parse_file(char* filename); diff --git a/OpenSRF/src/objson/object.c b/OpenSRF/src/objson/object.c index ff41eaaeb1..cea3d87a89 100644 --- a/OpenSRF/src/objson/object.c +++ b/OpenSRF/src/objson/object.c @@ -639,3 +639,112 @@ int object_iterator_has_next(object_iterator* itr) { } +object* object_find_path(object* obj, char* format, ...) { + if(!obj || !format || strlen(format) < 1) return NULL; + + /* build the string from the variable args */ + long len = 0; + va_list args, a_copy; + + va_copy(a_copy, args); + + va_start(args, format); + len = va_list_size(format, args); + char buf[len]; + bzero(buf, len); + + va_start(a_copy, format); + vsnprintf(buf, len - 1, format, a_copy); + va_end(a_copy); + /* -------------------------------------------- */ + + + /* tmp storage for strtok_r */ + char tokbuf[len]; + bzero(tokbuf, len); + + char* token = NULL; + char* t = buf; + char* tt = tokbuf; + + char* pathcopy = strdup(buf); + + /* grab the root of the path */ + token = strtok_r(t, "/", &tt); + t = NULL; + if(!token) return NULL; + + /* special case where path starts with // (start anywhere) */ + if(strlen(pathcopy) > 2 && pathcopy[0] == '/' && pathcopy[1] == '/') { + object* it = _object_find_path_recurse(obj, token, pathcopy + 1); + free(pathcopy); + return it; + } + + free(pathcopy); + + do { + obj = obj->get_key(obj, token); + } while( (token = strtok_r(NULL, "/", &tt)) && obj); + + return object_clone(obj); +} + + + +object* _object_find_path_recurse(object* obj, char* root, char* path) { + + if(!obj || ! root) return NULL; + object* arr = __object_find_path_recurse(obj, root); + object* newarr = json_parse_string("[]"); + + int i; + + /* path is just /root or /root/ */ + if( strlen(root) + 2 >= strlen(path) ) { + return arr; + } else { + + for( i = 0; i < arr->size; i++ ) { + /* + fprintf(stderr, "Searching root %s and path %s and size %ld\n", root, path + strlen(root) + 1, arr->size); + */ + object* a = arr->get_index(arr, i); + object* thing = object_find_path(a , path + strlen(root) + 1); + if(thing) newarr->push(newarr, thing); + } + } + + free_object(arr); + return newarr; +} + +object* __object_find_path_recurse(object* obj, char* root) { + + object* arr = json_parse_string("[]"); + if(!obj) return arr; + object* o = obj->get_key(obj, root); + if(o) arr->push(arr, object_clone(o)); + + object_node* tmp = NULL; + object* childarr; + object_iterator* itr = new_iterator(obj); + + while( (tmp = itr->next(itr)) ) { + childarr = __object_find_path_recurse(tmp->item, root); + if(childarr && childarr->size > 0) { + int i; + for( i = 0; i!= childarr->size; i++ ) { + arr->push(arr, object_clone(childarr->get_index(childarr, i))); + } + } + + free_object(childarr); + } + + free_iterator(itr); + + return arr; +} + + diff --git a/OpenSRF/src/objson/object.h b/OpenSRF/src/objson/object.h index f9925c2b68..8209de1c89 100644 --- a/OpenSRF/src/objson/object.h +++ b/OpenSRF/src/objson/object.h @@ -219,4 +219,19 @@ char* json_string_format(char* json); object* object_clone(object* o); +/* provide an XPATH style path (e.g. /some/node/here) and this will + return the object at that location if one exists. Naturally, + every element in the path must be a proper object ("hash" / {}). + Returns NULL if the specified node is not found + Note also that the object returned is a clone and + must be freed by the caller +*/ +object* object_find_path(object* obj, char* format, ...); + + +/* returns an object array of matches */ +object* _object_find_path_recurse(object* obj, char* root, char* path); +object* __object_find_path_recurse(object* obj, char* root); + + #endif diff --git a/OpenSRF/src/utils/utils.c b/OpenSRF/src/utils/utils.c index 1d79de36ea..9c0a3c2ad9 100644 --- a/OpenSRF/src/utils/utils.c +++ b/OpenSRF/src/utils/utils.c @@ -83,16 +83,22 @@ int clr_fl( int fd, int flags ) { return 0; } +long va_list_size(const char* format, va_list args) { + int len = 0; + len = vsnprintf(NULL, 0, format, args); + va_end(args); + len += 2; + return len; +} + + // --------------------------------------------------------------------------------- // Flesh out a ubiqitous growing string buffer // --------------------------------------------------------------------------------- growing_buffer* buffer_init(int num_initial_bytes) { - if( num_initial_bytes > BUFFER_MAX_SIZE ) { - return NULL; - } - + if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL; size_t len = sizeof(growing_buffer); @@ -105,23 +111,19 @@ growing_buffer* buffer_init(int num_initial_bytes) { return gb; } + int buffer_fadd(growing_buffer* gb, const char* format, ... ) { if(!gb || !format) return 0; - int len = 0; + long len = 0; va_list args; va_list a_copy; - //char* f_copy = strdup(format); - va_copy(a_copy, args); va_start(args, format); - len = vsnprintf(NULL, 0, format, args); - va_end(args); - - len += 2; + len = va_list_size(format, args); char buf[len]; memset(buf, 0, len); @@ -130,8 +132,6 @@ int buffer_fadd(growing_buffer* gb, const char* format, ... ) { vsnprintf(buf, len - 1, format, a_copy); va_end(a_copy); - //free(f_copy); - return buffer_add(gb, buf); } @@ -309,15 +309,16 @@ char* uescape( const char* string, int size, int full_escape ) { // A function to turn a process into a daemon and set it's process name in ps/top int daemonize() { int f = fork(); + if (f == -1) { perror("Failed to fork!"); return -1; - } else if (f == 0) { - // We're in the child now... + + } else if (f == 0) { // We're in the child now... setsid(); return 0; - } else { - // We're in the parent... + + } else { // We're in the parent... exit(0); } } @@ -332,3 +333,29 @@ int stringisnum(char* s) { } + +char* file_to_string(char* filename) { + + if(!filename) return NULL; + + int len = 1024; + char buf[len]; + bzero(buf, len); + growing_buffer* gb = buffer_init(len); + + FILE* file = fopen(filename, "r"); + if(!file) { + perror("Unable to open file in json_parse_file()"); + return NULL; + } + + while(fgets(buf, len - 1, file)) { + buffer_add(gb, buf); + bzero(buf, len); + } + + char* data = buffer_data(gb); + buffer_free(gb); + return data; +} + diff --git a/OpenSRF/src/utils/utils.h b/OpenSRF/src/utils/utils.h index 894faf304f..af09795858 100644 --- a/OpenSRF/src/utils/utils.h +++ b/OpenSRF/src/utils/utils.h @@ -52,6 +52,11 @@ char* buffer_data( growing_buffer* gb); int buffer_free( growing_buffer* gb ); int buffer_add_char(growing_buffer* gb, char c); +/* returns the size needed to fill in the vsnprintf buffer. + * ! this calls va_end on the va_list argument* + */ +long va_list_size(const char* format, va_list); + /* string escape utility method. escapes unicode embeded characters. escapes the usual \n, \t, etc. @@ -79,6 +84,11 @@ double get_timestamp_millis(); /* returns true if the whole string is a number */ int stringisnum(char* s); +/* reads a file and returns the string version of the file + user is responsible for freeing the returned char* + */ +char* file_to_string(char* filename); + -- 2.43.2