1 /* _________________________________________________________________________
2 *
3 * UTILIB: A utility library for developing portable C++ codes.
4 * Copyright (c) 2008 Sandia Corporation.
5 * This software is distributed under the BSD License.
6 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7 * the U.S. Government retains certain rights in this software.
8 * For more information, see the README file in the top UTILIB directory.
9 * _________________________________________________________________________
10 */
11
12 /**
13 * \file Serialize.cpp
14 */
15
16 #include <utilib/Serialize.h>
17 #include <utilib/exception_mngr.h>
18
19 using std::cerr;
20 using std::endl;
21
22 using std::map;
23 using std::pair;
24 using std::vector;
25 using std::string;
26 using std::type_info;
27
28
29 namespace utilib {
30
31 namespace { // local namespace for endian detection
32
33 const char template_separator = ';';
34
35 const int int_bytes = (( 0 << ( 8 * (3 % sizeof(int))) ) +
36 ( 1 << ( 8 * (2 % sizeof(int))) ) +
37 ( 2 << ( 8 * (1 % sizeof(int))) ) +
38 ( 3 << ( 8 * (0 % sizeof(int))) ));
39
40 } // namespace utilib::(local)
41
42 /** Detect the endian-ness of this platform.
43 *
44 * This code should be safe for compilers with both 2-byte and 4-byte
45 * ints. Common values are:
46 * - e4 (11 10 01 00) = 4-byte little-endian (Intel)
47 * - 1b (00 01 10 11) = 4-byte big-endian
48 * - 22 (00 10 00 10) = 2-byte little endian
49 * - 88 (10 00 10 00) = 2-byte big endian
50 */
51 const unsigned char Serialization_Manager::Endian =
52 (( (3 & reinterpret_cast<const char*>(&int_bytes)[0 % sizeof(int)]) << 6 ) +
53 ( (3 & reinterpret_cast<const char*>(&int_bytes)[1 % sizeof(int)]) << 4 ) +
54 ( (3 & reinterpret_cast<const char*>(&int_bytes)[2 % sizeof(int)]) << 2 ) +
55 ( (3 & reinterpret_cast<const char*>(&int_bytes)[3 % sizeof(int)]) ));
56
57
58 /// local namespace for default POD serialization functions
59 namespace POD_serializers {
60
61 template<typename T>
POD_serializer(SerialPOD & serial,Any & data,bool serialize)62 int POD_serializer(SerialPOD& serial, Any& data, bool serialize)
63 {
64 if ( serialize )
65 serial.set(&data.template expose<T>(), sizeof(T));
66 else
67 {
68 if ( serial.size() != sizeof(T) )
69 EXCEPTION_MNGR(serializer_bad_pod_size, "POD_serializer(): "
70 "SerialPOD data size does not match destination type");
71
72 memcpy( &const_cast<T&>(data.template expose<T>()),
73 serial.data(), serial.size() );
74 }
75 return 0;
76 }
77
78 template<>
POD_serializer(SerialPOD & serial,Any & data,bool serialize)79 int POD_serializer<std::string>(SerialPOD& serial, Any& data, bool serialize)
80 {
81 const std::string &str = data.expose<std::string>();
82 if ( serialize )
83 serial.set(str.c_str(), str.size());
84 else
85 data.set(std::string(serial.data(), serial.size()));
86 return 0;
87 }
88
89
90 template<typename T>
POD_text_serializer(std::string & serial,Any & data,bool serialize)91 int POD_text_serializer(std::string& serial, Any& data, bool serialize)
92 {
93 std::stringstream s;
94 if ( serialize )
95 {
96 s << data.template expose<T>();
97 serial = s.str();
98 }
99 else
100 {
101 s.str(serial);
102 s >> const_cast<T&>(data.template expose<T>()) >> std::ws;
103 }
104
105 if ( s.bad() || s.fail() )
106 return error::Serialization::BadPODTextConversion;
107 else if ( ! serialize )
108 return s.eof() ? 0 : error::Serialization::UnconvertedPODText;
109 else
110 return 0;
111 }
112
113 template<>
POD_text_serializer(std::string & serial,Any & data,bool serialize)114 int POD_text_serializer<float>(std::string& serial, Any& data, bool serialize)
115 {
116 std::stringstream s;
117 if ( serialize )
118 {
119 s.setf(std::ios::floatfield);
120 s.precision(FLT_DIG+2);
121 s << data.expose<float>();
122 serial = s.str();
123 }
124 else
125 {
126 s.str(serial);
127 s >> const_cast<float&>(data.expose<float>()) >> std::ws;
128 }
129
130 if ( s.bad() || s.fail() )
131 return error::Serialization::BadPODTextConversion;
132 else if ( ! serialize )
133 return s.eof() ? 0 : error::Serialization::UnconvertedPODText;
134 else
135 return 0;
136 }
137
138 template<>
POD_text_serializer(std::string & serial,Any & data,bool serialize)139 int POD_text_serializer<double>(std::string& serial, Any& data, bool serialize)
140 {
141 std::stringstream s;
142 if ( serialize )
143 {
144 s.setf(std::ios::floatfield);
145 s.precision(DBL_DIG+2);
146 s << data.expose<double>();
147 serial = s.str();
148 }
149 else
150 {
151 s.str(serial);
152 s >> const_cast<double&>(data.expose<double>()) >> std::ws;
153 }
154
155 if ( s.bad() || s.fail() )
156 return error::Serialization::BadPODTextConversion;
157 else if ( ! serialize )
158 return s.eof() ? 0 : error::Serialization::UnconvertedPODText;
159 else
160 return 0;
161 }
162
163 template<>
POD_text_serializer(std::string & serial,Any & data,bool serialize)164 int POD_text_serializer<long double>( std::string& serial, Any& data,
165 bool serialize )
166 {
167 std::stringstream s;
168 if ( serialize )
169 {
170 s.setf(std::ios::floatfield);
171 s.precision(LDBL_DIG+2);
172 s << data.expose<long double>();
173 serial = s.str();
174 }
175 else
176 {
177 s.str(serial);
178 s >> const_cast<long double&>(data.expose<long double>()) >> std::ws;
179 }
180
181 if ( s.bad() || s.fail() )
182 return error::Serialization::BadPODTextConversion;
183 else if ( ! serialize )
184 return s.eof() ? 0 : error::Serialization::UnconvertedPODText;
185 else
186 return 0;
187 }
188
189 template<>
POD_text_serializer(std::string & serial,Any & data,bool serialize)190 int POD_text_serializer<std::string>( std::string& serial, Any& data,
191 bool serialize )
192 {
193 if ( serialize )
194 serial = "\"" + data.expose<std::string>() + "\"";
195 else
196 {
197 string::iterator it = serial.begin();
198 string::iterator itEnd = serial.end();
199 // test for empty string or no leading "
200 if (( it == itEnd ) || ( *it != '"' ))
201 return error::Serialization::MissingStringQuote;
202 ++it;
203
204 // test for string.size() == 1
205 if ( it == itEnd )
206 return error::Serialization::MissingStringQuote;
207 --itEnd;
208 if ( *itEnd != '"' )
209 return error::Serialization::MissingStringQuote;
210
211 data.set(std::string(it, itEnd));
212 }
213 return 0;
214 }
215
216 template<>
POD_text_serializer(std::string & serial,Any & data,bool serialize)217 int POD_text_serializer<char>( std::string& serial, Any& data,
218 bool serialize )
219 {
220 std::stringstream s;
221 if ( serialize )
222 {
223 char c = data.expose<char>();
224 if ( c >= 32 && c <= 126 )
225 {
226 serial = "\'x\'";
227 serial[1] = c;
228 }
229 else
230 {
231 s << static_cast<int>(c);
232 serial = s.str();
233 }
234 }
235 else
236 {
237 if ( serial.empty() )
238 return error::Serialization::BadPODData;
239 if ( serial[0] == '\'' )
240 {
241 if ( serial.size() != 3 || serial[2] != '\'' )
242 return error::Serialization::BadPODData;
243 data.set<char>(serial[1]);
244 }
245 else
246 {
247 s.str(serial);
248 int i = CHAR_MAX + 1;
249 s >> i;
250 if (( i < CHAR_MIN ) || ( i > CHAR_MAX ))
251 return error::Serialization::BadPODTextConversion;
252 const_cast<char&>(data.expose<char>()) = static_cast<char>(i);
253 }
254 s >> std::ws;
255 }
256
257 if ( s.bad() || s.fail() )
258 return error::Serialization::BadPODTextConversion;
259 else if ( ! serialize )
260 return s.eof() ? 0 : error::Serialization::UnconvertedPODText;
261 else
262 return 0;
263 }
264
265 #ifndef QUOTE
266 # define QUOTE(x) _QUOTE(x)
267 # define _QUOTE(x) #x
268 #endif
269
270 #define REGISTER_POD(TYPE) \
271 register_serializer<TYPE >( QUOTE(TYPE), \
272 POD_serializers::POD_serializer<TYPE >, \
273 POD_serializers::POD_text_serializer<TYPE > )
274
275
276 } // namespace utilib::POD_serializers
277
278
279 //--------------------------------------------------------------------
280 // Serializer singleton management
281 //
Serializer()282 Serialization_Manager& Serializer()
283 {
284 static Serialization_Manager master_serializer;
285 return master_serializer;
286 }
287
288
289 //--------------------------------------------------------------------
290 // SerialPOD members
291 //
set(const void * buffer_src,const size_t length)292 void SerialPOD::set(const void* buffer_src, const size_t length)
293 {
294 buffer.resize(length);
295 memcpy(&buffer[0], buffer_src, length);
296 text_mode = false;
297 }
298
set(const std::string & buffer_src)299 void SerialPOD::set(const std::string& buffer_src)
300 {
301 size_t size = buffer_src.size();
302 buffer.resize(size);
303 memcpy(&buffer[0], buffer_src.c_str(), size);
304 text_mode = true;
305 }
306
print(std::ostream & os,std::string indent) const307 void SerialPOD::print(std::ostream& os, std::string indent) const
308 {
309 if ( text_mode )
310 os << ": ";
311 else
312 os << endl << indent << "POD: " << size() << ":";
313 for(size_t i = 0; i < size(); ++i)
314 if ( text_mode )
315 os << buffer[i];
316 else
317 os << " " << static_cast<int>(static_cast<unsigned char>(buffer[i]));
318 os << endl;
319 }
320
321
322 //--------------------------------------------------------------------
323 // SerialObject members
324 //
print(std::ostream & os,std::string indent) const325 void SerialObject::print(std::ostream& os, std::string indent) const
326 {
327 os << indent << "type = " << Serializer().get_username(type);
328 if ( data.is_type(typeid(SerialObject::elementList_t)) )
329 {
330 os << endl;
331 SerialObject::elementList_t::const_iterator it =
332 data.expose<SerialObject::elementList_t>().begin();
333 SerialObject::elementList_t::const_iterator itEnd =
334 data.expose<SerialObject::elementList_t>().end();
335 for ( ; it != itEnd; ++it )
336 it->print(os, indent + " ");
337 }
338 else if ( data.is_type(typeid(SerialPOD)) )
339 data.expose<SerialPOD>().print(os, indent + " ");
340 else
341 os << endl << indent << " UNKNOWN DATA! ("
342 << demangledName(data.type()) << ")" << endl;
343 }
344
345
346 //--------------------------------------------------------------------
347 // utilib namespace functions
348 //
349
serial_transform(SerialObject::elementList_t & serial,Any & data,bool serialize)350 int serial_transform(SerialObject::elementList_t& serial,
351 Any& data, bool serialize)
352 {
353 AnyFixedRef tmp = data;
354 int ans = Serializer().transform_impl
355 (data.empty() ? typeid(void) : data.type(), serial, tmp, serialize);
356 if ( data.empty() || tmp.empty() )
357 data = tmp;
358 return ans;
359 }
360
Deserialize(SerialObject & serial)361 Any Deserialize(SerialObject &serial)
362 {
363 SerialObject::elementList_t tmp(1, serial);
364 AnyFixedRef data;
365 int ans = Serializer().transform_impl(typeid(void), tmp, data, false);
366 if ( ans != 0 )
367 {
368 EXCEPTION_MNGR(serialization_error,
369 "Serialization_Manager::Deserialize()"
370 ": Deserialization failed for '"
371 << data.type().name() << "' (Error " << ans << ")");
372 }
373 return data;
374 }
375
376 //--------------------------------------------------------------------
377 // Serialization_Manager members
378 //
379
Serialization_Manager()380 Serialization_Manager::Serialization_Manager()
381 : typename_map(),
382 username_map(),
383 type_map(),
384 functions(),
385 rebuild_usernames(true),
386 serialize_pod_as_text(false)
387 {
388 // Reserve some space for the standard transformations
389 functions.reserve(19);
390
391 // NB: this must be first (so that void gets id 0)
392 register_serializer(typeid(void), "void", 0, NULL, NULL, NULL, NULL);
393
394 // Several of these registrations may be duplicates - BUT, since it's
395 // all in the same cpp file, the duplicates should be silently
396 // ignored.
397
398 // NB: according to the C++ standard, the signedness of char is
399 // implementation-specific. As a result, char, signed char, and
400 // unsigned char are distinct types. This means that the 'signed
401 // char' registration is explicitly required (or else signed chars
402 // will be silently cast into ints!)
403 REGISTER_POD(char);
404 REGISTER_POD(signed char);
405 REGISTER_POD(unsigned char);
406
407 REGISTER_POD(short);
408 REGISTER_POD(signed short);
409 REGISTER_POD(unsigned short);
410
411 REGISTER_POD(int);
412 REGISTER_POD(signed int);
413 REGISTER_POD(unsigned int);
414
415 REGISTER_POD(long);
416 REGISTER_POD(signed long);
417 REGISTER_POD(unsigned long);
418
419 REGISTER_POD(float);
420 REGISTER_POD(double);
421 REGISTER_POD(long double);
422
423 REGISTER_POD(bool);
424
425 // manually register wchar_t so the text string transform defaults to binary
426 register_serializer<wchar_t>
427 ( "wchar_t", POD_serializers::POD_serializer<wchar_t> );
428 // manually register strings so the name isn't "std::basic_string<*,*>"
429 register_serializer<std::string>
430 ( "std::string",
431 POD_serializers::POD_serializer<std::string>,
432 POD_serializers::POD_text_serializer<std::string>, -1 );
433 }
434
435
~Serialization_Manager()436 Serialization_Manager::~Serialization_Manager()
437 {}
438
439
440 const std::type_info*
get_typeinfo(size_t key)441 Serialization_Manager::get_typeinfo(size_t key)
442 {
443 if ( key >= functions.size() )
444 return NULL;
445 else
446 return functions[key].typeinfo;
447 }
448
449
450 std::string
get_username(size_t key)451 Serialization_Manager::get_username(size_t key)
452 {
453 if ( key >= functions.size() )
454 return "";
455 else
456 {
457 if ( rebuild_usernames )
458 rebuild_user_name_map();
459 username_map_t::iterator it = functions[key].username;
460 return ( it == username_map.end() ? "" : it->first );
461 }
462 }
463
464
465 bool
is_pod(size_t key)466 Serialization_Manager::is_pod(size_t key)
467 {
468 if ( key >= functions.size() )
469 return false;
470 else
471 return functions[key].pod_transform != NULL;
472 }
473
474
475 int
get_pod_length(size_t key)476 Serialization_Manager::get_pod_length(size_t key)
477 {
478 if ( key >= functions.size() )
479 return -1;
480 else
481 return functions[key].pod_size;
482 }
483
484
485 size_t
get_keyid(std::string user_name)486 Serialization_Manager::get_keyid(std::string user_name)
487 {
488 if ( rebuild_usernames )
489 rebuild_user_name_map();
490
491 username_map_t::iterator u_it = username_map.find(user_name);
492 if ( u_it == username_map.end() )
493 EXCEPTION_MNGR(serializer_unknown_type,
494 "Serialization_Manager::get_keyid(): "
495 "unknown user-defined type name, \""
496 << user_name << "\"");
497 if ( u_it->second == typename_map.end() )
498 EXCEPTION_MNGR(serializer_unknown_type,
499 "Serialization_Manager::get_keyid(): "
500 "user-defined type name, \""
501 << user_name << "\" maps to multiple types");
502
503 return u_it->second->second;
504 }
505
506 size_t
get_keyid(const std::type_info & type)507 Serialization_Manager::get_keyid(const std::type_info &type)
508 {
509 type_map_t::iterator t_it = type_map.find(&type);
510 if ( t_it == type_map.end() )
511 {
512 typename_map_t::iterator n_it = typename_map.find(mangledName(type));
513 if ( n_it == typename_map.end() )
514 EXCEPTION_MNGR(serializer_unknown_type,
515 "Serialization_Manager::get_keyid(): "
516 "unknown type_info name, \""
517 << type.name() << "\"");
518 return n_it->second;
519 }
520
521 return t_it->second;
522 }
523
524
525 int
transform_impl(const std::type_info & type,SerialObject::elementList_t & serial,AnyFixedRef & data,bool serialize)526 Serialization_Manager::transform_impl( const std::type_info& type,
527 SerialObject::elementList_t& serial,
528 AnyFixedRef& data,
529 bool serialize )
530 {
531 if ( rebuild_usernames )
532 rebuild_user_name_map();
533
534 type_map_t::iterator it = type_map.end();
535
536 if ( serialize )
537 {
538 if ( data.empty() )
539 {
540 // Serialize empty Anys as VOID
541 serial.push_back(SerialObject());
542 return 0;
543 }
544
545 // find this data type...
546 it = type_map.find(&type);
547 if ( it == type_map.end() )
548 {
549 // check to see if the mangled typename exists...
550 typename_map_t::iterator name_it
551 = typename_map.find(mangledName(type));
552 if ( name_it == typename_map.end() )
553 EXCEPTION_MNGR(serializer_unknown_type,
554 "Serialization_Manager::transform_impl(): "
555 "cannot serialize unknown type '"
556 << type.name() << "'");
557
558 // insert reference to this typeid for future use
559 it = type_map.insert(type_pair_t(&type,name_it->second)).first;
560 }
561
562 MappingFunctions &fcns = functions[it->second];
563
564 // Check for a username conflict
565 if ( fcns.username == username_map.end() )
566 EXCEPTION_MNGR(serialization_error,
567 "Serialization_Manager::transform_impl(): attempt "
568 "to serialize an object with a nonunique username.");
569
570 // Prep the serialization container.
571 serial.push_back(SerialObject(it->second));
572
573 int ans = 0;
574 // serialize the object
575 if ( fcns.transform != NULL )
576 ans = fcns.transform
577 ( serial.back().data.set<SerialObject::elementList_t>(),
578 data, serialize );
579 else if ( fcns.pod_transform != NULL )
580 {
581 if (( serialize_pod_as_text ) && ( fcns.pod_txt_xform != NULL ))
582 {
583 string buf;
584 ans = fcns.pod_txt_xform( buf, data, serialize );
585 serial.back().data.set<SerialPOD>().set(buf);
586 }
587 else
588 ans = fcns.pod_transform
589 ( serial.back().data.set<SerialPOD>(), data, serialize );
590 }
591 else
592 EXCEPTION_MNGR(serialization_error,
593 "Serialization_Manager::transform_impl(): "
594 "NULL serialization function for type '"
595 << type.name() << "'");
596 return ans;
597 }
598 else
599 {
600 if ( serial.empty() )
601 EXCEPTION_MNGR(serialization_error,
602 "Serialization_Manager::transform_impl(): "
603 "SerialObject missing required element.");
604
605 SerialObject& so = serial.front();
606 if (so.type == 0 )
607 {
608 // Deserialize VOID
609 data.clear();
610 return 0;
611 }
612 if ( so.type >= functions.size() )
613 EXCEPTION_MNGR(serializer_unknown_type,
614 "Serialization_Manager::transform_impl(): "
615 "SerialObject contains unknown type id.");
616
617 MappingFunctions &fcns = functions[so.type];
618 // Check for a username conflict
619 if ( fcns.username == username_map.end() )
620 EXCEPTION_MNGR(serialization_error,
621 "Serialization_Manager::transform_impl(): attempt "
622 "to deserialize an object with a nonunique username.");
623
624 // Initialize the result data
625 if ( fcns.init == NULL )
626 EXCEPTION_MNGR(serialization_error,
627 "Serialization_Manager::transform_impl(): "
628 "NULL initialization function for id " << so.type);
629 fcns.init(data);
630 if ( data.empty() )
631 {
632 cerr << "WARNING: Serialization_Manager::transform_impl(): "
633 "initialization function for " << type.name()
634 << " resulted in an empty Any." << endl
635 << " This will likely cause random segmentation "
636 "faults." << endl;
637 }
638
639 // deserialize the object
640 int ans = 0;
641 if ( fcns.transform != NULL )
642 ans = fcns.transform
643 ( const_cast<SerialObject::elementList_t&>
644 (so.data.expose<SerialObject::elementList_t>()),
645 data, serialize );
646 else if ( fcns.pod_transform != NULL )
647 {
648 SerialPOD& pod = const_cast<SerialPOD&>(so.data.expose<SerialPOD>());
649 if ( pod.is_text_mode() )
650 {
651 string buf = string(pod.data(), pod.size());
652 assert(fcns.pod_txt_xform != NULL);
653 ans = fcns.pod_txt_xform( buf, data, serialize );
654 }
655 else
656 ans = fcns.pod_transform( pod, data, serialize );
657 }
658 else
659 EXCEPTION_MNGR(serialization_error,
660 "Serialization_Manager::transform_impl(): "
661 "NULL deserialization function for id " << so.type);
662
663 serial.pop_front();
664 return ans;
665 }
666
667 // Cannot get here...
668 }
669
670
671 void
list_serializers(std::ostream & os)672 Serialization_Manager::list_serializers(std::ostream& os)
673 {
674 if ( rebuild_usernames )
675 rebuild_user_name_map();
676
677 os << "Known serializers:" << endl;
678 username_map_t::iterator it = username_map.begin();
679 username_map_t::iterator itEnd = username_map.end();
680 size_t max = 0;
681 for ( ; it != itEnd; ++it )
682 max = ( max < it->first.size() ? it->first.size() : max );
683
684 for (it = username_map.begin() ; it != itEnd; ++it )
685 os << " " << std::left << std::setw(max) << it->first << " [ "
686 << ( it->second == typename_map.end()
687 ? "CONFLICT" : it->second->first )
688 << " ]" << endl;
689 }
690
691
692 int
register_serializer(const std::type_info & type,std::string name,int pod_size,transform_fcn t_fcn,pod_transform_fcn p_fcn,pod_text_transform_fcn pt_fcn,initialization_fcn i_fcn)693 Serialization_Manager::register_serializer( const std::type_info& type,
694 std::string name,
695 int pod_size,
696 transform_fcn t_fcn,
697 pod_transform_fcn p_fcn,
698 pod_text_transform_fcn pt_fcn,
699 initialization_fcn i_fcn)
700 {
701 pair<typename_map_t::iterator,bool> ans = typename_map.insert
702 (typename_pair_t(mangledName(type), functions.size()));
703 if ( ans.second )
704 {
705 // New registration
706 type_map[&type] = functions.size();
707
708 functions.push_back(MappingFunctions());
709 MappingFunctions &m = functions.back();
710 m.init = i_fcn;
711 m.transform = t_fcn;
712 m.pod_transform = p_fcn;
713 m.pod_txt_xform = pt_fcn;
714 m.typeinfo = &type;
715 m.raw_user_name = name;
716 m.pod_size = pod_size;
717 m.username = username_map.end();
718 rebuild_usernames = true;
719 return 0;
720 }
721 else
722 {
723 MappingFunctions &original = functions[ans.first->second];
724 // Should we just check the user-defined name?
725 if ( ( original.init == i_fcn ) &&
726 ( original.transform == t_fcn ) &&
727 ( original.pod_transform == p_fcn ) &&
728 ( original.pod_txt_xform == pt_fcn ))
729 {
730 // A duplicate registration pointing to the same functions...
731 return 0;
732 }
733 cerr << "WARNING: Serialization_Manager::register_serializer(): "
734 " discarding duplicate registration for '" << mangledName(type) <<
735 "'" << endl;
736 return error::Serialization::DuplicateRegistration;
737 }
738 }
739
740
741 void
rebuild_user_name_map()742 Serialization_Manager::rebuild_user_name_map()
743 {
744 // clear out everything
745 username_map.clear();
746 username_map_t::iterator noUserName = username_map.end();
747
748 vector<MappingFunctions>::iterator it = functions.begin();
749 vector<MappingFunctions>::iterator itEnd = functions.end();
750 for( ; it != itEnd; ++it )
751 it->username = noUserName;
752
753 // rebuild everything
754 typename_map_t::iterator t_it = typename_map.begin();
755 typename_map_t::iterator t_itEnd = typename_map.end();
756 for( ; t_it != t_itEnd; ++t_it )
757 resolve_user_name(t_it->first);
758
759 rebuild_usernames = false;
760 }
761
762
763 std::string
resolve_user_name(std::string mangled)764 Serialization_Manager::resolve_user_name(std::string mangled)
765 {
766 typename_map_t::iterator mangled_it = typename_map.find(mangled);
767 // unknown mangled type name...
768 if ( mangled_it == typename_map.end() )
769 return "*";
770
771 MappingFunctions &m = functions[mangled_it->second];
772
773 // this user name has already been fully resolved
774 if ( m.username != username_map.end() )
775 return m.username->first;
776
777 // we must resolve the name
778 string uname = "";
779 size_t sep = m.raw_user_name.find(template_separator);
780 uname = m.raw_user_name.substr(0, sep);
781 if ( sep != string::npos )
782 {
783 // This uname is a template (defined in terms of mangled type names)
784 uname += "<";
785 while ( sep != string::npos )
786 {
787 ++sep;
788 size_t next_sep = m.raw_user_name.find(template_separator, sep);
789 uname += resolve_user_name(m.raw_user_name.substr(sep,
790 next_sep-sep));
791 uname += ',';
792 sep = next_sep;
793 }
794 *uname.rbegin() = '>';
795 }
796
797 // insert the newly-resolved name...
798 pair<username_map_t::iterator, bool> ans
799 = username_map.insert(username_pair_t(uname, mangled_it));
800 if ( ans.second )
801 m.username = ans.first;
802 else
803 {
804 cerr << "WARNING: Serialization_Manager::resolve_user_name(): \n"
805 " Multiple mangled type names map to the same user-defined name. It is\n"
806 " likely that you forgot to register a name or a serialization function\n"
807 " for a template argument. If you attempt to serialize either type,\n"
808 " you will get an exception.\n"
809 " User name: " << uname << endl
810 << " Mangled: " << mangled << endl
811 << " " << username_map[uname]->first << endl;
812
813 m.username = username_map.end();
814 if ( ans.first->second != typename_map.end() )
815 {
816 functions[ans.first->second->second].username = username_map.end();
817 ans.first->second = typename_map.end();
818 }
819 }
820
821 return uname;
822 }
823
824
825 } // namespace utilib
826