}
+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;
+}
+
+
+
+
*/
object* json_parse_string(char* string);
+object* json_parse_file(char* filename);
}
+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;
+}
+
+
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
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);
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);
vsnprintf(buf, len - 1, format, a_copy);
va_end(a_copy);
- //free(f_copy);
-
return buffer_add(gb, buf);
}
// 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);
}
}
}
+
+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;
+}
+
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.
/* 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);
+