From fa071dd0345832505ba6a8957d13b59a3a9bffd0 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Fri, 8 Feb 2019 14:57:39 -0800 Subject: [PATCH] Added builtin search functionality --- CMakeLists.txt | 4 +-- include/rjp.h | 10 +++++++ src/memory.c | 3 +++ src/rjp.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88d9335..1e874d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ include(GNUInstallDirs) cmake_minimum_required(VERSION 3.0.2) project(rjp) set(rjp_VERSION_MAJOR 0) -set(rjp_VERSION_MINOR 4) -set(rjp_VERSION_REVISION 1) +set(rjp_VERSION_MINOR 5) +set(rjp_VERSION_REVISION 0) set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include) configure_file( "${INCLUDE_PATH}/config.h.in" diff --git a/include/rjp.h b/include/rjp.h index e6064be..9b2737a 100644 --- a/include/rjp.h +++ b/include/rjp.h @@ -92,6 +92,8 @@ void rjp_copy_value(RJP_value* dest, const RJP_value* src); void* rjp_alloc(size_t nbytes); //Allocate heap space for rjp and initialize to 0. void* rjp_calloc(size_t num, size_t nbytes); +//Resize heap allocated space for rjp +void* rjp_realloc(void* ptr, size_t nbytes); //Free memory allocated by rjp_alloc or rjp_calloc void rjp_free(void* dest); @@ -124,6 +126,14 @@ size_t rjp_num_members(const RJP_value* object); char* rjp_member_name(const RJP_value* member); //Return the object member's key name length excluding null terminator size_t rjp_member_name_length(RJP_value* member); +//Search for an object member with given key +RJP_value* rjp_search_member(const RJP_value* object, const char* search, size_t* index, size_t skip); +//Search for first occurance of multiple keys. Returns first occurance of each. +//Assumes dest is large enough to hold maximum num items. +size_t rjp_search_members(const RJP_value* object, size_t num, const char** searches, RJP_value** dest, size_t skip); +//Search for multiple occurances of multiple keys. Returns pointer to list of matches. +//Returned pointer must be freed using rjp_free +RJP_value** rjp_search_members_multi(const RJP_value* object, size_t num, const char** searches, size_t* rsize, size_t skip); //Access first element of a json array RJP_value* rjp_get_element(const RJP_value* array); //Access next element of a json array given the previous element diff --git a/src/memory.c b/src/memory.c index d71f3ec..0ec6f77 100644 --- a/src/memory.c +++ b/src/memory.c @@ -27,6 +27,9 @@ void* rjp_alloc(size_t nbytes){ void* rjp_calloc(size_t num, size_t nbytes){ return calloc(num, nbytes); } +void* rjp_realloc(void* ptr, size_t nbytes){ + return realloc(ptr, nbytes); +} void rjp_free(void* data){ free(data); } diff --git a/src/rjp.c b/src/rjp.c index b66cf8d..167145b 100644 --- a/src/rjp.c +++ b/src/rjp.c @@ -124,6 +124,77 @@ char* rjp_member_name(const RJP_value* member){ size_t rjp_member_name_length(RJP_value* member){ return ((RJP_object_member*)member)->name.length; } +RJP_value* rjp_search_member(const RJP_value* object, const char* search, size_t* index, size_t skip){ + RJP_value* member = rjp_get_member(object); + size_t i = 0; + for(;i < skip && member;member = rjp_next_member(member),++i); + + for(;member;member = rjp_next_member(member),++i){ + if(!strcmp(((RJP_object_member*)member)->name.value, search)){ + if(index){ + *index = i; + } + return member; + } + } + return NULL; +} +size_t rjp_search_members(const RJP_value* object, size_t num, const char** searches, RJP_value** dest, size_t skip){ + const char** tmp = rjp_alloc(num*sizeof(char*)); + for(size_t i = 0;i < num;++i){ + tmp[i] = searches[i]; + dest[i] = NULL; + } + RJP_value* member = rjp_get_member(object); + for(size_t i = 0;i < skip && member;member = rjp_next_member(member)); + size_t matches = 0; + + for(;member;member = rjp_next_member(member)){ + for(size_t i = 0;i < num;++i){ + if(searches[i] == NULL) + continue; + if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){ + dest[i] = member; + searches[i] = NULL; + ++matches; + break; + } + } + } + for(size_t i = 0;i < num;++i){ + searches[i] = tmp[i]; + } + rjp_free(tmp); + return matches; +} +RJP_value** rjp_search_members_multi(const RJP_value* object, size_t num, const char** searches, size_t* rsize, size_t skip){ + RJP_value** ret = rjp_alloc(num*sizeof(RJP_value*)); + size_t ret_size = num; + size_t j = 0; + + RJP_value* member = rjp_get_member(object); + for(size_t i = 0;i < skip && member;member = rjp_next_member(member)); + + for(;member;member = rjp_next_member(member)){ + for(size_t i = 0;i < num;++i){ + if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){ + ret[j++] = member; + if(j == ret_size){ + ret_size *= 2; + ret = rjp_realloc(ret, ret_size*sizeof(RJP_value*)); + } + break; + } + } + } + if(rsize) + *rsize = j; + if(j == 0){ + rjp_free(ret); + return NULL; + } + return ret; +} RJP_value* rjp_get_element(const RJP_value* array){ return &array->array.elements->value;