Add support for config file parsing and watching
[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 namespace xapp {
39
40
41 // ------------------------------------------------------------------------
42
43
44
45 // ----------- construction/destruction housekeeping things -------------------
46 /*
47         Accept a string that contains valid json. Causes it to be parsed
48         after which the functions provided by the class can be used to
49         suss out the values.
50 */
51 xapp::Jhash::Jhash( const char* jbuf ) :
52         master_st( NULL ),
53         st( jw_new( jbuf ) )
54 { /* empty body */ }
55
56
57 /*
58         Move constructor.
59 */
60 Jhash::Jhash( Jhash&& soi ) {
61         master_st = soi.master_st;
62         st = soi.st;
63
64         soi.st = NULL;                                          // prevent closing of RMR stuff on soi destroy
65         soi.master_st = NULL;
66 }
67
68 /*
69         Move Operator.
70 */
71 Jhash& Jhash::operator=( Jhash&& soi ) {
72         if( this != &soi ) {                                            // cannot do self assignment
73                 master_st = soi.master_st;
74                 st = soi.st;
75
76                 soi.st = NULL;                                          // prevent closing of RMR stuff on soi destroy
77                 soi.master_st = NULL;
78         }
79
80         return *this;
81 }
82
83 /*
84         Blow it away.
85 */
86 xapp::Jhash::~Jhash() {
87         if( master_st != NULL ) {               // revert blob set if needed
88                 st = master_st;
89         }
90
91         jw_nuke( st );
92         st = NULL;
93         master_st = NULL;
94 }
95
96
97 // ------------ public API ---------------------------------------------------
98
99 // IMPORTANT: all underlying jwrapper functions check for nil st and name pointers
100 //                              so that is NOT needed in this code.
101
102
103 // --- root control ----------------------------------------------------------
104 /*
105         Sets the "root" to the named blob. Until unset, all subsequent
106         calls to Jhash functions (e.g. Is_missing()) will use this for the
107         look up. Returns true if name exists and was indeed a blob.
108
109         It is legit to call set multiple times without unsetting; set
110         overlays with the named root; unset needs only to be called to
111         return to the top level.
112 */
113 bool xapp::Jhash::Set_blob( const char* name ) {
114         void*   bst;                                            // blob symbol table
115
116         if( master_st == NULL ) {                       // must capture master
117                 master_st = st;
118         }
119
120         if( (bst = jw_blob( st, name )) != NULL ) {
121                 st = bst;
122                 return true;
123         }
124
125         return false;
126 }
127
128 /*
129         Return the suss root (blob root) to the root of the symtab.
130 */
131 void xapp::Jhash::Unset_blob( ) {
132         if( master_st != NULL ) {
133                 st = master_st;
134         }
135 }
136
137 // ---------------- debugging and sanity checks ---------------------------------------
138 /*
139         Returns true if there were parse errors which resulted in an empty
140         or non-existant hash.
141
142         Right now we don't have much to work with other than checking for a
143         nil table.
144 */
145 bool xapp::Jhash::Parse_errors( ) {
146         return st == NULL;
147 }
148
149 /*
150         Dump the selected blob as much as we can.
151 */
152 void xapp::Jhash::Dump() {
153         jw_dump( st );
154 }
155
156 // ---------------- type testing -----------------------------------------
157
158 /*
159         These funcitons return true if the named object in the current blob
160         is the indicated type
161 */
162 bool xapp::Jhash::Is_value( const char* name ) {
163         return jw_is_value( st, name ) == 1;
164 }
165
166 bool xapp::Jhash::Is_bool( const char* name ) {
167         return jw_is_bool( st, name ) == 1;
168 }
169
170 bool xapp::Jhash::Is_null( const char* name ) {
171         return jw_is_null( st, name ) == 1;
172 }
173
174 bool xapp::Jhash::Is_string( const char* name ) {
175         return jw_is_string( st, name ) == 1;
176 }
177
178 /*
179         These functions return true if the indicated element in the array
180         <name> is the indicated type.
181 */
182 bool xapp::Jhash::Is_string_ele( const char* name, int eidx ) {
183         return jw_is_string_ele( st, name, eidx ) == 1;
184 }
185
186 bool xapp::Jhash::Is_value_ele( const char* name, int eidx ) {
187         return jw_is_value_ele( st, name, eidx ) == 1;
188 }
189
190 bool xapp::Jhash::Is_bool_ele( const char* name, int eidx ) {
191         return jw_is_bool_ele( st, name, eidx ) == 1;
192 }
193
194 bool xapp::Jhash::Is_null_ele( const char* name, int eidx ) {
195         return jw_is_null_ele( st, name, eidx ) == 1;
196 }
197
198
199 // ---------------- presence ------------------------------------------------
200 /*
201         Returns true if the named element is in the hash.
202 */
203 bool xapp::Jhash::Exists( const char* name ) {
204         return jw_exists( st, name ) == 1;
205 }
206
207 /*
208         Returns true if the named element is not in the hash.
209 */
210 bool xapp::Jhash::Is_missing( const char* name ) {
211         return jw_missing( st, name ) == 1;
212 }
213
214 // ---------------- value sussing ----------------------------------------
215
216 /*
217         Returns the boolean value for the object if it is a bool; false otherwise.
218
219         Symtab saves bool values as 1 for true and doesn't provide a bool fetch
220         function. So, fetch the value and return true if it is 1.
221 */
222 bool xapp::Jhash::Bool( const char* name ) {
223         int v;
224         v = (int) jw_value( st, name );
225
226         return v == 1;
227 }
228
229 /*
230         Returns a C++ string to the named object; If the element is not
231         in the hash an empty string is returned.
232 */
233 std::string xapp::Jhash::String( const char* name ) {
234         std::string rv = "";
235         char*   hashv;
236
237         if( (hashv = jw_string( st, name )) != NULL ) {
238                 rv = std::string( hashv );
239         }
240
241         return rv;
242 }
243
244
245 /*
246         Returns the value assocated with the named object; If the element is not
247         in the hash 0 is returned.
248 */
249 double xapp::Jhash::Value( const char* name ) {
250         return jw_value( st, name );
251 }
252
253 // ------ array related things --------------------------------------------
254
255 /*
256         Return the length of the named array, or -1 if it doesn't exist.
257 */
258 int xapp::Jhash::Array_len( const char* name ) {
259         return jw_array_len( st, name );
260 }
261
262
263 /*
264         Sets the blob in the array <name>[eidx] to the current reference blob.
265 */
266 bool xapp::Jhash::Set_blob_ele( const char* name, int eidx ) {
267         void*   bst;
268
269         if( (bst = jw_obj_ele( st, name, eidx )) != NULL ) {
270                 if( master_st == NULL ) {                       // must capture master
271                         master_st = st;
272                 }
273
274                 st = bst;
275                 return true;
276         }
277
278         return false;
279 }
280 /*
281         Return the string at index eidx in the array <name>.
282 */
283 std::string xapp::Jhash::String_ele( const char* name, int eidx ) {
284         std::string rv = "";
285         char*   hashv;
286
287         if( (hashv = jw_string_ele( st, name, eidx )) != NULL ) {
288                 rv = std::string( hashv );
289         }
290
291         return rv;
292 }
293
294 /*
295         Return the value at index eidx in the array <name>.
296 */
297 double xapp::Jhash::Value_ele( const char* name, int eidx ) {
298         return jw_value_ele( st, name, eidx );
299 }
300
301 /*
302         Return the bool value at index eidx in the array <name>.
303 */
304 bool xapp::Jhash::Bool_ele( const char* name, int eidx ) {
305         return jw_bool_ele( st, name, eidx ) == 1;
306 }
307
308
309
310 } // namespace