// vi: ts=4 sw=4 noet: /* ================================================================================== Copyright (c) 2020 Nokia Copyright (c) 2020 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================================================== */ /* Mnemonic: jhash.cpp Abstract: This class provides the ability to parse a json string into a hashtable, and exposes various functions that can be used to read the data from the hash. Date: 26 June 2020 Author: E. Scott Daniels */ #include #include "jwrapper.h" #include "jhash.hpp" namespace xapp { // ------------------------------------------------------------------------ // ----------- construction/destruction housekeeping things ------------------- /* Accept a string that contains valid json. Causes it to be parsed after which the functions provided by the class can be used to suss out the values. */ xapp::Jhash::Jhash( const char* jbuf ) : master_st( NULL ), st( jw_new( jbuf ) ) { /* empty body */ } /* Move constructor. */ Jhash::Jhash( Jhash&& soi ) { master_st = soi.master_st; st = soi.st; soi.st = NULL; // prevent closing of RMR stuff on soi destroy soi.master_st = NULL; } /* Move Operator. */ Jhash& Jhash::operator=( Jhash&& soi ) { if( this != &soi ) { // cannot do self assignment master_st = soi.master_st; st = soi.st; soi.st = NULL; // prevent closing of RMR stuff on soi destroy soi.master_st = NULL; } return *this; } /* Blow it away. */ xapp::Jhash::~Jhash() { if( master_st != NULL ) { // revert blob set if needed st = master_st; } jw_nuke( st ); st = NULL; master_st = NULL; } // ------------ public API --------------------------------------------------- // IMPORTANT: all underlying jwrapper functions check for nil st and name pointers // so that is NOT needed in this code. // --- root control ---------------------------------------------------------- /* Sets the "root" to the named blob. Until unset, all subsequent calls to Jhash functions (e.g. Is_missing()) will use this for the look up. Returns true if name exists and was indeed a blob. It is legit to call set multiple times without unsetting; set overlays with the named root; unset needs only to be called to return to the top level. */ bool xapp::Jhash::Set_blob( const char* name ) { void* bst; // blob symbol table if( master_st == NULL ) { // must capture master master_st = st; } if( (bst = jw_blob( st, name )) != NULL ) { st = bst; return true; } return false; } /* Return the suss root (blob root) to the root of the symtab. */ void xapp::Jhash::Unset_blob( ) { if( master_st != NULL ) { st = master_st; } } // ---------------- debugging and sanity checks --------------------------------------- /* Returns true if there were parse errors which resulted in an empty or non-existant hash. Right now we don't have much to work with other than checking for a nil table. */ bool xapp::Jhash::Parse_errors( ) { return st == NULL; } /* Dump the selected blob as much as we can. */ void xapp::Jhash::Dump() { jw_dump( st ); } // ---------------- type testing ----------------------------------------- /* These funcitons return true if the named object in the current blob is the indicated type */ bool xapp::Jhash::Is_value( const char* name ) { return jw_is_value( st, name ) == 1; } bool xapp::Jhash::Is_bool( const char* name ) { return jw_is_bool( st, name ) == 1; } bool xapp::Jhash::Is_null( const char* name ) { return jw_is_null( st, name ) == 1; } bool xapp::Jhash::Is_string( const char* name ) { return jw_is_string( st, name ) == 1; } /* These functions return true if the indicated element in the array is the indicated type. */ bool xapp::Jhash::Is_string_ele( const char* name, int eidx ) { return jw_is_string_ele( st, name, eidx ) == 1; } bool xapp::Jhash::Is_value_ele( const char* name, int eidx ) { return jw_is_value_ele( st, name, eidx ) == 1; } bool xapp::Jhash::Is_bool_ele( const char* name, int eidx ) { return jw_is_bool_ele( st, name, eidx ) == 1; } bool xapp::Jhash::Is_null_ele( const char* name, int eidx ) { return jw_is_null_ele( st, name, eidx ) == 1; } // ---------------- presence ------------------------------------------------ /* Returns true if the named element is in the hash. */ bool xapp::Jhash::Exists( const char* name ) { return jw_exists( st, name ) == 1; } /* Returns true if the named element is not in the hash. */ bool xapp::Jhash::Is_missing( const char* name ) { return jw_missing( st, name ) == 1; } // ---------------- value sussing ---------------------------------------- /* Returns the boolean value for the object if it is a bool; false otherwise. Symtab saves bool values as 1 for true and doesn't provide a bool fetch function. So, fetch the value and return true if it is 1. */ bool xapp::Jhash::Bool( const char* name ) { int v; v = (int) jw_value( st, name ); return v == 1; } /* Returns a C++ string to the named object; If the element is not in the hash an empty string is returned. */ std::string xapp::Jhash::String( const char* name ) { std::string rv = ""; char* hashv; if( (hashv = jw_string( st, name )) != NULL ) { rv = std::string( hashv ); } return rv; } /* Returns the value assocated with the named object; If the element is not in the hash 0 is returned. */ double xapp::Jhash::Value( const char* name ) { return jw_value( st, name ); } // ------ array related things -------------------------------------------- /* Return the length of the named array, or -1 if it doesn't exist. */ int xapp::Jhash::Array_len( const char* name ) { return jw_array_len( st, name ); } /* Sets the blob in the array [eidx] to the current reference blob. */ bool xapp::Jhash::Set_blob_ele( const char* name, int eidx ) { void* bst; if( (bst = jw_obj_ele( st, name, eidx )) != NULL ) { if( master_st == NULL ) { // must capture master master_st = st; } st = bst; return true; } return false; } /* Return the string at index eidx in the array . */ std::string xapp::Jhash::String_ele( const char* name, int eidx ) { std::string rv = ""; char* hashv; if( (hashv = jw_string_ele( st, name, eidx )) != NULL ) { rv = std::string( hashv ); } return rv; } /* Return the value at index eidx in the array . */ double xapp::Jhash::Value_ele( const char* name, int eidx ) { return jw_value_ele( st, name, eidx ); } /* Return the bool value at index eidx in the array . */ bool xapp::Jhash::Bool_ele( const char* name, int eidx ) { return jw_bool_ele( st, name, eidx ) == 1; } } // namespace