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