Line data Source code
1 : //
2 : // ALPHA ROOT analyzer
3 : //
4 : // Access to ODB stored in JSON odb save file or ODB JSON dump in MIDAS data file.
5 : //
6 : // Name: mjsonodb.cxx
7 : // Author: K.Olchanski, 28-May-2019
8 : //
9 :
10 : #include <stdio.h>
11 : #include <assert.h>
12 : #include <stdlib.h>
13 : #include <string.h> // memset()
14 : #include <errno.h> // errno
15 :
16 : #include "mvodb.h"
17 : #include "mjson.h"
18 :
19 0 : static std::string toString(int i)
20 : {
21 : char buf[256];
22 0 : snprintf(buf, sizeof(buf), "%d", i);
23 0 : return buf;
24 : }
25 :
26 : /// Access to ODB saved in JSON format inside midas .mid files
27 :
28 : class JsonOdb : public MVOdb
29 : {
30 : public:
31 : MJsonNode* fRoot; // root of JSON document, NULL if we are a subdirectory
32 : MJsonNode* fDir; // current ODB directory
33 : std::string fPath; // path to correct ODB directory
34 : bool fPrintError;
35 :
36 : public:
37 0 : JsonOdb(MJsonNode* root, MJsonNode* dir, MVOdbError* error) // ctor
38 0 : {
39 0 : fPrintError = false;
40 0 : fRoot = root;
41 0 : fDir = dir;
42 0 : fPath = "";
43 0 : SetOk(error);
44 0 : }
45 :
46 0 : ~JsonOdb() // dtor
47 0 : {
48 0 : if (fRoot) {
49 0 : delete fRoot;
50 0 : fRoot = NULL;
51 : }
52 0 : fDir = NULL;
53 0 : }
54 :
55 : public:
56 0 : void SetPrintError(bool v)
57 : {
58 0 : fPrintError = true;
59 0 : }
60 :
61 0 : bool GetPrintError() const
62 : {
63 0 : return fPrintError;
64 : }
65 :
66 0 : void SetNotFound(MVOdbError* error, const char* varname)
67 : {
68 0 : std::string msg;
69 0 : msg += "Cannot find ";
70 0 : msg += "\"";
71 0 : msg += varname;
72 0 : msg += "\"";
73 0 : SetError(error, fPrintError, fPath, msg);
74 0 : }
75 :
76 0 : void SetVarError(MVOdbError* error, const char* varname, std::string msg)
77 : {
78 0 : std::string path;
79 0 : path += fPath;
80 0 : path += "/";
81 0 : path += varname;
82 0 : SetError(error, fPrintError, path, msg);
83 0 : }
84 :
85 0 : void SetWrongType(MVOdbError* error, const char* varname, const MJsonNode* node, const char* wanted_type)
86 : {
87 0 : std::string path;
88 0 : path += fPath;
89 0 : path += "/";
90 0 : path += varname;
91 0 : std::string msg;
92 0 : msg += "JSON node type mismatch: cannot convert node type ";
93 0 : msg += MJsonNode::TypeToString(node->GetType());
94 0 : msg += " to c++ type ";
95 0 : msg += "\"";
96 0 : msg += wanted_type;
97 0 : msg += "\"";
98 0 : SetError(error, fPrintError, path, msg);
99 0 : }
100 :
101 0 : bool IsReadOnly() const
102 : {
103 0 : return true;
104 : }
105 :
106 : template <typename T>
107 : bool GetJsonValue(const char* varname, const MJsonNode* node, T* value, MVOdbError *error);
108 :
109 : /// Follow the ODB path through the JSON tree
110 0 : static MJsonNode* FindPath(MJsonNode* dir, const char* path)
111 : {
112 0 : assert(dir);
113 :
114 : while (1) {
115 : // skip leading slashes
116 0 : while (*path == '/')
117 0 : path++;
118 :
119 0 : if (*path == 0)
120 0 : return dir;
121 :
122 0 : std::string elem;
123 :
124 : // copy the next path element into "elem"-
125 : // copy "path" until we hit "/" or end of string
126 : while (1) {
127 0 : if (*path==0 || *path=='/')
128 : break;
129 0 : elem += *path++;
130 : }
131 :
132 : //printf("looking for \"%s\" more \"%s\"\n", elem.c_str(), path);
133 :
134 0 : MJsonNode* found = NULL;
135 :
136 0 : const MJsonStringVector* s = dir->GetObjectNames();
137 0 : const MJsonNodeVector* n = dir->GetObjectNodes();
138 0 : assert(s->size() == n->size());
139 :
140 0 : for (unsigned i=0; i<s->size(); i++) {
141 0 : if (strcasecmp(elem.c_str(), (*s)[i].c_str()) == 0) {
142 0 : if (dir->GetType() == MJSON_OBJECT) {
143 : // found the right subdirectory, descend into it
144 0 : found = (*n)[i];
145 0 : break;
146 : } else {
147 0 : return (*n)[i];
148 : }
149 : }
150 : }
151 :
152 0 : if (!found)
153 0 : return NULL;
154 0 : dir = found;
155 0 : }
156 : }
157 :
158 0 : MVOdb* Chdir(const char* subdir, bool create, MVOdbError* error)
159 : {
160 0 : MJsonNode* node = FindPath(fDir, subdir);
161 0 : if (!node) {
162 0 : SetNotFound(error, subdir);
163 0 : if (create) {
164 0 : return MakeNullOdb();
165 : } else {
166 0 : return NULL;
167 : }
168 : }
169 :
170 0 : if (node->GetType() != MJSON_OBJECT) {
171 0 : std::string msg;
172 0 : msg += "\"";
173 0 : msg += subdir;
174 0 : msg += "\"";
175 0 : msg += " JSON node is ";
176 0 : msg += "\"";
177 0 : msg += MJsonNode::TypeToString(node->GetType());
178 0 : msg += "\"";
179 0 : msg += " instead of subdirectory";
180 0 : SetError(error, fPrintError, fPath, msg);
181 0 : if (create)
182 0 : return MakeNullOdb();
183 : else
184 0 : return NULL;
185 0 : }
186 :
187 : //printf("Found subdir [%s]\n", subdir);
188 : //DumpTree(node);
189 :
190 0 : JsonOdb* x = new JsonOdb(NULL, node, error);
191 0 : x->fPath = fPath + "/" + subdir;
192 :
193 0 : SetOk(error);
194 0 : return x;
195 : }
196 :
197 0 : void ReadKey(const char* varname, int *tid, int *num_values, int *total_size, int *item_size, MVOdbError* error)
198 : {
199 0 : if (tid) *tid = 0;
200 0 : if (num_values) *num_values = 0;
201 0 : if (total_size) *total_size = 0;
202 0 : if (item_size) *item_size = 0;
203 : // FIXME: not implemented
204 0 : SetOk(error);
205 0 : }
206 :
207 0 : void ReadKeyLastWritten(const char* varname, int *last_written, MVOdbError* error)
208 : {
209 0 : if (last_written) *last_written = 0;
210 : // FIXME: not implemented
211 0 : SetOk(error);
212 0 : }
213 :
214 0 : void ReadDir(std::vector<std::string>* varname, std::vector<int> *tid, std::vector<int> *num_values, std::vector<int> *total_size, std::vector<int> *item_size, MVOdbError* error)
215 : {
216 : // FIXME: not implemented
217 0 : SetOk(error);
218 0 : }
219 :
220 0 : void RB(const char* varname, bool *value, bool create, MVOdbError* error)
221 : {
222 0 : RBAI(varname, 0, value, error);
223 0 : };
224 :
225 0 : void RI(const char* varname, int *value, bool create, MVOdbError* error)
226 : {
227 0 : RIAI(varname, 0, value, error);
228 0 : };
229 :
230 0 : void RD(const char* varname, double *value, bool create, MVOdbError* error)
231 : {
232 0 : RDAI(varname, 0, value, error);
233 0 : };
234 :
235 0 : void RF(const char* varname, float *value, bool create, MVOdbError* error)
236 : {
237 0 : RFAI(varname, 0, value, error);
238 0 : };
239 :
240 0 : void RS(const char* varname, std::string *value, bool create, int create_string_length, MVOdbError* error)
241 : {
242 0 : RSAI(varname, 0, value, error);
243 0 : };
244 :
245 0 : void RU16(const char* varname, uint16_t *value, bool create, MVOdbError* error)
246 : {
247 0 : RU16AI(varname, 0, value, error);
248 0 : };
249 :
250 0 : void RU32(const char* varname, uint32_t *value, bool create, MVOdbError* error)
251 : {
252 0 : RU32AI(varname, 0, value, error);
253 0 : };
254 :
255 : template <typename T>
256 0 : void RXA(const char* varname, std::vector<T> *value, MVOdbError* error)
257 : {
258 0 : if (!value) {
259 0 : SetOk(error);
260 0 : return;
261 : }
262 :
263 0 : MJsonNode* node = FindPath(fDir, varname);
264 0 : if (!node) {
265 0 : SetNotFound(error, varname);
266 0 : return;
267 : }
268 :
269 : //DumpTree(node);
270 :
271 0 : if (node->GetType() == MJSON_OBJECT) {
272 0 : SetVarError(error, varname, "JSON node is a subdirectory");
273 0 : return;
274 0 : } else if (node->GetType() == MJSON_ARRAY) {
275 :
276 0 : const MJsonNodeVector* a = node->GetArray();
277 :
278 0 : int num_values = a->size();
279 :
280 0 : value->clear();
281 :
282 0 : for (int i=0; i<num_values; i++) {
283 0 : const MJsonNode* elem = (*a)[i];
284 0 : T v;
285 0 : bool ok = GetJsonValue<T>(varname, elem, &v, error);
286 0 : if (!ok)
287 0 : break;
288 0 : value->push_back(v);
289 : }
290 : } else {
291 0 : T v;
292 0 : bool ok = GetJsonValue<T>(varname, node, &v, error);
293 0 : if (!ok)
294 0 : return;
295 0 : value->clear();
296 0 : value->push_back(v);
297 0 : }
298 : };
299 :
300 0 : void RBA(const char* varname, std::vector<bool> *value, bool create, int create_size, MVOdbError* error)
301 : {
302 0 : RXA(varname, value, error);
303 0 : }
304 :
305 0 : void RIA(const char* varname, std::vector<int> *value, bool create, int create_size, MVOdbError* error)
306 : {
307 0 : RXA(varname, value, error);
308 0 : }
309 :
310 0 : void RDA(const char* varname, std::vector<double> *value, bool create, int create_size, MVOdbError* error)
311 : {
312 0 : RXA(varname, value, error);
313 0 : }
314 :
315 0 : void RFA(const char* varname, std::vector<float> *value, bool create, int create_size, MVOdbError* error)
316 : {
317 0 : RXA(varname, value, error);
318 0 : }
319 :
320 0 : void RSA(const char* varname, std::vector<std::string> *value, bool create, int create_size, int create_string_length, MVOdbError* error)
321 : {
322 0 : RXA(varname, value, error);
323 0 : }
324 :
325 0 : void RU16A(const char* varname, std::vector<uint16_t> *value, bool create, int create_size, MVOdbError* error)
326 : {
327 0 : RXA(varname, value, error);
328 0 : }
329 :
330 0 : void RU32A(const char* varname, std::vector<uint32_t> *value, bool create, int create_size, MVOdbError* error)
331 : {
332 0 : RXA(varname, value, error);
333 0 : }
334 :
335 : template <typename T>
336 0 : void RXAI(const char* varname, int index, T* value, MVOdbError* error)
337 : {
338 0 : if (!value) {
339 0 : SetOk(error);
340 0 : return;
341 : }
342 :
343 0 : MJsonNode* node = FindPath(fDir, varname);
344 0 : if (!node) {
345 0 : SetNotFound(error, varname);
346 0 : return;
347 : }
348 :
349 : //printf("varname [%s] index %d, found node %p:\n", varname, index, node);
350 : //node->Dump();
351 :
352 0 : if (node->GetType() == MJSON_OBJECT) {
353 0 : SetVarError(error, varname, "JSON node is a subdirectory");
354 0 : return;
355 0 : } else if (node->GetType() == MJSON_ARRAY) {
356 : //DumpTree(node);
357 :
358 0 : const MJsonNodeVector* a = node->GetArray();
359 :
360 0 : int num_values = a->size();
361 :
362 0 : if (index < 0) {
363 0 : std::string msg;
364 0 : msg += "bad index ";
365 0 : msg += toString(index);
366 0 : msg += " for array of size ";
367 0 : msg += toString(num_values);
368 0 : SetVarError(error, varname, msg);
369 0 : return;
370 0 : }
371 :
372 0 : if (index >= num_values) {
373 0 : std::string msg;
374 0 : msg += "bad index ";
375 0 : msg += toString(index);
376 0 : msg += " for array of size ";
377 0 : msg += toString(num_values);
378 0 : SetVarError(error, varname, msg);
379 0 : return;
380 0 : }
381 :
382 0 : MJsonNode* elem = (*a)[index];
383 :
384 0 : GetJsonValue<T>(varname, elem, value, error);
385 0 : return;
386 : } else {
387 0 : if (index != 0) {
388 0 : std::string msg;
389 0 : msg += "non-zero index ";
390 0 : msg += toString(index);
391 0 : msg += " for non-array";
392 0 : SetVarError(error, varname, msg);
393 0 : return;
394 0 : }
395 :
396 0 : GetJsonValue<T>(varname, node, value, error);
397 0 : return;
398 : }
399 : }
400 :
401 0 : void RBAI(const char* varname, int index, bool *value, MVOdbError* error)
402 : {
403 0 : RXAI(varname, index, value, error);
404 0 : }
405 :
406 0 : void RIAI(const char* varname, int index, int *value, MVOdbError* error)
407 : {
408 0 : RXAI(varname, index, value, error);
409 0 : }
410 :
411 0 : void RDAI(const char* varname, int index, double *value, MVOdbError* error)
412 : {
413 0 : RXAI(varname, index, value, error);
414 0 : }
415 :
416 0 : void RFAI(const char* varname, int index, float *value, MVOdbError* error)
417 : {
418 0 : RXAI(varname, index, value, error);
419 0 : }
420 :
421 0 : void RSAI(const char* varname, int index, std::string *value, MVOdbError* error)
422 : {
423 0 : RXAI(varname, index, value, error);
424 0 : }
425 :
426 0 : void RU16AI(const char* varname, int index, uint16_t *value, MVOdbError* error)
427 : {
428 0 : RXAI(varname, index, value, error);
429 0 : }
430 :
431 0 : void RU32AI(const char* varname, int index, uint32_t *value, MVOdbError* error)
432 : {
433 0 : RXAI(varname, index, value, error);
434 0 : }
435 :
436 : // write functions do nothing
437 :
438 0 : void WB(const char* varname, bool v, MVOdbError* error) { SetOk(error); };
439 0 : void WI(const char* varname, int v, MVOdbError* error) { SetOk(error); };
440 0 : void WD(const char* varname, double v, MVOdbError* error) { SetOk(error); };
441 0 : void WF(const char* varname, float v, MVOdbError* error) { SetOk(error); };
442 0 : void WS(const char* varname, const char* v, int string_length, MVOdbError* error) { SetOk(error); };
443 0 : void WU16(const char* varname, uint16_t v, MVOdbError* error) { SetOk(error); };
444 0 : void WU32(const char* varname, uint32_t v, MVOdbError* error) { SetOk(error); };
445 :
446 0 : void WBA(const char* varname, const std::vector<bool>& v, MVOdbError* error) { SetOk(error); };
447 0 : void WIA(const char* varname, const std::vector<int>& v, MVOdbError* error) { SetOk(error); };
448 0 : void WDA(const char* varname, const std::vector<double>& v, MVOdbError* error) { SetOk(error); };
449 0 : void WFA(const char* varname, const std::vector<float>& v, MVOdbError* error) { SetOk(error); };
450 0 : void WSA(const char* varname, const std::vector<std::string>& data, int odb_string_length, MVOdbError* error) { SetOk(error); };
451 0 : void WU16A(const char* varname, const std::vector<uint16_t>& v, MVOdbError* error) { SetOk(error); };
452 0 : void WU32A(const char* varname, const std::vector<uint32_t>& v, MVOdbError* error) { SetOk(error); };
453 :
454 0 : void WBAI(const char* varname, int index, bool v, MVOdbError* error) { SetOk(error); };
455 0 : void WIAI(const char* varname, int index, int v, MVOdbError* error) { SetOk(error); };
456 0 : void WDAI(const char* varname, int index, double v, MVOdbError* error) { SetOk(error); };
457 0 : void WFAI(const char* varname, int index, float v, MVOdbError* error) { SetOk(error); };
458 0 : void WSAI(const char* varname, int index, const char* v, MVOdbError* error) { SetOk(error); };
459 0 : void WU16AI(const char* varname, int index, uint16_t v, MVOdbError* error) { SetOk(error); };
460 0 : void WU32AI(const char* varname, int index, uint32_t v, MVOdbError* error) { SetOk(error); };
461 :
462 : // delete function does nothing
463 :
464 0 : void Delete(const char* odbname, MVOdbError* error) { SetOk(error); };
465 : };
466 :
467 : template<>
468 0 : bool JsonOdb::GetJsonValue<int>(const char* varname, const MJsonNode* node, int* value, MVOdbError* error)
469 : {
470 0 : switch (node->GetType()) {
471 0 : case MJSON_INT: *value = node->GetInt(); SetOk(error); return true;
472 0 : default: SetWrongType(error, varname, node, "int"); return false;
473 : }
474 : }
475 :
476 : template<>
477 0 : bool JsonOdb::GetJsonValue<double>(const char* varname, const MJsonNode* node, double* value, MVOdbError* error)
478 : {
479 0 : switch (node->GetType()) {
480 0 : case MJSON_INT: *value = (double)node->GetInt(); SetOk(error); return true;
481 0 : case MJSON_NUMBER: *value = node->GetDouble(); SetOk(error); return true;
482 0 : default: SetWrongType(error, varname, node, "double"); return false;
483 : }
484 : }
485 :
486 : template<>
487 0 : bool JsonOdb::GetJsonValue<float>(const char* varname, const MJsonNode* node, float* value, MVOdbError* error)
488 : {
489 0 : switch (node->GetType()) {
490 0 : case MJSON_INT: *value = (float)node->GetInt(); SetOk(error); return true;
491 0 : case MJSON_NUMBER: *value = node->GetDouble(); SetOk(error); return true;
492 0 : default: SetWrongType(error, varname, node, "float"); return false;
493 : }
494 : }
495 :
496 : template<>
497 0 : bool JsonOdb::GetJsonValue<bool>(const char* varname, const MJsonNode* node, bool* value, MVOdbError* error)
498 : {
499 0 : switch (node->GetType()) {
500 : //case MJSON_INT: *value = node->GetInt(); SetOk(error); return true;
501 : //case MJSON_NUMBER: *value = node->GetDouble(); SetOk(error); return true;
502 0 : case MJSON_BOOL: *value = node->GetBool(); SetOk(error); return true;
503 0 : default: SetWrongType(error, varname, node, "bool"); return false;
504 : }
505 : }
506 :
507 : template<>
508 0 : bool JsonOdb::GetJsonValue<uint16_t>(const char* varname, const MJsonNode* node, uint16_t* value, MVOdbError* error)
509 : {
510 0 : switch (node->GetType()) {
511 0 : case MJSON_INT: *value = (0xFFFF & node->GetInt()); SetOk(error); return true;
512 0 : case MJSON_STRING: *value = (0xFFFF & strtoul(node->GetString().c_str(), NULL, 0)); SetOk(error); return true;
513 0 : default: SetWrongType(error, varname, node, "uint16_t"); return false;
514 : }
515 : }
516 :
517 : template<>
518 0 : bool JsonOdb::GetJsonValue<uint32_t>(const char* varname, const MJsonNode* node, uint32_t* value, MVOdbError* error)
519 : {
520 0 : switch (node->GetType()) {
521 0 : case MJSON_INT: *value = node->GetInt(); SetOk(error); return true;
522 0 : case MJSON_STRING: *value = strtoul(node->GetString().c_str(), NULL, 0); SetOk(error); return true;
523 0 : default: SetWrongType(error, varname, node, "uint32_t"); return false;
524 : }
525 : }
526 :
527 : template<>
528 0 : bool JsonOdb::GetJsonValue<std::string>(const char* varname, const MJsonNode* node, std::string* value, MVOdbError* error)
529 : {
530 0 : switch (node->GetType()) {
531 0 : case MJSON_STRING: *value = node->GetString(); SetOk(error); return true;
532 0 : default: SetWrongType(error, varname, node, "std::string"); return false;
533 : }
534 : }
535 :
536 0 : MVOdb* MakeJsonFileOdb(const char* filename, MVOdbError* error)
537 : {
538 0 : std::string data;
539 :
540 : {
541 0 : FILE *fp = fopen(filename, "r");
542 0 : if (!fp) {
543 0 : std::string msg;
544 0 : msg += "Cannot open file ";
545 0 : msg += "\"";
546 0 : msg += filename;
547 0 : msg += "\"";
548 0 : msg += " fopen() errno: ";
549 0 : msg += toString(errno);
550 0 : msg += " (";
551 0 : msg += strerror(errno);
552 0 : msg += ")";
553 0 : SetError(error, true, filename, msg);
554 0 : return MakeNullOdb();
555 0 : }
556 :
557 : while (1) {
558 : char buf[1024*1024];
559 0 : const char* s = fgets(buf, sizeof(buf), fp);
560 0 : if (!s)
561 0 : break;
562 0 : data += s;
563 0 : }
564 :
565 0 : fclose(fp);
566 0 : fp = NULL;
567 : }
568 :
569 0 : MJsonNode* root = MJsonNode::Parse(data.c_str());
570 : //root->Dump();
571 0 : return new JsonOdb(root, root, error);
572 0 : }
573 :
574 0 : MVOdb* MakeJsonBufferOdb(const char* buf, int bufsize, MVOdbError* error)
575 : {
576 0 : MJsonNode* root = MJsonNode::Parse(buf);
577 : //root->Dump();
578 0 : return new JsonOdb(root, root, error);
579 : //return MakeNullOdb();
580 : }
581 :
582 : /* emacs
583 : * Local Variables:
584 : * tab-width: 8
585 : * c-basic-offset: 3
586 : * indent-tabs-mode: nil
587 : * End:
588 : */
|