export more serializer interface to allow for finer grain testing
[dyninst.git] / dynutil / h / Serialization.h
1
2 #if !defined (SERIALIZATION_PUBLIC_H)
3 #define SERIALIZATION_PUBLIC_H
4 //  Hopefully just a few definitions allowing for a public interface to 
5 //  serializing user-providede annotations
6
7 #include <stdio.h>
8 #include <assert.h>
9 #include <string.h>
10 #include <stdexcept>
11 #include <typeinfo>
12 #include <vector>
13 #include <map>
14 #include <assert.h>
15 #include "dyntypes.h"
16 #include "util.h"
17
18 namespace Dyninst {
19 //  SER_ERR("msg") -- an attempt at "graceful" failure.  If debug flag is set
20 //  it will assert, otherwise it throws...  leaving the "graceful" aspect
21 //  to the next (hopefully top-level) exception handler.
22
23 #define serialize_printf serializer_printf
24
25 COMMON_EXPORT int serializer_printf(const char *format, ...);
26
27
28 COMMON_EXPORT bool &serializer_debug_flag();
29
30 #define SER_ERR(cmsg) \
31    do { \
32       if (serializer_debug_flag()) { \
33          fprintf(stderr, "%s", cmsg); \
34          assert (0); \
35       } else { \
36          throw SerializerError(__FILE__, __LINE__, std::string(cmsg)); \
37       } \
38    } while (0)
39
40
41 class SerializerBase;
42
43
44 typedef enum {sd_serialize, sd_deserialize} iomode_t;
45 typedef bool (*deserialize_and_annotate_t)(SerializerBase *, void *parent);
46
47 bool addDeserializeFuncForType(deserialize_and_annotate_t, const std::type_info *);
48 deserialize_and_annotate_t getDeserializeFuncForType(const std::type_info *);
49
50 class SerializerError : public std::runtime_error {
51    //  SerializerError:  a small class that is thrown by serialization/deserialization
52    //  routines.  This exists as an attempt to standardize and simplify error handling
53    //  for ser-des routines that are possibly deeply nested.
54    //  Here's the rub:  we don't want stray, unhandled exceptions finding their way into
55    //  the larger system...  thus all entry points to serialization/deserialization need
56    //  to catch this exception to render it transparent to the rest of the system.
57
58    public:
59
60    typedef enum {
61       ser_err_unspecified,
62       ser_err_no_err,
63       ser_err_disabled
64    } SerializerErrorType;
65
66    private:
67
68    std::string file__;
69    int line__;
70    SerializerErrorType err__;
71
72    public:
73
74
75    COMMON_EXPORT SerializerError(const std::string &__file__, 
76          const int &__line__, 
77          const std::string &msg, 
78          SerializerErrorType __err__ = ser_err_unspecified) :
79       runtime_error(msg),
80       file__(__file__),
81       line__(__line__),
82       err__(__err__)
83    {}
84
85    COMMON_EXPORT virtual ~SerializerError() THROW {}
86
87    COMMON_EXPORT std::string file() const {return file__;}
88    COMMON_EXPORT int line() const {return line__;}
89    COMMON_EXPORT SerializerErrorType code() const {return err__;}
90 };
91
92
93 COMMON_EXPORT void printSerErr(const SerializerError &err);
94
95 class Serializable {
96    protected:
97       COMMON_EXPORT Serializable() {}
98       COMMON_EXPORT virtual ~Serializable() {}
99
100       COMMON_EXPORT virtual void serialize_impl(SerializerBase *,  const char * = NULL) THROW_SPEC(SerializerError) = 0;
101    public:
102       COMMON_EXPORT virtual void serialize(SerializerBase *,  const char * = NULL) THROW_SPEC(SerializerError);
103 };
104
105 class SerFile;
106 class SerDes;
107 #if 1
108 class SerializerBase {
109
110         public:
111                 //  TODO:  make these private or protected
112                 COMMON_EXPORT static dyn_hash_map<std::string, SerializerBase *> active_bin_serializers;
113                 static bool global_disable;
114         private:
115
116                 SerFile *sf;
117                 SerDes *sd;
118
119                 std::string serializer_name;
120
121                 typedef dyn_hash_map<std::string, SerializerBase *> subsystem_serializers_t;
122                 COMMON_EXPORT static dyn_hash_map<std::string, subsystem_serializers_t> all_serializers;
123
124         public:
125                 COMMON_EXPORT static void globalDisable()
126                 {
127                         global_disable = true;
128                 }
129                 COMMON_EXPORT static bool serializationDisabled()
130                 {
131                         return global_disable; 
132                 }
133
134                 COMMON_EXPORT static void globalEnable()
135                 {
136                         global_disable = false;
137                 }
138                 COMMON_EXPORT virtual bool isXML() = 0;
139                 COMMON_EXPORT virtual bool isBin ()= 0;
140                 COMMON_EXPORT bool isInput () {return iomode() == sd_deserialize;}
141                 COMMON_EXPORT bool isOutput () {return iomode() == sd_serialize;}
142
143                 COMMON_EXPORT static void dumpActiveBinSerializers();
144
145                 COMMON_EXPORT SerializerBase(const char *name_, std::string filename, 
146                                 iomode_t dir, bool verbose); 
147
148                 COMMON_EXPORT SerializerBase();
149
150                 COMMON_EXPORT virtual ~SerializerBase() 
151                 {
152                         serialize_printf("%s[%d]:  serializer %p-%sdtor\n", FILE__, __LINE__, 
153                                         this, serializer_name.c_str());
154                 }
155
156                 COMMON_EXPORT virtual SerDes &getSD()  { assert(sd); return *sd;}
157                 COMMON_EXPORT SerFile &getSF() {assert(sf); return *sf;}
158                 COMMON_EXPORT std::string &name() {return serializer_name;}
159                 COMMON_EXPORT static SerializerBase *getSerializer(std::string subsystem, std::string fname);
160                 COMMON_EXPORT static bool addSerializer(std::string subsystem, std::string fname, SerializerBase *sb);
161
162                 COMMON_EXPORT virtual void vector_start(unsigned int &, const char * = NULL);
163                 COMMON_EXPORT virtual void vector_end();
164                 COMMON_EXPORT virtual void hash_map_start(unsigned int &size, const char *tag = NULL); 
165                 COMMON_EXPORT virtual void hash_map_end();
166                 COMMON_EXPORT void translate_base(bool &v, const char *&t);
167                 COMMON_EXPORT void translate_base(short &v, const char *&t);
168                 COMMON_EXPORT void translate_base(char &v, const char *&t);
169                 COMMON_EXPORT void translate_base(int &v, const char *&t);
170                 COMMON_EXPORT void translate_base(unsigned int &v, const char *&t);
171                 COMMON_EXPORT void translate_base(unsigned long &v, const char *&t);
172                 COMMON_EXPORT void translate_base(long &v, const char *&t);
173                 COMMON_EXPORT void translate_base(float &v, const char *&t);
174                 COMMON_EXPORT void translate_base(double &v, const char *&t);
175                 COMMON_EXPORT void translate_base(const char * &v, int bufsize, const char *&t);
176                 COMMON_EXPORT void translate_base(char * &v, int bufsize, const char *&t);
177                 COMMON_EXPORT void translate_base(std::string &v, const char *t);
178
179                 COMMON_EXPORT virtual iomode_t iomode(); 
180
181 };
182
183 template <class T>
184 class ScopedSerializerBase : public SerializerBase
185 {
186         T *scope;
187         public:
188         ScopedSerializerBase(T *scope_, const char *name_, std::string filename, 
189                         iomode_t dir, bool verbose) :
190                 SerializerBase(name_, filename, dir, verbose), scope(scope_) {}
191         ScopedSerializerBase(T *scope_) :
192                 SerializerBase(), scope(scope_) {}
193         virtual ~ScopedSerializerBase() {}
194         T *getScope() {return scope;}
195 };
196
197 class SerDesXML;
198
199
200 bool start_xml_elem(SerDesXML &, const char *);
201 bool end_xml_elem(SerDesXML &);
202
203 template <class T>
204 class SerializerXML : public ScopedSerializerBase<T>
205 {
206         public:
207                 COMMON_EXPORT virtual bool isXML() {return true;}
208                 COMMON_EXPORT virtual bool isBin () {return false;}
209
210                 COMMON_EXPORT SerializerXML(T *t, const char *name_, std::string filename,
211                                 iomode_t dir, bool verbose) :
212                         ScopedSerializerBase<T>(t, name_, filename, dir, verbose) {}
213
214                 COMMON_EXPORT virtual ~SerializerXML() {}
215
216                 COMMON_EXPORT SerDesXML &getSD_xml()
217                 {
218                         SerializerBase *sb = this;
219                         SerDes &sd = sb->getSD();
220                         SerDesXML *sdxml = dynamic_cast<SerDesXML *> (&sd);
221                         assert(sdxml);
222                         return *sdxml;
223                 }
224
225                 COMMON_EXPORT static bool start_xml_element(SerializerBase *sb, const char *tag)
226                 {
227                         SerializerXML<T> *sxml = dynamic_cast<SerializerXML<T> *>(sb);
228
229                         if (!sxml)
230                         {
231                                 fprintf(stderr, "%s[%d]:  FIXME:  called xml function with non xml serializer\n",
232                                                 FILE__, __LINE__);
233                                 return false;
234                         }
235
236                         SerDesXML sdxml = sxml->getSD_xml();
237                         start_xml_elem(sdxml, tag);
238                         return true;
239                 }
240
241
242                 COMMON_EXPORT static bool end_xml_element(SerializerBase *sb, const char *)
243                 {
244                         SerializerXML<T> *sxml = dynamic_cast<SerializerXML<T> *>(sb);
245
246                         if (!sxml)
247                         {
248                                 fprintf(stderr, "%s[%d]:  FIXME:  called xml function with non xml serializer\n",
249                                                 FILE__, __LINE__);
250                                 return false;
251                         }
252
253                         SerDesXML sdxml = sxml->getSD_xml();
254                         end_xml_elem(sdxml);
255                         //end_xml_elem(sdxml.writer);
256
257                         return true;
258                 }
259 };
260
261 class SerDesBin;
262
263 template <class T>
264 class SerializerBin : public ScopedSerializerBase<T> {
265         friend class SerDesBin;
266
267         public:
268         virtual bool isXML() {return false;}
269         virtual bool isBin () {return true;}
270
271         SerializerBin(T *t)  :
272                 ScopedSerializerBase<T>(t) {}
273
274
275         SerializerBin(T *t, const char *name_, std::string filename,
276                         iomode_t dir, bool verbose) :
277                 ScopedSerializerBase<T>(t, name_, filename, dir, verbose)
278         {
279                 SerializerBase *sb = this;
280                 if (sb->serializationDisabled())
281                 {
282                         fprintf(stderr, "%s[%d]:  Failing to construct Bin Translator:  global disable set\n",
283                                         FILE__, __LINE__);
284
285                         throw SerializerError(FILE__, __LINE__,
286                                         std::string("serialization disabled"),
287                                         SerializerError::ser_err_disabled);
288                 }
289
290                 dyn_hash_map<std::string, SerializerBase *>::iterator iter;
291
292                 iter = sb->active_bin_serializers.find(std::string(name_));
293
294                 if (iter == sb->active_bin_serializers.end())
295                 {
296                         serialize_printf("%s[%d]:  Adding Active serializer for name %s\n",
297                                         FILE__, __LINE__, name_);
298
299                         sb->active_bin_serializers[std::string(name_)] = this;
300                 }
301                 else
302                 {
303                         fprintf(stderr, "%s[%d]:  Weird, already have active serializer for name %s\n",
304                                         FILE__, __LINE__, name_);
305                 }
306         }
307
308
309         virtual ~SerializerBin()
310         {
311                 serialize_printf("%s[%d]:  WELCOME TO SERIALIZER_BIN dtor\n", FILE__, __LINE__);
312                 dyn_hash_map<std::string, SerializerBase *>::iterator iter;
313
314                 SerializerBase *sb = this;
315                 iter = sb->active_bin_serializers.find(sb->name());
316
317                 if (iter == sb->active_bin_serializers.end())
318                 {
319                         fprintf(stderr, "%s[%d]:  Weird, no static ptr for name %s\n",
320                                         FILE__, __LINE__, sb->name().c_str());
321                 }
322                 else
323                 {
324                         serialize_printf("%s[%d]:  Removing active serializer for name %s\n",
325                                         FILE__, __LINE__, sb->name().c_str());
326                         sb->active_bin_serializers.erase(iter);
327                 }
328
329         }
330
331         SerDesBin &getSD_bin()
332         {
333                 SerializerBase *sb = this;
334                 SerDes &sd = sb->getSD();
335                 SerDesBin *sdbin = dynamic_cast<SerDesBin *> (&sd);
336                 assert(sdbin);
337                 return *sdbin;
338         }
339
340
341
342         static SerializerBin *findSerializerByName(const char *name_)
343         {
344                 dyn_hash_map<std::string, SerializerBase *>::iterator iter;
345
346                 iter = SerializerBase::active_bin_serializers.find(std::string(name_));
347
348                 if (iter == SerializerBase::active_bin_serializers.end())
349                 {
350                         fprintf(stderr, "%s[%d]:  No static ptr for name %s\n",
351                                         FILE__, __LINE__, name_);
352                         SerializerBase::dumpActiveBinSerializers();
353                 }
354                 else
355                 {
356                         fprintf(stderr, "%s[%d]:  Found active serializer for name %s\n",
357                                         FILE__, __LINE__, name_);
358
359                         return iter->second;
360                 }
361
362                 return NULL;
363         }
364
365
366 };
367
368
369
370
371
372
373 #endif
374
375         template <class S, class T>
376 void translate_vector(S *ser, std::vector<T> &vec,
377                 const char *tag = NULL, const char *elem_tag = NULL)
378 {
379         unsigned int nelem = vec.size();
380         ser->vector_start(nelem, tag);
381
382         if (ser->iomode() == sd_deserialize) 
383         {
384                 if (vec.size())
385                         SER_ERR("nonempty vector used to create");
386
387                 //  zero size vectors are allowed
388                 //  what it T is a complex type (with inheritance info)??
389                 //  does resize() call default ctors, or should we do that
390                 //  manually here? look this up.
391                 if (nelem)
392                         vec.resize(nelem);
393         }
394
395         for (unsigned int i = 0; i < vec.size(); ++i) 
396         {
397                 T &t = vec[i];
398                 gtranslate(ser, t, elem_tag);
399         }
400
401         ser->vector_end();
402 }
403
404
405         template <class S, class T>
406 void translate_vector(S *ser, std::vector<T *> &vec, 
407                 const char *tag = NULL, const char *elem_tag = NULL) 
408 {
409         unsigned int nelem = vec.size();
410         ser->vector_start(nelem, tag);
411
412         if (ser->iomode() == sd_deserialize) 
413         {
414                 if (vec.size()) 
415                         SER_ERR("nonempty vector used to create");
416
417                 //  zero size vectors are allowed
418                 if (nelem) 
419                 {
420                         //  block-allocate array of underlying type, then assign to our vector
421                         //  What happens if an individual elem is later deleted??
422                         T *chunk_alloc = new T[nelem];
423                         vec.resize(nelem);
424                         for (unsigned int i = 0; i < nelem; ++i)
425                                 vec[i] = &(chunk_alloc[i]);
426                 }
427         }
428
429         for (unsigned int i = 0; i < vec.size(); ++i) 
430         {
431                 T &t = *(vec[i]);
432                 gtranslate(ser, t, elem_tag);
433         }
434
435         ser->vector_end();
436 }
437
438         template <class S, class T>
439 void translate_vector(S *ser, std::vector<std::vector<T> > &vec, 
440                 const char *tag = NULL, const char *elem_tag = NULL) 
441 {
442    fprintf(stderr, "%s[%d]:  welcome to translate vector of vectors\n", 
443            __FILE__, __LINE__);
444
445    unsigned int nelem = vec.size();
446    ser->vector_start(nelem, tag);
447    if (ser->iomode() == sd_deserialize) 
448    {
449       if (vec.size())
450          SER_ERR("nonempty vector used to create");
451
452       //  zero size vectors are allowed
453       //  what it T is a complex type (with inheritance info)??
454       //  does resize() call default ctors, or should we do that
455       //  manually here? look this up.
456       if (nelem)
457          vec.resize(nelem);
458    }
459
460    for (unsigned int i = 0; i < vec.size(); ++i) 
461    {
462       std::vector<T> &tv = vec[i];
463       translate_vector(ser,tv, tag, elem_tag);
464    }
465
466    ser->vector_end();
467 }
468
469 template <class S, class K, class V>
470 void translate_pair(S *ser, std::pair<K, V> &p,
471                 const char *tag = NULL, const char *tag2 = NULL)
472 {
473         ser->pair_start();
474
475         gtranslate(ser, p.first, tag);
476         gtranslate(ser, p.second, tag2);
477
478         ser->pair_end();
479 }
480
481 template <class S, class K, class V>
482 void translate_map(S *ser, std::map<K, V> &map,
483                 const char *tag = NULL, const char *elem_tag = NULL)
484 {
485         unsigned int nelem = map.size();
486         ser->map_start(nelem, tag);
487
488         if (ser->iomode() == sd_deserialize)
489         {
490                 if (map.size())
491                         SER_ERR("nonempty vector used to create");
492
493                 typename std::map<K, V>::iterator lastentry = map.begin();
494                 //  cannot do any kind of bulk allocation with maps
495                 for (unsigned int i = 0; i < nelem; ++i)
496                 {
497                         K a_k;
498                         V a_v;
499                         gtranslate(ser, a_k, elem_tag);
500                         gtranslate(ser, a_v, elem_tag);
501                         map[a_k] = a_v;
502                 }
503
504         }
505         else
506         {
507                 assert (ser->iomode() == sd_serialize);
508                 typename std::map<K, V>::iterator iter = map.begin();
509                 while (iter != map.end())
510                 {
511                         K &a_k = const_cast<K &>(iter->first);
512                         V &a_v = const_cast<V &>(iter->second);
513                         gtranslate(ser, a_k, elem_tag);
514                         gtranslate(ser, a_v, elem_tag);
515                         iter++;
516                 }
517         }
518         ser->map_end();
519 }
520
521 template <class S, class K, class V>
522 void translate_multimap(S *ser, std::multimap<K, V> &map,
523                 const char *tag = NULL, const char *elem_tag = NULL)
524 {
525         unsigned int nelem = map.size();
526         ser->multimap_start(nelem, tag);
527
528         if (ser->iomode() == sd_deserialize)
529         {
530                 if (map.size())
531                         SER_ERR("nonempty vector used to create");
532
533                 typename std::multimap<K, V>::iterator lastentry = map.begin();
534                 //  cannot do any kind of bulk allocation with multimaps
535                 for (unsigned int i = 0; i < nelem; ++i)
536                 {
537                         typename std::multimap<K, V>::value_type mapentry;
538                         gtranslate(ser, mapentry, elem_tag);
539                         //  lastentry serves as a hint as to where the new value goes 
540                         //  (presumably near the last value inserted)
541                         //  not sure if this really makes things more efficient.
542                         lastentry = map.insert(lastentry, mapentry);
543                 }
544
545         }
546         else
547         {
548                 assert (ser->iomode() == sd_serialize);
549                 typename std::multimap<K, V>::iterator iter = map.begin();
550                 while (iter != map.end())
551                 {
552                         gtranslate(ser, *iter, elem_tag);
553                         iter++;
554                 }
555         }
556
557         ser->multimap_end();
558 }
559
560 template <class S, class K, class V>
561 void translate_hash_map(S *ser, dyn_hash_map<K, V> &hash, 
562                 const char *tag = NULL, const char *key_tag = NULL, const char *value_tag = NULL)
563 {   
564         fprintf(stderr, "%s[%d]:  welcome to translate_hash_map<%s, %s>()\n", 
565                         __FILE__, __LINE__,
566                         typeid(K).name(), typeid(V).name()); 
567
568         unsigned int nelem = hash.size();
569         ser->hash_map_start(nelem, tag);
570         fprintf(stderr, "%s[%d]:  after hash_map start, mode = %sserialize\n", 
571                         __FILE__, __LINE__, ser->iomode() == sd_serialize ? "" : "de"); 
572
573         if (ser->iomode() == sd_serialize) 
574    {
575       typename dyn_hash_map<K,V>::iterator iter = hash.begin();
576       fprintf(stderr, "%s[%d]:  about to serialize hash with %d elements\n", 
577               __FILE__, __LINE__, hash.size());
578
579       while (iter != hash.end()) 
580       {
581          K k = iter->first;
582          V v = iter->second;
583          ser->translate_base(k, key_tag);
584          ser->translate_base(v, value_tag);
585          iter++;           
586       }
587    }
588    else 
589    {
590       //  can we do some kind of preallocation here?
591       for (unsigned int i = 0; i < nelem; ++i) 
592       {
593          K k;
594          V v;
595          ser->translate_base(k, key_tag);
596          ser->translate_base(v, value_tag);
597          hash[k] = v;
598       }
599    }
600
601    ser->hash_map_end();
602 }
603
604 template <class S, class K, class V>
605 void translate_hash_map(S *ser, dyn_hash_map<K, V *> &hash,
606       const char *tag = NULL, const char *key_tag = NULL, const char *value_tag = NULL)
607 {
608    fprintf(stderr, "%s[%d]:  welcome to translate_hash_map<%s, %s*>()\n", 
609          __FILE__, __LINE__,
610          typeid(K).name(), typeid(V).name());
611
612    unsigned int nelem = hash.size();
613    ser->hash_map_start(nelem, tag);
614
615    fprintf(stderr, "%s[%d]:  after hash_map start, mode = %sserialize\n", 
616          __FILE__, __LINE__, ser->iomode() == sd_serialize ? "" : "de");
617
618    if (ser->iomode() == sd_serialize) 
619    {
620       typename dyn_hash_map<K,V *>::iterator iter = hash.begin();
621
622       while (iter != hash.end()) 
623       {
624          K k = iter->first;
625          V *v = iter->second;
626          ser->translate_base(k, key_tag);
627          ser->translate_base(*v, value_tag);
628          iter++;
629       }
630    }
631    else 
632    {
633       //  can we do some kind of preallocation here?
634       for (unsigned int i = 0; i < nelem; ++i) 
635       {
636          K k;
637          V *v = new V();
638          ser->translate_base(k, key_tag);
639          ser->translate_base(*v, value_tag);
640          hash[k] = v;
641       }
642    }
643    ser->hash_map_end();
644 }
645
646 template <class S, class K, class V>
647 void translate_hash_map(S *ser, dyn_hash_map<K, char *> &hash,
648       const char *tag = NULL, const char *key_tag = NULL, const char *value_tag = NULL)
649 {
650    //  THIS SPECIALIZATION DOES NOT WORK CORRECTLY (YET)
651    fprintf(stderr, "%s[%d]:  welcome to translate_hash_map<%s, %s*>()\n", 
652          __FILE__, __LINE__,
653          typeid(K).name(), typeid(V).name());
654
655    unsigned int nelem = hash.size();
656    ser->hash_map_start(nelem, tag);
657
658    fprintf(stderr, "%s[%d]:  after hash_map start, mode = %sserialize\n", 
659          __FILE__, __LINE__, ser->iomode() == sd_serialize ? "" : "de");
660
661    if (ser->iomode() == sd_serialize) 
662    {
663       typename dyn_hash_map<K,V *>::iterator iter = hash.begin();
664       
665       while (iter != hash.end()) 
666       {
667          K k = iter->first;
668          V v = iter->second;
669          ser->translate_base(k, key_tag);
670          ser->translate_base(v, value_tag);
671          iter++;
672       }
673    }
674    else 
675    {
676       //  can we do some kind of preallocation here?
677       for (unsigned int i = 0; i < nelem; ++i) 
678       {
679          K k;
680          V v;
681          ser->translate_base(k, key_tag);
682          ser->translate_base(*v, value_tag);
683          hash[k] = v;
684       }
685    }
686    ser->hash_map_end();
687 }
688
689
690 COMMON_EXPORT void trans_adapt(SerializerBase *ser, Serializable &it,  const char *tag);
691 COMMON_EXPORT void trans_adapt(SerializerBase *ser, Serializable *itp,  const char *tag);
692
693 COMMON_EXPORT void trans_adapt(SerializerBase *ser, bool &it,  const char *tag);
694 COMMON_EXPORT void trans_adapt(SerializerBase *ser, int &it,  const char *tag);
695 COMMON_EXPORT void trans_adapt(SerializerBase *ser, unsigned int &it,  const char *tag);
696 COMMON_EXPORT void trans_adapt(SerializerBase *ser, long &it,  const char *tag);
697 COMMON_EXPORT void trans_adapt(SerializerBase *ser, unsigned long &it,  const char *tag);
698 COMMON_EXPORT void trans_adapt(SerializerBase *ser, char &it,  const char *tag);
699 COMMON_EXPORT void trans_adapt(SerializerBase *ser, char *&it,  const char *tag);
700 COMMON_EXPORT void trans_adapt(SerializerBase *ser, std::string &it,  const char *tag);
701 COMMON_EXPORT void trans_adapt(SerializerBase *ser, float &it,  const char *tag);
702 COMMON_EXPORT void trans_adapt(SerializerBase *ser, double &it,  const char *tag);
703
704 COMMON_EXPORT bool isBinary(Dyninst::SerializerBase *ser);
705 COMMON_EXPORT bool isOutput(Dyninst::SerializerBase *ser);
706
707 typedef void NOTYPE_T;
708 template<class S, class T, class T2 = NOTYPE_T>
709 class trans_adaptor {
710    public:
711       trans_adaptor() 
712       {
713          //fprintf(stderr, "%s[%d]:  trans_adaptor  -- general\n", __FILE__, __LINE__);
714       } 
715
716       T * operator()(S *ser, T & it, const char *tag = NULL, const char * /*tag2*/ = NULL)
717       {
718          trans_adapt(ser, it, tag);
719          return &it;
720       }
721 };
722
723 template<class S, class T2>
724 class trans_adaptor<S, Serializable, T2> {
725    public:
726       trans_adaptor() 
727       {
728          serialize_printf("%s[%d]:  trans_adaptor  -- general\n", __FILE__, __LINE__);
729       } 
730
731       Serializable * operator()(S *ser, Serializable & it, const char *tag = NULL, 
732             const char * /*tag2*/ = NULL)
733       {
734          gtranslate(ser, it, tag);
735          return &it;
736       }
737 };
738
739 template<class S, class T, class TT2>
740 class trans_adaptor<S, std::vector<T>, TT2 > {
741    public:
742       trans_adaptor()
743       {
744          serialize_printf("%s[%d]:  trans_adaptor  -- vectorl\n", __FILE__, __LINE__);
745       }
746
747       std::vector<T> * operator()(S *ser, std::vector<T> &v, const char *tag = NULL, 
748             const char *tag2 = NULL) 
749       {
750          translate_vector(ser, v, tag, tag2);         //  maybe catch errors here?
751          return &v;
752       }
753 };
754
755 template<class S, class T, class TT2>
756 class trans_adaptor<S, std::vector<T *>, TT2>  {
757    public: 
758       trans_adaptor() 
759       {
760          serialize_printf("%s[%d]:  trans_adaptor  -- vector of ptrs\n", __FILE__, __LINE__);
761       }
762
763       std::vector<T*> * operator()(S *ser, std::vector<T *> &v, const char *tag = NULL, 
764             const char *tag2 = NULL) 
765       {
766          translate_vector(ser, v, tag, tag2);
767          //  maybe catch errors here?
768          return &v;
769       }
770 };
771
772 template<class S, class T, class TT2>
773 class trans_adaptor<S, std::map<T, TT2> >  {
774         public:
775                 trans_adaptor()
776                 {
777                         serialize_printf("%s[%d]:  trans_adaptor  -- std::map\n", __FILE__, __LINE__);
778                 }
779
780                 std::map<T, TT2> * operator()(S *ser, std::map<T, TT2> &v, const char *tag = NULL,
781                                 const char *tag2 = NULL)
782                 {
783                         translate_map(ser, v, tag, tag2);
784                         //  maybe catch errors here?
785                         return &v;
786                 }
787 };
788
789 template<class S, class T, class TT2>
790 class trans_adaptor<S, std::multimap<T, TT2>, TT2>  {
791         public:
792                 trans_adaptor()
793                 {
794                         serialize_printf("%s[%d]:  trans_adaptor  -- multimap<%s, %s>\n",
795                                         __FILE__, __LINE__, typeid(T).name(), typeid(TT2).name());
796                 }
797
798                 std::multimap<T, TT2> * operator()(S *ser, std::multimap<T, TT2> &m, const char *tag = NULL, 
799                                 const char *tag2 = NULL)
800                 {
801                         translate_multimap(ser, m, tag, tag2);
802                         //  maybe catch errors here?
803                         return &m;
804                 }
805 };
806
807 template<class S, class T, class TT2>
808 class trans_adaptor<S, std::pair<T, TT2> >  {
809         public:
810                 trans_adaptor()
811                 {
812                         serialize_printf("%s[%d]:  trans_adaptor  -- pair<%s, %s>\n",
813                                         __FILE__, __LINE__, typeid(T).name(), typeid(TT2).name());
814                 }
815
816                 std::pair<T, TT2> * operator()(S *ser, std::pair<T, TT2> &p, const char *tag = NULL,
817                                 const char *tag2 = NULL)
818                 {
819                         translate_pair(ser, p, tag, tag2);
820                         //  maybe catch errors here?
821                         return &p;
822                 }
823 };
824
825 #if 0
826 template<class T, class ANNO_NAME, bool, annotation_implementation_t>
827 class Annotatable<T, ANNO_NAME,bool, annotation_implementation_t>;
828 #endif
829
830 #if 0
831 I really really wish this worked, maybe it still can given some more pounding
832
833 template<class S, class T, class ANNO_NAME, bool SERIALIZABLE, annotation_implementation_t IMPL>
834 class trans_adaptor<S, 
835       Annotatable<T, 
836       ANNO_NAME, 
837       SERIALIZABLE,
838       IMPL> &>  {
839    public: 
840       trans_adaptor() 
841       {
842          fprintf(stderr, "%s[%d]:  trans_adaptor  -- annotatable<%s, %s, %s>\n", 
843                __FILE__, __LINE__, typeid(T).name(), typeid(ANNO_NAME).name(),
844                SERIALIZABLE ? "true" : "false");
845       }
846
847       Annotatable<T, ANNO_NAME, SERIALIZABLE, IMPL> * operator()(S *ser, 
848             Annotatable<T, ANNO_NAME, SERIALIZABLE, IMPL> &v, const char *tag = NULL, 
849             const char *tag2 = NULL) 
850       {
851           if (!SERIALIZABLE) 
852           {
853              fprintf(stderr, "%s[%d]:  Annotatable<%s, %s, %s>, not serializable\n", 
854                    __FILE__, __LINE__, typeid(T).name(), typeid(ANNO_NAME).name(),
855                    SERIALIZABLE ? "true" : "false");
856              return NULL;
857           }
858
859           int nelem = v.size();
860
861           if (0 == nelem) 
862           {
863              fprintf(stderr, "%s[%d]:  Annotatable<%s, %s, %s>, no annotations\n", 
864                    __FILE__, __LINE__, typeid(T).name(), typeid(ANNO_NAME).name(),
865                    SERIALIZABLE ? "true" : "false");
866              return NULL;
867           }
868
869           //  data structure must exist since size > 0
870
871           std::vector<T> &anno_vec = v.getDataStructure();
872
873           //  But is this OK??  (This goes around the usual annotations interface)
874           //  probably not, but let's see if it works anyways
875
876           fprintf(stderr, "%s[%d]:  WARNING:  This may not be kosher -- circumventing the anotations interface, think on this\n", __FILE__, __LINE__);
877           translate_vector(ser, anno_vec, tag, tag2);
878
879          //  maybe catch errors here?
880          return &v;
881       }
882 };
883 #endif
884
885 template <class S, class T>
886 void gtranslate(S *ser, T &it, const char *tag = NULL, const char *tag2 = NULL)
887 {
888    //fprintf(stderr, "%s[%d]:  welcome to gtranslate<%s, %s>(%p)\n",
889    //      __FILE__, __LINE__,
890    //      "SerializerBase",
891    //      typeid(T).name(), &it);
892
893    //  Maybe just need to do try/catch here since the template mapping may 
894    //  change the type of return value thru template specialization
895
896    trans_adaptor<S, T> ta;
897    //fprintf(stderr, "%s[%d]: gtranslate: before operation\n", __FILE__, __LINE__);
898
899    T *itp = ta(ser, it, tag, tag2);
900
901    if (!itp) 
902    {
903       fprintf(stderr, "%s[%d]: translate adaptor failed to de/serialize\n", 
904             __FILE__, __LINE__);
905    }
906 }
907
908 COMMON_EXPORT bool ifxml_start_element(SerializerBase *sb, const char *tag);
909 COMMON_EXPORT bool ifxml_end_element(SerializerBase *sb, const char * /*tag*/);
910
911 //template<class T> class SerializerBin<T>;
912 //template<class T> class SerializerXML<T>;
913
914 COMMON_EXPORT bool sb_is_input(SerializerBase *sb);
915 COMMON_EXPORT bool sb_is_output(SerializerBase *sb);
916
917 #if 0
918 template <class T>
919 bool ifinput(bool (*f)(SerializerBase *, T*), SerializerBase *sb, T *itp)
920 {
921    if (!sb_is_input(sb))
922       return false;
923
924
925    return (*f)(sb, itp);
926 }
927
928 template <class T>
929 bool ifoutput(bool (*f)(SerializerBase *, T*), SerializerBase *sb, T *itp)
930 {
931    if (!sb_is_output(sb))
932       return false;
933
934    return (*f)(sb, itp);
935 }
936
937 template <class T>
938 bool ifbin(bool (*f)(SerializerBase *, T*), SerializerBase *sb, T *itp)
939 {
940    SerializerBin *sbin = dynamic_cast<SerializerBin *>(sb);
941
942    if (!sbin)
943       return false;
944
945    return (*f)(sbin, itp);
946 }
947
948 template <class T>
949 bool ifxml(bool (*f)(SerializerBase *, T*), SerializerBase *sb, T *itp)
950 {
951    SerializerXML *sxml = dynamic_cast<SerializerXML *>(sb);
952
953    if (!sxml)
954       return false;
955
956    return (*f)(sxml, itp);
957 }
958 #endif
959 #if 0
960 {
961    fprintf(stderr, "%s[%d]:  welcome to gtranslate<%s, %s>(%p)\n",
962          __FILE__, __LINE__,
963          "SerializerBase",
964          typeid(TT).name(), &it);
965
966    //  Maybe just need to do try/catch here since the template mapping may 
967    //  change the type of return value thru template specialization
968    assert(use_func);
969    (*use_func)(ser, it);
970 }
971
972 template<class S, class TT>
973 void trans_enum(S *ser, TT &it, std::vector<std::string> *enum_tags_ptr) 
974 {
975    assert(enum_tags_ptr);
976    std::vector<std::string> &enum_tags = *enum_tags_ptr;
977    assert(it < enum_tags.size());
978    unsigned int enum_int = (unsigned int) it;
979    gtranslate(ser, it);
980 }
981 #endif
982
983
984 template <class S, class T>
985 void gtranslate(S *ser, 
986       T &it, 
987       const char * (*to_str_func)(T), 
988       const char *tag = NULL, 
989       const char * /*tag2*/ = NULL)
990 {
991    assert(ser);
992    int enum_int = (int) it;
993
994    if (!isBinary(ser)) 
995    {
996       assert(isOutput(ser));
997
998       // use human-readable tag
999       const char *enum_tag = (*to_str_func)(it);
1000       std::string enum_tag_str(enum_tag);
1001       assert(enum_tag);
1002
1003       gtranslate(ser, enum_tag_str, tag, NULL);
1004    }
1005    else 
1006    {
1007       //  just in/output raw binary value 
1008       gtranslate(ser, enum_int, tag, NULL);
1009       it = (T) enum_int;
1010    }
1011 }
1012
1013 class SerializerError;
1014
1015 template <class S, class T>
1016 bool gtranslate_w_err(S *ser, T&it, const char *tag = NULL, const char *tag2 = NULL)
1017 {
1018
1019    try 
1020    {
1021       gtranslate(ser, it, tag, tag2);
1022    }
1023
1024    catch (const SerializerError &err_) 
1025    {
1026       fprintf(stderr, "%s[%d]:  gtranslate failed\n", __FILE__, __LINE__);
1027       printSerErr(err_);
1028       return false;
1029    }
1030    return true;
1031 }
1032
1033 //  These are for testing purposes -- do not use elsewhere
1034 //  Must deallocate serializer that is returned when done.
1035 #if 0
1036 SerializerBase *nonpublic_make_bin_serializer(std::string file);
1037 SerializerBase *nonpublic_make_bin_deserializer(std::string file);
1038 void nonpublic_free_bin_serializer(SerializerBase *sb);
1039 #endif
1040 #if 0
1041 template <class T> class SerializerBin;
1042
1043 template <class T>
1044 inline SerializerBase *nonpublic_make_bin_serializer(T *t, std::string file)
1045 {
1046         SerializerBin<T> *ser;
1047         ser = new SerializerBin<T>(t, "SerializerBin", file, sd_serialize, true);
1048         return ser;
1049 }
1050
1051 template <class T>
1052 inline void nonpublic_free_bin_serializer(SerializerBase *sb)
1053 {
1054         SerializerBin<T> *sbin = dynamic_cast<SerializerBin<T> *>(sb);
1055         if (sbin)
1056         {
1057                 delete(sbin);
1058         }
1059         else
1060                 fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
1061 }
1062
1063 template <class T>
1064 inline SerializerBase *nonpublic_make_bin_deserializer(T *t,std::string file)
1065 {
1066         SerializerBin<T> *ser;
1067         ser = new SerializerBin<T>(t, "DeserializerBin", file, sd_deserialize, true);
1068         return ser;
1069 }
1070 #endif
1071
1072 } /* namespace Dyninst */
1073 #endif