Medial Code Documentation
Loading...
Searching...
No Matches
SerializableObject_imp.h
1#ifndef __SERIALIZABLE_OBJECT_IMP_LIB_H__
2#define __SERIALIZABLE_OBJECT_IMP_LIB_H__
3
4#include <type_traits>
5#include <typeinfo>
6#include <regex>
7
8#if __GNUC__
9#if __cplusplus < 201402L
10template< bool B, class T = void >
11using enable_if_t = typename enable_if<B, T>::type;
12#endif
13#endif // !_
14
15namespace MedSerialize {
16
17 // Helper function to parse names and clean spaces, tabs, etc
18 static void get_list_names(char *list_of_args, vector<string> &names) {
19 // get names
20 string s(list_of_args);
21 boost::replace_all(s, " ", "");
22 boost::replace_all(s, "\t", "");
23 boost::replace_all(s, "\n", "");
24 boost::split(names, s, boost::is_any_of(","));
25 }
26
27 //========================================================================================
28 // FUNCTION FROM BELOW THAT IMPLEMENT AN STD CONTAINER (map, vector, etc)
29 // MUST BE PRE DECLARED HERE BEFORE THE IMPLEMENTATION
30 // TO MAKE SURE THE CORRECT RECURSIVE RESOLVING IS DONE
31 // (simple, string & variadic need not - and will create a compilation error)
32 //========================================================================================
33
34 template <class T> size_t get_size(T *&v);
35 template <class T> size_t serialize(unsigned char *blob, T *&v);
36 template <class T> size_t deserialize(unsigned char *blob, T *&v);
37 template <class T> string object_json(T *&v);
38 template <class T> string object_json(const T *&v);
39 template <class T> string object_json(T * const &v);
40 template <class T> size_t get_size(vector<T> &v);
41 template <class T> size_t serialize(unsigned char *blob, vector<T> &v);
42 template <class T> size_t deserialize(unsigned char *blob, vector<T> &v);
43 template <class T> string object_json(const vector<const T> &v);
44 template <class T> string object_json(const vector<T> &v);
45 template <class T> string object_json(vector<const T> &v);
46 template <class T, class S> size_t get_size(pair<T, S> &v);
47 template <class T, class S> size_t serialize(unsigned char *blob, pair<T, S> &v);
48 template <class T, class S> size_t deserialize(unsigned char *blob, pair<T, S> &v);
49 template <class T, class S> string object_json(pair<const T, const S> &v);
50 template <class T, class S> string object_json(const pair<T, S> &v);
51 template <class T, class S> string object_json(const pair<const T, const S> &v);
52 template <class T, class S> size_t get_size(map<T, S> &v);
53 template <class T, class S> size_t serialize(unsigned char *blob, map<T, S> &v);
54 template <class T, class S> size_t deserialize(unsigned char *blob, map<T, S> &v);
55 template <class T, class S> string object_json(map<const T, const S> &v);
56 template <class T, class S> string object_json(const map<const T, const S> &v);
57 template <class T, class S> string object_json(const map<T, S> &v);
58 template <class T, class S> size_t get_size(unordered_map<T, S> &v);
59 template <class T, class S> size_t serialize(unsigned char *blob, unordered_map<T, S> &v);
60 template <class T, class S> size_t deserialize(unsigned char *blob, unordered_map<T, S> &v);
61 template <class T, class S> string object_json(unordered_map<const T, const S> &v);
62 template <class T, class S> string object_json(const unordered_map<const T, const S> &v);
63 template <class T, class S> string object_json(const unordered_map<T, S> &v);
64 template <class T> size_t get_size(unordered_set<T> &v);
65 template <class T> size_t serialize(unsigned char *blob, unordered_set<T> &v);
66 template <class T> size_t deserialize(unsigned char *blob, unordered_set<T> &v);
67 template <class T> string object_json(unordered_set<const T> &v);
68 template <class T> string object_json(const unordered_set<const T> &v);
69 template <class T> string object_json(const unordered_set<T> &v);
70 template <class T> size_t get_size(set<T> &v);
71 template <class T> size_t serialize(unsigned char *blob, set<T> &v);
72 template <class T> size_t deserialize(unsigned char *blob, set<T> &v);
73 template <class T> string object_json(set<const T> &v);
74 template <class T> string object_json(const set<const T> &v);
75 template <class T> string object_json(const set<T> &v);
76 template <class T> size_t get_size(unique_ptr<T> &v);
77 template <class T> size_t serialize(unsigned char *blob, unique_ptr<T> &v);
78 template <class T> size_t deserialize(unsigned char *blob, unique_ptr<T> &v);
79 template <class T> string object_json(unique_ptr<T> &v);
80 template <class T> string object_json(unique_ptr<const T> &v);
81
82 //========================================================================================
83 // IMPLEMANTATIONS
84 //========================================================================================
85
86 //.........................................................................................
87 // templated simple ones : int, float, long, double, etc...
88 //.........................................................................................
89 template <class T> size_t get_size(T &elem)
90 {
91 //cout << "inside simple getsize with type " << typeid(T).name() << endl;
92 return sizeof(T);
93 }
94
95 //.........................................................................................
96 template <class T> size_t serialize(unsigned char *blob, T &elem)
97 {
98 //cout << "inside simple serialize with type " << typeid(T).name() << " with sizeof " << sizeof(T) << endl;
99 memcpy(blob, &elem, sizeof(T));
100 //unsigned char *pelem = (unsigned char *)(&elem);
101 //SRL_LOG("simple serialize: %02x %02x %02x %02x\n", blob[0], blob[1], blob[2], blob[3]);
102 return sizeof(T);
103 }
104
105 //.........................................................................................
106 template <class T> size_t deserialize(unsigned char *blob, T &elem)
107 {
108 //cerr << "inside simple deserialize with type " << typeid(T).name() << " with sizeof " << sizeof(T) << endl;
109 memcpy(&elem, blob, sizeof(T));
110 //unsigned char *pelem = (unsigned char *)(&elem);
111 //SRL_LOG("simple deserialize: %02x %02x %02x %02x\n", blob[0], blob[1], blob[2], blob[3]);
112 return sizeof(T);
113 }
114
115 template<class T>
116 string object_json_spec(T& v, std::true_type /* is_enum */, std::false_type) {
117 stringstream str;
118 //it's object:
119 string enum_nm = typeid(v).name();
120 //remove number prefix:
121 enum_nm = std::regex_replace(enum_nm, std::regex("^([0-9]*|enum )"), "");
122 str << enum_nm << "::" << (int)v;
123 return str.str();
124 }
125 template<class T>
126 string object_json_spec(T& v, std::false_type, std::true_type /* SerializableObject */) {
127 stringstream str;
128 str << v.object_json();
129 return str.str();
130 }
131 template<class T>
132 string object_json_spec(T& v, std::false_type, std::false_type) {
133 // neither
134 stringstream str;
135 str << "UNSUPPORTED::" << typeid(v).name();
136 return str.str();
137 }
138
139 template<class T>
140 string object_json(T& v) {
141 return object_json_spec(v, std::is_enum<T>{}, std::is_base_of<SerializableObject, T>{});
142 }
143
144 //.........................................................................................
145 // T * case : will ONLY Work for classes implementing the new_polymorphic, and my_class_name methods !!
146 // Also assumes a SINGLE new (not an array).
147 //.........................................................................................
148 template <class T> size_t get_size(T *&elem)
149 {
150 //cerr << "get size of T *\n";
151 size_t size = 0;
152
153 if (elem == NULL) {
154 // account for "NULL" string when pointer is null
155 string s = "NULL";
156 size += MedSerialize::get_size(s);
157 }
158 else {
159 string s = elem->my_class_name(); // help compiler
160 //cerr << "get size of T * (2) : class" << s << "\n";
161 size += MedSerialize::get_size(s); // account for class name
162 size += MedSerialize::get_size((*elem)); // account for class serialization
163 }
164 //cerr << "get size of T * (3) : size" << size << "\n";
165 return size;
166 }
167
168 //.........................................................................................
169 template <class T> size_t serialize(unsigned char *blob, T *&elem)
170 {
171 //cerr << "Serializing T * for " << (elem != NULL) ? elem->my_class_name().c_str() : string("NULL").c_str() << "\n";
172 size_t pos = 0;
173
174 // serializing name of class, for polymorphic support
175 // we will detect NULL pointers by simply writing "NULL" into the serialization
176 string s = "NULL";
177 if (elem != NULL)
178 s = elem->my_class_name(); // help compiler
179 pos += MedSerialize::serialize<string>(blob + pos, s);
180
181 // serializing the actual class
182 //cerr << "Serializing T * (2) : class name is " << s << " pos " << pos << "\n";
183 if (elem != NULL)
184 pos += MedSerialize::serialize(blob + pos, (*elem));
185
186 //cerr << "Serializing T * (4) : pos " << pos << "\n";
187 return pos;
188 }
189
190 //.........................................................................................
191 template <class T> size_t deserialize(unsigned char *blob, T *&elem)
192 {
193 //cerr << "DeSerializing T * \n";
194
195 size_t pos = 0;
196
197 // deserialize name of class
198 string cname;
199 pos += MedSerialize::deserialize<string>(blob + pos, cname);
200
201 //cerr << "Deserializing T * (2) : Got class name " << cname << " pos " << pos << "\n";
202
203 if (cname == "NULL") {
204 elem = NULL;
205 }
206 else {
207 // heart of matters: doing the right new operation
208 T dummy; // we need access to the new_polymorphic method
209 elem = (T *)dummy.new_polymorphic(cname);
210 //cerr << "Deserializing T * (3) : elem is " << elem << "\n";
211 if (elem == NULL) {
212 elem = new T;
213 }
214
215 //cerr << "Deserializing T * (4) : elem is " << elem << "\n";
216
217 // now we are ready to deserialize T or its derived
218 pos += MedSerialize::deserialize(blob + pos, (*elem));
219 }
220
221 //cerr << "Deserializing T * (4) : pos " << pos << "\n";
222 return pos;
223 }
224
225 template <class T> string object_json(T *&v) {
226 stringstream str;
227 //it's object:
228 if (v != NULL) {
229 str << MedSerialize::object_json((const T&)*v);
230 }
231 else
232 str << "NULL";
233 return str.str();
234 }
235 template <class T> string object_json(const T *&v) {
236 stringstream str;
237 if (v != NULL) {
238 //it's object:
239 str << MedSerialize::object_json((const T&)*v);
240 }
241 else
242 str << "NULL";
243 return str.str();
244 }
245 template <class T> string object_json(T * const &v) {
246 stringstream str;
247 if (v != NULL) {
248 //it's object:
249 str << MedSerialize::object_json((const T&)*v);
250 }
251 else
252 str << "NULL";
253 return str.str();
254 }
255
256
257
258 template <class T> size_t get_size(unique_ptr<T> &elem)
259 {
260 //cerr << "get size of T *\n";
261 size_t size = 0;
262
263 if (elem.get() == NULL) {
264 // account for "NULL" string when pointer is null
265 string s = "NULL";
266 size += MedSerialize::get_size(s);
267 }
268 else {
269 string s = elem->my_class_name(); // help compiler
270 //cerr << "get size of T * (2) : class" << s << "\n";
271 size += MedSerialize::get_size(s); // account for class name
272 size += MedSerialize::get_size((*elem)); // account for class serialization
273 }
274 //cerr << "get size of T * (3) : size" << size << "\n";
275 return size;
276 }
277
278 //.........................................................................................
279 template <class T> size_t serialize(unsigned char *blob, unique_ptr<T> &elem)
280 {
281 //cerr << "Serializing T * for " << (elem != NULL) ? elem->my_class_name().c_str() : string("NULL").c_str() << "\n";
282 size_t pos = 0;
283
284 // serializing name of class, for polymorphic support
285 // we will detect NULL pointers by simply writing "NULL" into the serialization
286 string s = "NULL";
287 if (elem.get() != NULL)
288 s = elem->my_class_name(); // help compiler
289 pos += MedSerialize::serialize<string>(blob + pos, s);
290
291 // serializing the actual class
292 //cerr << "Serializing T * (2) : class name is " << s << " pos " << pos << "\n";
293 if (elem.get() != NULL)
294 pos += MedSerialize::serialize(blob + pos, (*elem));
295
296 //cerr << "Serializing T * (4) : pos " << pos << "\n";
297 return pos;
298 }
299
300 //.........................................................................................
301 template <class T> size_t deserialize(unsigned char *blob, unique_ptr<T> &elem)
302 {
303 //cerr << "DeSerializing T * \n";
304
305 size_t pos = 0;
306
307 // deserialize name of class
308 string cname;
309 pos += MedSerialize::deserialize<string>(blob + pos, cname);
310
311 //cerr << "Deserializing T * (2) : Got class name " << cname << " pos " << pos << "\n";
312
313 if (cname == "NULL") {
314 elem = NULL;
315 }
316 else {
317 // heart of matters: doing the right new operation
318 T dummy; // we need access to the new_polymorphic method
319 elem = unique_ptr<T>((T *)dummy.new_polymorphic(cname));
320 //cerr << "Deserializing T * (3) : elem is " << elem << "\n";
321 if (elem.get() == NULL) {
322 elem = unique_ptr<T>(new T);
323 }
324
325 //cerr << "Deserializing T * (4) : elem is " << elem << "\n";
326
327 // now we are ready to deserialize T or its derived
328 pos += MedSerialize::deserialize(blob + pos, (*elem.get()));
329 }
330
331 //cerr << "Deserializing T * (4) : pos " << pos << "\n";
332 return pos;
333 }
334
335 template <class T> string object_json(unique_ptr<T> &v) {
336 stringstream str;
337 //it's object:
338 if (v.get() != NULL) {
339 str << MedSerialize::object_json((const T&)*v);
340 }
341 else
342 str << "NULL";
343 return str.str();
344 }
345 template <class T> string object_json(unique_ptr<const T> &v) {
346 stringstream str;
347 //it's object:
348 if (v.get() != NULL) {
349 str << MedSerialize::object_json((const T&)*v);
350 }
351 else
352 str << "NULL";
353 return str.str();
354 }
355
356
357 //.........................................................................................
358 // string is special
359 //.........................................................................................
360 template<> inline size_t get_size<string>(string &str) {
361 size_t size = 0;
362 size += sizeof(size_t); // length of string
363 size += str.length() + 1;
364 return size;
365 }
366
367 //.........................................................................................
368 template<> inline size_t serialize<string>(unsigned char *blob, string &str)
369 {
370 size_t pos = 0;
371 size_t len = str.length();
372 //fprintf(stderr, "string serialize(%d) %s\n", len, str.c_str());
373 memcpy(blob, &len, sizeof(size_t)); pos += sizeof(size_t);
374 memcpy(blob + pos, str.c_str(), len); pos += len;
375 blob[pos] = 0; pos++;
376 //fprintf(stderr, "string serialize(%d) %s\n", len, &blob[sizeof(size_t)]);
377 return pos;
378 }
379
380 //.........................................................................................
381 template<> inline size_t deserialize<string>(unsigned char *blob, string &str)
382 {
383 //fprintf(stderr, "string deserialize\n");
384 size_t pos = 0;
385 size_t len;
386 memcpy(&len, blob, sizeof(size_t)); pos += sizeof(size_t);
387 //fprintf(stderr, "string deserialize pos %d len %d\n", pos, len);
388 string new_s((char *)&blob[pos]);
389 str = new_s;
390 //fprintf(stderr, "string deserialize pos %d :: %s\n", pos, str.c_str());
391 pos += len + 1;
392 return pos;
393 }
394
395 //.........................................................................................
396 // vector of type T that has a MedSerialize function
397 //.........................................................................................
398 template<class T> size_t get_size(vector<T> &v)
399 {
400 //cout << "inside vector getsize with type " << typeid(T).name() << endl;
401 size_t size = 0, len = v.size();
402 size += MedSerialize::get_size<size_t>(len);
403 for (T &elem : v)
404 size += MedSerialize::get_size(elem);
405
406 return size;
407 }
408
409 //.........................................................................................
410 template <class T> size_t serialize(unsigned char *blob, vector<T> &v)
411 {
412 //fprintf(stderr, "vector serialize\n");
413 //cout << "inside vector serialize with type " << typeid(T).name() << endl;
414 size_t pos = 0, len = v.size();
415 pos += MedSerialize::serialize<size_t>(blob + pos, len);
416 if (len > 0)
417 for (T &elem : v)
418 pos += MedSerialize::serialize(blob + pos, elem);
419 return pos;
420 }
421
422 //.........................................................................................
423 template <class T> size_t deserialize(unsigned char *blob, vector<T> &v)
424 {
425 //fprintf(stderr, "vector deserialize\n");
426 //cout << "inside vector deserialize with type " << typeid(T).name() << endl;
427 size_t pos = 0, len;
428 pos += MedSerialize::deserialize<size_t>(blob + pos, len);
429 if (len != v.size()) v.clear();
430 if (len > 0) {
431 v.resize(len);
432 for (T &elem : v)
433 pos += MedSerialize::deserialize(blob + pos, elem);
434 }
435 return pos;
436 }
437
438 template <class T> string object_json(const vector<const T> &v) {
439 stringstream str;
440 //it's object:
441 str << "[";
442 for (size_t i = 0; i < v.size(); ++i)
443 {
444 if (i > 0)
445 str << ",";
446 str << MedSerialize::object_json(v[i]);
447 }
448 str << "]";
449 return str.str();
450 }
451 template <class T> string object_json(const vector<T> &v) {
452 stringstream str;
453 //it's object:
454 str << "[";
455 for (size_t i = 0; i < v.size(); ++i)
456 {
457 if (i > 0)
458 str << ",";
459 str << MedSerialize::object_json(v[i]);
460 }
461 str << "]";
462 return str.str();
463 }
464 template <class T> string object_json(vector<const T> &v) {
465 stringstream str;
466 //it's object:
467 str << "[";
468 for (size_t i = 0; i < v.size(); ++i)
469 {
470 if (i > 0)
471 str << ",";
472 str << MedSerialize::object_json(v[i]);
473 }
474 str << "]";
475 return str.str();
476 }
477
478
479 //.........................................................................................
480 // set<T> with a MedSerialize function
481 //.........................................................................................
482 template <class T> size_t get_size(set<T> &v)
483 {
484 size_t size = 0, len = v.size();
485 size += MedSerialize::get_size<size_t>(len);
486
487 for (typename set<T>::iterator it = v.begin(); it != v.end(); ++it)
488 size += MedSerialize::get_size(*it);
489
490 return size;
491 }
492
493 //.........................................................................................
494 template <class T> size_t serialize(unsigned char *blob, set<T> &v)
495 {
496 //fprintf(stderr, "map serialize\n");
497 size_t pos = 0, len = v.size();
498 pos += MedSerialize::serialize<size_t>(blob + pos, len);
499
500 if (len > 0) {
501 for (typename set<T>::iterator it = v.begin(); it != v.end(); ++it)
502 pos += MedSerialize::serialize(blob + pos, (T &)(*it));
503 }
504
505 return pos;
506 }
507
508 //.........................................................................................
509 template <class T> size_t deserialize(unsigned char *blob, set<T> &v)
510 {
511 size_t pos = 0, len;
512 pos += MedSerialize::deserialize<size_t>(blob + pos, len);
513 v.clear();
514 T elem;
515 if (len > 0) {
516 for (int i = 0; i < len; i++) {
517 pos += MedSerialize::deserialize(blob + pos, elem);
518 v.insert(elem);
519 }
520 }
521 return pos;
522 }
523
524 template <class T> string object_json(set<const T> &v) {
525 stringstream str;
526 //it's object:
527 str << "[";
528 bool start = true;
529 for (typename set<T>::iterator it = v.begin(); it != v.end(); ++it)
530 {
531 if (!start)
532 str << ",";
533 str << MedSerialize::object_json((const T &)(*it));
534 start = false;
535 }
536 str << "]";
537 return str.str();
538 }
539 template <class T> string object_json(const set<const T> &v) {
540 stringstream str;
541 //it's object:
542 str << "[";
543 bool start = true;
544 for (typename set<T>::iterator it = v.begin(); it != v.end(); ++it)
545 {
546 if (!start)
547 str << ",";
548 str << MedSerialize::object_json((const T &)(*it));
549 start = false;
550 }
551 str << "]";
552 return str.str();
553 }
554 template <class T> string object_json(const set<T> &v) {
555 stringstream str;
556 //it's object:
557 str << "[";
558 bool start = true;
559 for (typename set<T>::iterator it = v.begin(); it != v.end(); ++it)
560 {
561 if (!start)
562 str << ",";
563 str << MedSerialize::object_json((T &)(*it));
564 start = false;
565 }
566 str << "]";
567 return str.str();
568 }
569
570
571 //.........................................................................................
572 // unordered_set<T> with a MedSerialize function
573 //.........................................................................................
574 template <class T> size_t get_size(unordered_set<T> &v)
575 {
576 size_t size = 0, len = v.size();
577 size += MedSerialize::get_size<size_t>(len);
578 for (T elem : v)
579 size += MedSerialize::get_size(elem);
580
581 return size;
582 }
583
584 //.........................................................................................
585 template <class T> size_t serialize(unsigned char *blob, unordered_set<T> &v)
586 {
587 //fprintf(stderr, "map serialize\n");
588 size_t pos = 0, len = v.size();
589 pos += MedSerialize::serialize<size_t>(blob + pos, len);
590 if (len > 0)
591 for (T elem : v) {
592 pos += MedSerialize::serialize(blob + pos, elem);
593 }
594 return pos;
595 }
596
597 //.........................................................................................
598 template <class T> size_t deserialize(unsigned char *blob, unordered_set<T> &v)
599 {
600 size_t pos = 0, len;
601 pos += MedSerialize::deserialize<size_t>(blob + pos, len);
602 v.clear();
603 T elem;
604 if (len > 0) {
605 for (int i = 0; i < len; i++) {
606 pos += MedSerialize::deserialize(blob + pos, elem);
607 v.insert(elem);
608 }
609 }
610 return pos;
611 }
612
613 template <class T> string object_json(unordered_set<const T> &v) {
614 stringstream str;
615 //it's object:
616 str << "[";
617 bool start = true;
618 for (const T &e : v)
619 {
620 if (!start)
621 str << ",";
622 str << MedSerialize::object_json(e);
623 start = false;
624 }
625 str << "]";
626 return str.str();
627 }
628 template <class T> string object_json(const unordered_set<const T> &v) {
629 stringstream str;
630 //it's object:
631 str << "[";
632 bool start = true;
633 for (const T &e : v)
634 {
635 if (!start)
636 str << ",";
637 str << MedSerialize::object_json(e);
638 start = false;
639 }
640 str << "]";
641 return str.str();
642 }
643 template <class T> string object_json(const unordered_set<T> &v) {
644 stringstream str;
645 //it's object:
646 str << "[";
647 bool start = true;
648 for (const T &e : v)
649 {
650 if (!start)
651 str << ",";
652 str << MedSerialize::object_json(e);
653 start = false;
654 }
655 str << "]";
656 return str.str();
657 }
658
659
660
661 //.........................................................................................
662 // pair<T,S> both with a MedSerialize function
663 //.........................................................................................
664 template <class T, class S> size_t get_size(pair<T, S> &v)
665 {
666 size_t size = 0;
667 T *t = (T *)&v.first;
668 S *s = (S *)&v.second;
669 size += MedSerialize::get_size((*t));
670 size += MedSerialize::get_size((*s));
671
672 return size;
673 }
674
675 //.........................................................................................
676 template <class T, class S> size_t serialize(unsigned char *blob, pair<T, S> &v)
677 {
678 //fprintf(stderr, "map serialize\n");
679 size_t pos = 0;
680 T *t = (T *)&v.first;
681 S *s = (S *)&v.second;
682 pos += MedSerialize::serialize(blob + pos, (*t));
683 pos += MedSerialize::serialize(blob + pos, (*s));
684
685 return pos;
686 }
687
688 //.........................................................................................
689 template <class T, class S> size_t deserialize(unsigned char *blob, pair<T, S> &v)
690 {
691 //fprintf(stderr, "map deserialize\n");
692 size_t pos = 0;
693 T t;
694 S s;
695 pos += MedSerialize::deserialize(blob + pos, t);
696 pos += MedSerialize::deserialize(blob + pos, s);
697 v.first = t;
698 v.second = s;
699
700 return pos;
701 }
702
703 template <class T, class S> string object_json(const pair<const T, const S> &v) {
704 stringstream str;
705 //it's object: - TODO: print type name
706 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
707 str << "[";
708
709 str << MedSerialize::object_json(v.first);
710 str << "," << MedSerialize::object_json(v.second);
711
712 str << "]}";
713 return str.str();
714 }
715 template <class T, class S> string object_json(pair<const T, const S> &v) {
716 stringstream str;
717 //it's object: - TODO: print type name
718 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
719 str << "[";
720
721 str << MedSerialize::object_json(v.first);
722 str << "," << MedSerialize::object_json(v.second);
723
724 str << "]}";
725 return str.str();
726 }
727 template <class T, class S> string object_json(const pair<T, S> &v) {
728 stringstream str;
729 //it's object: - TODO: print type name
730 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
731 str << "[";
732
733 str << MedSerialize::object_json(v.first);
734 str << "," << MedSerialize::object_json(v.second);
735
736 str << "]}";
737 return str.str();
738 }
739
740 //.........................................................................................
741 // map<T,S> both with a MedSerialize function
742 //.........................................................................................
743 template <class T, class S> size_t get_size(map<T, S> &v)
744 {
745 size_t size = 0, len = v.size();
746 size += MedSerialize::get_size<size_t>(len);
747 for (auto &elem : v) {
748 T *t = (T *)&elem.first;
749 S *s = (S *)&elem.second;
750 size += MedSerialize::get_size((*t));
751 size += MedSerialize::get_size((*s));
752 }
753 return size;
754 }
755
756 //.........................................................................................
757 template <class T, class S> size_t serialize(unsigned char *blob, map<T, S> &v)
758 {
759 //fprintf(stderr, "map serialize\n");
760 size_t pos = 0, len = v.size();
761 pos += MedSerialize::serialize<size_t>(blob + pos, len);
762 if (len > 0)
763 for (auto &elem : v) {
764 T *t = (T *)&elem.first;
765 S *s = (S *)&elem.second;
766 pos += MedSerialize::serialize(blob + pos, (*t));
767 pos += MedSerialize::serialize(blob + pos, (*s));
768 }
769 return pos;
770 }
771
772 //.........................................................................................
773 template <class T, class S> size_t deserialize(unsigned char *blob, map<T, S> &v)
774 {
775 //fprintf(stderr, "map deserialize\n");
776 size_t pos = 0, len;
777 pos += MedSerialize::deserialize(blob + pos, len);
778 v.clear();
779 T t;
780 S s;
781 if (len > 0) {
782 for (int i = 0; i < len; i++) {
783 pos += MedSerialize::deserialize(blob + pos, t);
784 pos += MedSerialize::deserialize(blob + pos, s);
785 v[t] = s;
786 }
787 }
788 return pos;
789 }
790
791 template <class T, class S> string object_json(map<const T, const S> &v) {
792 stringstream str;
793 //it's object:
794 str << "[";
795 bool start = true;
796 for (auto it = v.begin(); it != v.end(); ++it)
797 {
798 if (!start)
799 str << ",";
800 //print pair:
801
802 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
803 str << "[";
804
805 str << MedSerialize::object_json((const T&)it->first);
806 str << "," << MedSerialize::object_json((const S &)it->second);
807
808 str << "]}";
809 start = false;
810
811 }
812 str << "]";
813 return str.str();
814 }
815 template <class T, class S> string object_json(const map<const T, const S> &v) {
816 stringstream str;
817 //it's object:
818 str << "[";
819 bool start = true;
820 for (auto it = v.begin(); it != v.end(); ++it)
821 {
822 if (!start)
823 str << ",";
824 //print pair:
825
826 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
827 str << "[";
828
829 str << MedSerialize::object_json((const T&)it->first);
830 str << "," << MedSerialize::object_json((const S &)it->second);
831
832 str << "]}";
833 start = false;
834
835 }
836 str << "]";
837 return str.str();
838 }
839 template <class T, class S> string object_json(const map<T, S> &v) {
840 stringstream str;
841 //it's object:
842 str << "[";
843 bool start = true;
844 for (auto it = v.begin(); it != v.end(); ++it)
845 {
846 if (!start)
847 str << ",";
848 //print pair:
849
850 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
851 str << "[";
852
853 str << MedSerialize::object_json((T&)it->first);
854 str << "," << MedSerialize::object_json((S &)it->second);
855
856 str << "]}";
857 start = false;
858
859 }
860 str << "]";
861 return str.str();
862 }
863
864
865 //.........................................................................................
866 // unordered_map<T,S> both with a MedSerialize function
867 //.........................................................................................
868 template <class T, class S> size_t get_size(unordered_map<T, S> &v)
869 {
870 size_t size = 0, len = v.size();
871 size += MedSerialize::get_size<size_t>(len);
872
873 for (typename unordered_map<T, S>::iterator it = v.begin(); it != v.end(); ++it) {
874 size += MedSerialize::get_size((T &)(it->first));
875 size += MedSerialize::get_size((S &)(it->second));
876 }
877
878 return size;
879 }
880
881 //.........................................................................................
882 template <class T, class S> size_t serialize(unsigned char *blob, unordered_map<T, S> &v)
883 {
884 size_t pos = 0, len = v.size();
885 pos += MedSerialize::serialize<size_t>(blob + pos, len);
886
887 if (len > 0) {
888 for (typename unordered_map<T, S>::iterator it = v.begin(); it != v.end(); ++it) {
889 pos += MedSerialize::serialize(blob + pos, (T &)(it->first));
890 pos += MedSerialize::serialize(blob + pos, (S &)(it->second));
891 }
892 }
893 return pos;
894 }
895
896 //.........................................................................................
897 template <class T, class S> size_t deserialize(unsigned char *blob, unordered_map<T, S> &v)
898 {
899 size_t pos = 0, len;
900 pos += MedSerialize::deserialize(blob + pos, len);
901 v.clear();
902 T t;
903 S s;
904 if (len > 0) {
905 for (int i = 0; i < len; i++) {
906 pos += MedSerialize::deserialize(blob + pos, t);
907 pos += MedSerialize::deserialize(blob + pos, s);
908 v[t] = s;
909 }
910 }
911 return pos;
912 }
913
914 template <class T, class S> string object_json(unordered_map<const T, const S> &v) {
915 stringstream str;
916 //it's object:
917 str << "[";
918 bool start = true;
919 for (auto it = v.begin(); it != v.end(); ++it)
920 {
921 if (!start)
922 str << ",";
923 //print pair:
924
925 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
926 str << "[";
927
928 str << MedSerialize::object_json((const T &)it->first);
929 str << "," << MedSerialize::object_json((const S &)it->second);
930
931 str << "]}";
932 start = false;
933
934 }
935 str << "]";
936 return str.str();
937 }
938 template <class T, class S> string object_json(const unordered_map<const T, const S> &v) {
939 stringstream str;
940 //it's object:
941 str << "[";
942 bool start = true;
943 for (auto it = v.begin(); it != v.end(); ++it)
944 {
945 if (!start)
946 str << ",";
947 //print pair:
948
949 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
950 str << "[";
951
952 str << MedSerialize::object_json((const T &)it->first);
953 str << "," << MedSerialize::object_json((const S &)it->second);
954
955 str << "]}";
956 start = false;
957
958 }
959 str << "]";
960 return str.str();
961 }
962 template <class T, class S> string object_json(const unordered_map<T, S> &v) {
963 stringstream str;
964 //it's object:
965 str << "[";
966 bool start = true;
967 for (auto it = v.begin(); it != v.end(); ++it)
968 {
969 if (!start)
970 str << ",";
971 //print pair:
972
973 str << "{ \"Object\":\"pair<" << typeid(T).name() << ", " << typeid(S).name() << ">\", ";
974 str << "[";
975
976 str << MedSerialize::object_json((T &)it->first);
977 str << "," << MedSerialize::object_json((S &)it->second);
978
979 str << "]}";
980 start = false;
981
982 }
983 str << "]";
984 return str.str();
985 }
986
987
988 //.........................................................................................
989 // Variadic Wrappers to call several elements is a single line
990 //.........................................................................................
991 template <class T, class... Ts> size_t get_size(T& elem, Ts&... args)
992 {
993 size_t size = 0;
994
995 size += MedSerialize::get_size(elem);
996 size += MedSerialize::get_size(args...);
997
998 return size;
999
1000 }
1001
1002 //.........................................................................................
1003 template <class T, class... Ts> size_t serialize(unsigned char *blob, T& elem, Ts&... args)
1004 {
1005 size_t pos = 0;
1006
1007 pos += MedSerialize::serialize(blob, elem);
1008 pos += MedSerialize::serialize(blob + pos, args...);
1009
1010 return pos;
1011
1012 }
1013
1014 //.........................................................................................
1015 template <typename T, typename... Ts> size_t deserialize(unsigned char *blob, T& elem, Ts&... args)
1016 {
1017 size_t pos = 0;
1018
1019 pos += MedSerialize::deserialize(blob, elem);
1020 pos += MedSerialize::deserialize(blob + pos, args...);
1021
1022 return pos;
1023
1024 }
1025
1026 template <class T, class... Ts> string object_json(T& elem, Ts&... args) {
1027 stringstream str;
1028 //it's object:
1029 str << MedSerialize::object_json(elem);
1030 str << "," << MedSerialize::object_json(args...);
1031
1032 return str.str();
1033 }
1034
1035
1036 //====================================================================================================
1037 // Next is the implementation of the serialization/deserialization process
1038 //====================================================================================================
1039 // last stage serializer : the last element : size, name, serialization
1040 template<class T> size_t serializer(unsigned char *blob, int counter, vector<string> &names, T &elem)
1041 {
1042 //SRL_LOG("last_serializaer: blob %x counter %d name %s\n", blob, counter, names[counter].c_str());
1043
1044 // keep size_t place for size
1045 size_t pos = 0;
1046 pos += MedSerialize::serialize(blob + pos, pos);
1047
1048 //SRL_LOG("last_serializer(1) : blob %x size %d name %s\n", blob, pos, names[counter].c_str());
1049 // serialize string : the name of the variable
1050 pos += MedSerialize::serialize(blob + pos, names[counter]);
1051
1052 //SRL_LOG("last_serializer(2) : blob %x size %d name %s\n", blob, pos, names[counter].c_str());
1053 // serialize elem
1054 pos += MedSerialize::serialize(blob + pos, elem);
1055
1056 //SRL_LOG("last_serializer(3) : blob %x size %d name %s\n", blob, pos, names[counter].c_str());
1057
1058 // going back to 0 and writing the size
1059 MedSerialize::serialize(blob, pos);
1060
1061 // return serialized size
1062 return pos;
1063 }
1064
1065
1066 // mid level serializer : looping through the elements to serialize
1067 template<class T, class... Ts> size_t serializer(unsigned char *blob, int counter, vector<string> &names, T &elem, Ts&...args)
1068 {
1069 //SRL_LOG("mid_serializer: name %d is %s\n", counter, names[counter].c_str());
1070
1071 size_t pos = 0;
1072 // serialize elem
1073 pos += MedSerialize::serializer(blob, counter, names, elem);
1074
1075 //SRL_LOG("mid(1) name %s blob %x pos %d\n", names[counter].c_str(), blob, pos);
1076
1077 // recursive call to the next elements
1078 pos += MedSerialize::serializer(blob + pos, counter + 1, names, args...);
1079
1080 //SRL_LOG("mid(2) name %s blob %x pos %d\n", names[counter].c_str(), blob, pos);
1081
1082 // return serialized size
1083 return pos;
1084 }
1085
1086 template<typename T, enable_if_t<std::is_base_of<SerializableObject, T>::value, int> = 0> string get_name() {
1087 unique_ptr<T> cl = unique_ptr<T>(new T); //Not using object
1088 string cl_name = cl->my_class_name();
1089
1090 return cl_name;
1091 }
1092
1093 template<typename T, enable_if_t<!std::is_base_of<SerializableObject, T>::value, int> = 0> string get_name() {
1094 string cl_name = "primitive_type";
1095
1096 return cl_name;
1097 }
1098
1099 // last stage deserializer : the last element : size, name, serialization
1100 template<class T> size_t deserializer(unsigned char *blob, int counter, vector<string> &names, map <string, size_t> &name2pos, T &elem)
1101 {
1102 string name = names[counter];
1103 //cerr << "last_deserializer: name " << counter << " is " << name << "\n";
1104
1105 size_t pos = 0;
1106 // deserialize only if appears in map, otherwise warn
1107 if (name2pos.find(name) != name2pos.end()) {
1108 //cerr << "last_deserializer: name " << name << " name2pos " << name2pos[name] << "\n";
1109 pos += MedSerialize::deserialize(blob + name2pos[name], elem);
1110 //unsigned char *p = blob + name2pos[name];
1111 //SRL_LOG("=====> size is %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]);
1112 }
1113 else {
1114 string cl_name = get_name<T>();
1115 cerr << "WARNING: In \"" << cl_name << "\" element " << name << " not serialized... will be deserialized to its default\n";
1116 }
1117
1118 return pos;
1119 }
1120
1121
1122 // mid level deserializer : looping through the elements to serialize
1123 template<class T, class... Ts> size_t deserializer(unsigned char *blob, int counter, vector<string> &names, map<string, size_t> &name2pos, T &elem, Ts&...args)
1124 {
1125 string name = names[counter];
1126 //cerr << "mid_deserializer: name " << counter << " is " << name << "\n";
1127
1128 size_t pos = 0;
1129
1130 // deserialize elem , note we don't use blob+pos , this is due to the usage of name2pos to get exact positions
1131 pos += MedSerialize::deserializer(blob, counter, names, name2pos, elem);
1132
1133 // recursive call to the next elements
1134 pos += MedSerialize::deserializer(blob, counter + 1, names, name2pos, args...);
1135
1136 // return serialized size
1137 return pos;
1138 }
1139
1140
1141 // last stage get_sizer : the last element : size, name, serialization
1142 template<class T> size_t get_sizer(int counter, vector<string> &names, T &elem)
1143 {
1144 string name = names[counter];
1145 //cerr << "last_serializer: name " << counter << " is " << name << "\n";
1146
1147 size_t size = 0;
1148
1149 size += MedSerialize::get_size(size); // account for size at start
1150 size += MedSerialize::get_size(name); // account for string name
1151 size += MedSerialize::get_size(elem); // account for actual element serialization
1152
1153 return size;
1154 }
1155
1156
1157 // mid level get_sizer : looping through the elements to serialize
1158 template<class T, class... Ts> size_t get_sizer(int counter, vector<string> &names, T &elem, Ts&...args)
1159 {
1160 string name = names[counter];
1161 //cerr << "mid_get_sizer: name " << counter << " is " << name << "\n";
1162
1163 size_t size = 0;
1164
1165 // deserialize elem
1166 size += MedSerialize::get_sizer(counter, names, elem);
1167
1168 // recursive call to the next elements
1169 size += MedSerialize::get_sizer(counter + 1, names, args...);
1170
1171 return size;
1172 }
1173
1174
1175 // get_size before serialization , for top levels
1176 template<class... Ts> size_t get_size_top(char *list_of_args, Ts&...args) {
1177
1178 //cerr << "get_size_top\n";
1179 size_t size = 0;
1180
1181 // get names
1182 vector<string> names;
1183 MedSerialize::get_list_names(list_of_args, names);
1184
1185 size += MedSerialize::get_size(size); // count for the serialization size kept at the beginning
1186 size += MedSerialize::get_sizer(0, names, args...);
1187
1188 //cerr << "get_size_top returned size is " << size << "\n";
1189 return size;
1190 }
1191
1192 // preparing for serializer chain of calls: getting names out of the args list.
1193 // adding and filling in the total size at start (will be needed in deserialize_top)
1194 template<class... Ts> size_t serialize_top(unsigned char *blob, char *list_of_args, Ts&...args) {
1195
1196 //cerr << "serialize_top\n";
1197
1198 // get names
1199 vector<string> names;
1200 MedSerialize::get_list_names(list_of_args, names);
1201
1202 // save place for size
1203 size_t pos = 0;
1204 pos += MedSerialize::serialize(blob + pos, pos);
1205
1206 // serialize (recursively)
1207 pos += MedSerialize::serializer(blob + pos, 0, names, args...);
1208
1209 // write back the size at pos 0
1210 //cerr << "stop: writing pos " << pos << " at start\n";
1211 MedSerialize::serialize(blob, pos);
1212
1213 // return the size
1214 return pos;
1215 }
1216
1217 // preparing for deserializer: (1) get names (2) prepare a map of the names + positions inside blob at this level
1218 template<class... Ts> size_t deserialize_top(unsigned char *blob, char *list_of_args, Ts&...args) {
1219
1220 //SRL_LOG("deserialize_top\n");
1221
1222 // get names
1223 vector<string> names;
1224 MedSerialize::get_list_names(list_of_args, names);
1225
1226 // get total size
1227 size_t tot_size = 0, pos = 0;
1228 pos += MedSerialize::deserialize(blob, tot_size);
1229 //SRL_LOG("dtop(1) pos %d tot_size %d\n", pos, tot_size);
1230
1231 // prepare the map
1232 map<string, size_t> name2pos;
1233 while (pos < tot_size) {
1234
1235 // read curr_size
1236 size_t curr_size;
1237 size_t orig_curr_pos = pos;
1238 //SRL_LOG("dtop(2) pos %d\n", pos);
1239 pos += MedSerialize::deserialize(blob + pos, curr_size);
1240
1241 // read name
1242 string name;
1243 //SRL_LOG("dtop(3) pos %d curr_size %d\n", pos, curr_size);
1244 pos += MedSerialize::deserialize(blob + pos, name);
1245
1246 // add to map
1247 //SRL_LOG("dtop(4) pos %d curr_size %d name %s\n", pos, curr_size, name.c_str());
1248 name2pos[name] = pos;
1249
1250 // advance pos to next element
1251 pos = orig_curr_pos + curr_size;
1252 //cerr << "dtop(5) orig_pos " << orig_curr_pos << " pos " << pos << " curr_size " << curr_size << "\n";
1253
1254 }
1255
1256#if 0
1257 for (auto &e : name2pos)
1258 SRL_LOG("dtop(5.5) name2pos [ %s ] = %d\n", e.first.c_str(), e.second);
1259#endif
1260 // ready for deserializer (note that all name2pos addresses are relative to the original blob)
1261 MedSerialize::deserializer(blob, 0, names, name2pos, args...);
1262
1263 // return size of deserialized area (taking it from tot_size (!) , and not from the actual deserialized part,
1264 // in case there were elements in the blob that were not asked for.)
1265
1266 //cerr << "dtop(6) tot_size " << tot_size << "\n";
1267 return tot_size;
1268 }
1269
1270 template<class T> string object_json_rec(int counter, vector<string> &names, T &elem) {
1271 stringstream str;
1272 //need to print only names[counter] elemet. the value is stored in elem
1273
1274 str << "\n\t\"" << names[counter] << "\": ";
1275 str << MedSerialize::object_json(elem);
1276
1277 return str.str();
1278 }
1279
1280 template<class T, class... Ts> string object_json_rec(int counter, vector<string> &names, T &elem, Ts&...args) {
1281 stringstream str;
1282
1283 //print current and get next:
1284 str << MedSerialize::object_json_rec(counter, names, elem);
1285
1286 if (counter + 1 < names.size())
1287 str << ",";
1288
1289 str << MedSerialize::object_json_rec(counter + 1, names, args...);
1290
1291 return str.str();
1292 }
1293
1294 template<class... Ts> string object_json_start(const string &cls_name, int vers, char *list_of_args, Ts&...args) {
1295 vector<string> names;
1296 MedSerialize::get_list_names(list_of_args, names);
1297
1298 stringstream str;
1299 //str << "{\n\t\"Object\":\"" << cls_name << "\",";
1300 str << "{\n\t\"Object\":\"" << cls_name << "\",\n\t\"Version\":" << vers << ",";
1301
1302 /*str << "{";
1303 for (int i = 0; i < names.size(); ++i) {
1304 if (i > 0)
1305 str << ",";
1306 str << "\n\t\"" << names[i] << "\":\"NOT_IMPLEMENTED\"";
1307 }
1308 str << "}";*/
1309
1310 string res = MedSerialize::object_json_rec(0, names, args...);
1311 str << res << "\n}";
1312
1313 return str.str();
1314 }
1315
1316 //primitive types
1317 template<> inline string object_json<const int>(const int &v) { return to_string(v); }
1318 template<> inline string object_json<const unsigned int>(const unsigned int &v) { return to_string(v); }
1319 template<> inline string object_json<const float>(const float &v) { return to_string(v); }
1320 template<> inline string object_json<const double>(const double &v) { return to_string(v); }
1321 template<> inline string object_json<const char>(const char &v) { return to_string(v); }
1322 template<> inline string object_json<const unsigned char>(const unsigned char &v) { return to_string(v); }
1323 template<> inline string object_json<const long>(const long &v) { return to_string(v); }
1324 template<> inline string object_json<const long long>(const long long &v) { return to_string(v); }
1325 template<> inline string object_json<const unsigned long long>(const unsigned long long &v) { return to_string(v); }
1326 template<> inline string object_json<const bool>(const bool &v) { return to_string(v); }
1327 template<> inline string object_json<int>(int &v) { return to_string(v); }
1328 template<> inline string object_json<unsigned int>(unsigned int &v) { return to_string(v); }
1329 template<> inline string object_json<float>(float &v) { return to_string(v); }
1330 template<> inline string object_json<double>(double &v) { return to_string(v); }
1331 template<> inline string object_json<char>(char &v) { return to_string(v); }
1332 template<> inline string object_json<unsigned char>(unsigned char &v) { return to_string(v); }
1333 template<> inline string object_json<long>(long &v) { return to_string(v); }
1334 template<> inline string object_json<long long>(long long &v) { return to_string(v); }
1335 template<> inline string object_json<unsigned long long>(unsigned long long &v) { return to_string(v); }
1336 template<> inline string object_json<bool>(bool &v) { return to_string(v); }
1337 template<> inline string object_json<string>(string &str) { return "\"" + str + "\""; }
1338 template<> inline string object_json<const string>(const string &str) { return "\"" + str + "\""; }
1339 inline string object_json(int v) { return to_string(v); }
1340 inline string object_json(unsigned int v) { return to_string(v); }
1341 inline string object_json(float v) { return to_string(v); }
1342 inline string object_json(double v) { return to_string(v); }
1343 inline string object_json(char v) { return to_string(v); }
1344 inline string object_json(unsigned char v) { return to_string(v); }
1345 inline string object_json(long v) { return to_string(v); }
1346 inline string object_json(long long v) { return to_string(v); }
1347 inline string object_json(unsigned long long v) { return to_string(v); }
1348 inline string object_json(bool v) { return to_string(v); }
1349
1350
1351}
1352
1353void mes_trim(string &s);
1354
1355// A few IO helpers copied here in order to make SerializableObject a PURE h file implementation
1356namespace MedSerialize {
1357
1358 inline int read_binary_data_alloc(const string &fname, unsigned char *&data, unsigned long long &size)
1359 {
1360 ifstream inf;
1361
1362 inf.open(fname, ios::in | ios::binary | ios::ate);
1363
1364 if (!inf) {
1365 SRL_ERR("read_binary_data_alloc(): can't open file %s for read\n", fname.c_str());
1366 return -1;
1367 }
1368
1369 size = inf.tellg();
1370 data = new unsigned char[size];
1371 inf.seekg(0, ios::beg);
1372 inf.read((char *)data, size);
1373
1374 boost::crc_32_type checksum_agent;
1375 checksum_agent.process_bytes(data, size);
1376 SRL_LOG("read_binary_data_alloc [%s] with crc32 [%zu]\n", fname.c_str(), checksum_agent.checksum());
1377
1378 inf.close();
1379 return 0;
1380 }
1381
1382 //-----------------------------------------------------------------------------
1383 inline int write_binary_data(const string &fname, unsigned char *data, unsigned long long size)
1384 {
1385 ofstream of;
1386
1387 //MLOG("Writing file %s :: size %lld\n", fname.c_str(), size);
1388 of.open(fname, ios::out | ios::binary);
1389
1390 if (!of) {
1391 SRL_ERR("write_binary_data(): can't open file %s for write\n", fname.c_str());
1392 return -1;
1393 }
1394
1395 of.write((char *)data, size);
1396
1397 of.close();
1398
1399 return 0;
1400 }
1401
1402 // Initialization Utility
1403 static int initialization_text_to_map(const string& text, map<string, string>& init_map) {
1404
1405 if (text == "")
1406 return 0;
1407
1408 //MLOG("INPUT TEXT: %s\n", text.c_str());
1409 // dealing with {}
1410 // whenever there's a v={S} where S is any string (that may also include {}) we want the map to put S for v ...
1411 // follows is (hence) an ugly code to parse that
1412 // but this adds the ability to pass parameters for an embedded element within our current (say a model that holds parameters for other models)
1413 //
1414
1415 vector<size_t> start_pos;
1416 vector<size_t> end_pos;
1417 vector<pair<size_t, size_t>> from_to;
1418
1419 // find all positions of "={"
1420 size_t pos = text.find("={", 0);
1421 while (pos != string::npos) {
1422 start_pos.push_back(pos);
1423 pos = text.find("={", pos + 1);
1424 }
1425
1426 // find all positions of "}"
1427 pos = text.find("}", 0);
1428 while (pos != string::npos) {
1429 end_pos.push_back(pos);
1430 pos = text.find("}", pos + 1);
1431 }
1432
1433 // treating nesting
1434 if (start_pos.size() > 0 && end_pos.size() > 0) {
1435
1436 int i = 0, j = 0, stack = 0, stack_first = -1, stack_last = -1;
1437
1438 while (j < end_pos.size()) {
1439 if (i < (int)start_pos.size() && start_pos[i] < end_pos[j]) {
1440 if (stack_first < 0) stack_first = (int)start_pos[i];
1441 stack++;
1442 i++;
1443 }
1444 else {
1445 if (stack == 0) {
1446 SRL_ERR("ERROR: Unmatched {} in string %s\n", text.c_str());
1447 return -1;
1448 }
1449 stack--;
1450 if (stack == 0) stack_last = (int)end_pos[j];
1451 j++;
1452 }
1453
1454 if (stack == 0) {
1455 from_to.push_back(pair<size_t, size_t>(stack_first, stack_last));
1456 stack_first = -1;
1457 }
1458 }
1459
1460 for (auto &ft : from_to) {
1461 SRL_LOG_D("found substring: %d-%d : %s\n", ft.first, ft.second, text.substr(ft.first, ft.second - ft.first + 1).c_str());
1462 }
1463
1464 }
1465
1466
1467 // replacing {} areas with other strings to allow for correct parsing, and then returning them
1468 string new_text = "";
1469 map<string, string> replacers;
1470 if (from_to.size() == 0) new_text = text;
1471 else {
1472 new_text = text.substr(0, from_to[0].first + 1); // up to the first '='
1473 int j;
1474 for (j = 0; j < from_to.size(); j++) {
1475 string name = "REPLACE_ME_LATER_NUMBER_" + to_string(j);
1476 string replacer = text.substr(from_to[j].first + 2, from_to[j].second - from_to[j].first - 2);
1477 SRL_LOG_D("replacer %d : %s -> %s\n", j, name.c_str(), replacer.c_str());
1478 new_text += name;
1479 replacers[name] = replacer;
1480 if (j < from_to.size() - 1)
1481 new_text += text.substr(from_to[j].second + 1, from_to[j + 1].first - from_to[j].second);
1482 }
1483 new_text += text.substr(from_to[j - 1].second + 1, text.length() - from_to[j - 1].second);
1484 SRL_LOG_D("new_text is %s\n", new_text.c_str());
1485
1486 }
1487
1488 // TBD
1489
1490
1491 // get "Name = value" fields
1492 vector<string> fields;
1493 boost::split(fields, new_text, boost::is_any_of(";"));
1494
1495 // get name + value
1496 vector<string> sub_fields;
1497
1498 for (string& field : fields) {
1499 if (field.size() == 0)
1500 continue;
1501
1502 boost::split(sub_fields, field, boost::is_any_of("="));
1503 if (sub_fields.size() != 2) {
1504 SRL_ERR("Cannot parse \'%s\' from \'%s\'\n", field.c_str(), text.c_str());
1505 return -1;
1506 }
1507 mes_trim(sub_fields[0]);
1508 mes_trim(sub_fields[1]);
1509 init_map[sub_fields[0]] = sub_fields[1];
1510 }
1511
1512 for (auto &el : init_map) {
1513 if (el.second.compare(0, 24, "REPLACE_ME_LATER_NUMBER_") == 0) {
1514 init_map[el.first] = replacers[el.second];
1515 }
1516 }
1517
1518 return 0;
1519 }
1520 //..............................................................................
1521 static int init_map_from_string(string text, map<string, string>& init_map) {
1522
1523 if (text == "") return 0;
1524
1525 // parse text of the format "Name = Value ; Name = Value ; ..."
1526
1527 // remove white spaces
1528 text.erase(remove_if(text.begin(), text.end(), ::isspace), text.end());
1529
1530 if (MedSerialize::initialization_text_to_map(text, init_map) == -1)
1531 return -1;
1532
1533 // for (auto rec : init_map)
1534 // MLOG("Initializing with \'%s\' = \'%s\'\n", rec.first.c_str(), rec.second.c_str());
1535
1536
1537 return 0;
1538 }
1539
1540 static int read_file_into_string(const string &fname, string &data)
1541 {
1542 ifstream inf(fname);
1543 if (!inf) {
1544 SRL_ERR("MedSerialize::read_file_into_string: Can't open file %s\n", fname.c_str());
1545 return -1;
1546 }
1547
1548 data = "";
1549 string curr_line;
1550 while (getline(inf, curr_line)) {
1551 if ((curr_line.size() > 1) && (curr_line[0] != '#')) { // ignore empty lines, ignore comment lines
1552
1553 // get rid of leading spaces, trailing spaced, and shrink inner spaces to a single one, get rid of tabs and end of line (win or linux)
1554 string fixed_spaces = std::regex_replace(curr_line, std::regex("^ +| +$|( ) +|\r|\n|\t+"), string("$1"));
1555 data += fixed_spaces;
1556 }
1557 }
1558
1559 return 0;
1560 }
1561
1562
1563 // similar in concept to read_file_into_string, but gets the strings in the file and adds a comma "," between them
1564 static int read_list_into_string(const string &fname, string &data)
1565 {
1566 ifstream inf(fname);
1567 if (!inf) {
1568 SRL_ERR("MedSerialize::read_file_into_string: Can't open file %s\n", fname.c_str());
1569 return -1;
1570 }
1571
1572 data = "";
1573 string curr_line;
1574 while (getline(inf, curr_line)) {
1575 //SRL_LOG("read_list: curr_line: %s\n", curr_line.c_str());
1576 if ((curr_line.size() > 1) && (curr_line[0] != '#')) { // ignore empty lines, ignore comment lines
1577 // move all tabs to spaces
1578 string fixed_spaces = std::regex_replace(fixed_spaces, std::regex("\t+"), " ");
1579
1580 // get rid of leading spaced, ending spaces, \r
1581 fixed_spaces = std::regex_replace(curr_line, std::regex("^ +| +$|\r|\n"), "");
1582
1583 fixed_spaces += "\n"; // re-adding eol, in case it was missing
1584
1585 // change all internal spaces and \n to comma
1586 fixed_spaces = std::regex_replace(fixed_spaces, std::regex(" +|\n"), ",");
1587
1588 // make sure there are no adjacent commas
1589 fixed_spaces = std::regex_replace(fixed_spaces, std::regex(",,+"), ",");
1590
1591 // add
1592 data += fixed_spaces;
1593 //SRL_LOG("read_list: data: %s\n", data.c_str());
1594 }
1595 }
1596 // could happen that last char is comma, we fix it.
1597 if (data.back() == ',') data.pop_back();
1598
1599 return 0;
1600 }
1601}
1602
1603
1604#endif
c_str(string)
Definition basic.py:110