Fix json blob selection bug
[ric-plt/xapp-frame-cpp.git] / src / json / jhash.cpp
1 // vi: ts=4 sw=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2020 Nokia
5         Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       jhash.cpp
23         Abstract:       This class provides the ability to parse a json string into
24                                 a hashtable, and exposes various functions that can be used
25                                 to read the data from the hash.
26
27         Date:           26 June 2020
28         Author:         E. Scott Daniels
29 */
30
31
32 #include <string>
33
34 #include "jwrapper.h"
35 #include "jhash.hpp"
36
37 // ------------------------------------------------------------------------
38
39
40
41 // ----------- construction/destruction housekeeping things -------------------
42 /*
43         Accept a string that contains valid json. Causes it to be parsed
44         after which the functions provided by the class can be used to
45         suss out the values.
46 */
47 Jhash::Jhash( const char* jbuf ) :
48         master_st( NULL ),
49         st( jw_new( jbuf ) )
50 { /* empty body */ }
51
52
53 /*
54         Move constructor.
55 */
56 Jhash::Jhash( Jhash&& soi ) {
57         master_st = soi.master_st;
58         st = soi.st;
59
60         soi.st = NULL;                                          // prevent closing of RMR stuff on soi destroy
61         soi.master_st = NULL;
62 }
63
64 /*
65         Move Operator.
66 */
67 Jhash& Jhash::operator=( Jhash&& soi ) {
68         if( this != &soi ) {                                            // cannot do self assignment
69                 master_st = soi.master_st;
70                 st = soi.st;
71
72                 soi.st = NULL;                                          // prevent closing of RMR stuff on soi destroy
73                 soi.master_st = NULL;
74         }
75
76         return *this;
77 }
78
79 /*
80         Blow it away.
81 */
82 Jhash::~Jhash() {
83         if( master_st != NULL ) {               // revert blob set if needed
84                 st = master_st;
85         }
86
87         jw_nuke( st );
88         st = NULL;
89         master_st = NULL;
90 }
91
92
93 // ------------ public API ---------------------------------------------------
94
95 // IMPORTANT: all underlying jwrapper functions check for nil st and name pointers
96 //                              so that is NOT needed in this code.
97
98
99 // --- root control ----------------------------------------------------------
100 /*
101         Sets the "root" to the named blob. Until unset, all subsequent
102         calls to Jhash functions (e.g. Is_missing()) will use this for the
103         look up. Returns true if name exists and was indeed a blob.
104
105         It is legit to call set multiple times without unsetting; set
106         overlays with the named root; unset needs only to be called to
107         return to the top level.
108 */
109 bool Jhash::Set_blob( const char* name ) {
110         void*   bst;                                            // blob symbol table
111
112         if( master_st == NULL ) {                       // must capture master
113                 master_st = st;
114         }
115
116         if( (bst = jw_blob( st, name )) != NULL ) {
117                 st = bst;
118                 return true;
119         }
120
121         return false;
122 }
123
124 /*
125         Return the suss root (blob root) to the root of the symtab.
126 */
127 void Jhash::Unset_blob( ) {
128         if( master_st != NULL ) {
129                 st = master_st;
130         }
131 }
132
133 // ---------------- debugging and sanity checks ---------------------------------------
134 /*
135         Returns true if there were parse errors which resulted in an empty
136         or non-existant hash.
137
138         Right now we don't have much to work with other than checking for a
139         nil table.
140 */
141 bool Jhash::Parse_errors( ) {
142         return st == NULL;
143 }
144
145 /*
146         Dump the selected blob as much as we can.
147 */
148 void Jhash::Dump() {
149         jw_dump( st );
150 }
151
152 // ---------------- type testing -----------------------------------------
153
154 /*
155         These funcitons return true if the named object in the current blob
156         is the indicated type
157 */
158 bool Jhash::Is_value( const char* name ) {
159         return jw_is_value( st, name ) == 1;
160 }
161
162 bool Jhash::Is_bool( const char* name ) {
163         return jw_is_bool( st, name ) == 1;
164 }
165
166 bool Jhash::Is_null( const char* name ) {
167         return jw_is_null( st, name ) == 1;
168 }
169
170 bool Jhash::Is_string( const char* name ) {
171         return jw_is_string( st, name ) == 1;
172 }
173
174 /*
175         These functions return true if the indicated element in the array
176         <name> is the indicated type.
177 */
178 bool Jhash::Is_string_ele( const char* name, int eidx ) {
179         return jw_is_string_ele( st, name, eidx ) == 1;
180 }
181
182 bool Jhash::Is_value_ele( const char* name, int eidx ) {
183         return jw_is_value_ele( st, name, eidx ) == 1;
184 }
185
186 bool Jhash::Is_bool_ele( const char* name, int eidx ) {
187         return jw_is_bool_ele( st, name, eidx ) == 1;
188 }
189
190 bool Jhash::Is_null_ele( const char* name, int eidx ) {
191         return jw_is_null_ele( st, name, eidx ) == 1;
192 }
193
194
195 // ---------------- presence ------------------------------------------------
196 /*
197         Returns true if the named element is in the hash.
198 */
199 bool Jhash::Exists( const char* name ) {
200         return jw_exists( st, name ) == 1;
201 }
202
203 /*
204         Returns true if the named element is not in the hash.
205 */
206 bool Jhash::Is_missing( const char* name ) {
207         return jw_missing( st, name ) == 1;
208 }
209
210 // ---------------- value sussing ----------------------------------------
211
212 /*
213         Returns the boolean value for the object if it is a bool; false otherwise.
214
215         Symtab saves bool values as 1 for true and doesn't provide a bool fetch
216         function. So, fetch the value and return true if it is 1.
217 */
218 bool Jhash::Bool( const char* name ) {
219         int v;
220         v = (int) jw_value( st, name );
221         return v == 1;
222 }
223
224 /*
225         Returns a C++ string to the named object; If the element is not
226         in the hash an empty string is returned.
227 */
228 std::string Jhash::String( const char* name ) {
229         std::string rv = "";
230         char*   hashv;
231
232         if( (hashv = jw_string( st, name )) != NULL ) {
233                 rv = std::string( hashv );
234         }
235
236         return rv;
237 }
238
239
240 /*
241         Returns the value assocated with the named object; If the element is not
242         in the hash 0 is returned.
243 */
244 double Jhash::Value( const char* name ) {
245         return jw_value( st, name );
246 }
247
248 // ------ array related things --------------------------------------------
249
250 /*
251         Return the length of the named array, or -1 if it doesn't exist.
252 */
253 int Jhash::Array_len( const char* name ) {
254         return jw_array_len( st, name );
255 }
256
257
258 /*
259         Sets the blob in the array <name>[eidx] to the current reference blob.
260 */
261 bool Jhash::Set_blob_ele( const char* name, int eidx ) {
262         void*   bst;
263
264         if( (bst = jw_obj_ele( st, name, eidx )) != NULL ) {
265                 if( master_st == NULL ) {                       // must capture master
266                         master_st = st;
267                 }
268
269                 st = bst;
270                 return true;
271         }
272
273         return false;
274 }
275 /*
276         Return the string at index eidx in the array <name>.
277 */
278 std::string Jhash::String_ele( const char* name, int eidx ) {
279         std::string rv = "";
280         char*   hashv;
281
282         if( (hashv = jw_string_ele( st, name, eidx )) != NULL ) {
283                 rv = std::string( hashv );
284         }
285
286         return rv;
287 }
288
289 /*
290         Return the value at index eidx in the array <name>.
291 */
292 double Jhash::Value_ele( const char* name, int eidx ) {
293         return jw_value_ele( st, name, eidx );
294 }
295
296 /*
297         Return the bool value at index eidx in the array <name>.
298 */
299 bool Jhash::Bool_ele( const char* name, int eidx ) {
300         return jw_bool_ele( st, name, eidx ) == 1;
301 }
302