Serialization.h

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #if !defined (SERIALIZATION_PUBLIC_H)
00032 #define SERIALIZATION_PUBLIC_H
00033 //  Hopefully just a few definitions allowing for a public interface to 
00034 //  serializing user-providede annotations
00035 
00036 
00037 #define SERIALIZATION_DISABLED
00038 #if defined(SERIALIZATION_DISABLED)
00039 
00040 #if defined(THROW_SPEC)
00041 #undef THROW_SPEC
00042 #endif
00043 #define THROW_SPEC(X)
00044 
00045 #include <stdlib.h>
00046 
00047 namespace Dyninst {
00048    class Serializable {
00049      public:
00050       virtual ~Serializable() {}
00051    };
00052    class SerializerBase {
00053      public:
00054       virtual ~SerializerBase() {}
00055    };
00056 
00057    template <class T>
00058    class AnnotationContainer
00059    {
00060       virtual bool deserialize_item(SerializerBase *) { return true; }
00061      public:
00062         AnnotationContainer() { }
00063         virtual ~AnnotationContainer() { }
00064         virtual bool addItem_impl(T t) = 0;
00065         bool addItem(T t) { return addItem_impl(t); }
00066         virtual const char *getElementTypename() {return NULL;}
00067         virtual Serializable *ac_serialize_impl(SerializerBase *, const char *) THROW_SPEC(SerializerError) { return NULL; };
00068    };
00069 }
00070 
00071 #else
00072 
00073 #include <stdio.h>
00074 #include <assert.h>
00075 #include <string.h>
00076 #include <stdexcept>
00077 #include <typeinfo>
00078 #include <vector>
00079 #include <map>
00080 #include <assert.h>
00081 #include "dyntypes.h"
00082 #include "util.h"
00083 #include "Annotatable.h"
00084 #include "boost/type_traits/is_fundamental.hpp"
00085 #include "boost/type_traits/is_const.hpp"
00086 #include "boost/type_traits/remove_cv.hpp"
00087 #include "boost/type_traits/is_pointer.hpp"
00088 #include "boost/type_traits/is_enum.hpp"
00089 #include "boost/type_traits/alignment_of.hpp"
00090 #include "boost/type_traits/type_with_alignment.hpp"
00091 #include "boost/type_traits/remove_pointer.hpp"
00092 
00093 #define SERIALIZE_CONTROL_ENV_VAR "DYNINST_SERIALIZE_ENABLE"
00094 #define SERIALIZE_DISABLE "disable"
00095 #define SERIALIZE_ONLY "serialize_but_dont_deserialize"
00096 #define SERIALIZE_DESERIALIZE "deserialize"
00097 #define SERIALIZE_DESERIALIZE_OR_DIE "deser_or_die"
00098 #define DESERIALIZE_FORCE_ENV_VAR "DYNINST_DESERIALIZE_FORCE"
00099 
00100 namespace Dyninst 
00101 {
00102 #if 0
00103 //  throw_ser_err(FILE__, __LINE__,"msg") -- an attempt at "graceful" failure.  If debug flag is set
00104 //  it will assert, otherwise it throws...  leaving the "graceful" aspect
00105 //  to the next (hopefully top-level) exception handler.
00106 //  UPDATE -- due to vtable recognition probs between modules (dyninst libs and
00107 //  testsuite executables) no longer asserts.
00108     
00109 
00110 
00111 #define throw_ser_err(FILE__, __LINE__,cmsg) \
00112    do { \
00113       if (serializer_debug_flag()) { \
00114          serialize_printf("SER_ERR: %s", cmsg); \
00115          throw SerializerError(__FILE__, __LINE__, std::string(cmsg)); \
00116       } else { \
00117          throw SerializerError(__FILE__, __LINE__, std::string(cmsg)); \
00118       } \
00119    } while (0)
00120 #endif
00121 
00122 COMMON_EXPORT bool &serializer_debug_flag();
00123 
00124 class SerializerBase;
00125 
00126 typedef enum {sd_serialize, sd_deserialize} iomode_t;
00127 
00128 class SerializerError {
00129    //  SerializerError:  a small class that is thrown by serialization/deserialization
00130    //  routines.  This exists as an attempt to standardize and simplify error handling
00131    //  for ser-des routines that are possibly deeply nested.
00132    //  Here's the rub:  we don't want stray, unhandled exceptions finding their way into
00133    //  the larger system...  thus all entry points to serialization/deserialization need
00134    //  to catch this exception to render it transparent to the rest of the system.
00135 
00136    public:
00137 
00138    typedef enum {
00139       ser_err_unspecified,
00140       ser_err_no_err,
00141       ser_err_disabled
00142    } SerializerErrorType;
00143 
00144    private:
00145 
00146    std::string msg__;
00147    std::string file__;
00148    int line__;
00149    SerializerErrorType err__;
00150 
00151    public:
00152 
00153    COMMON_EXPORT SerializerError(const std::string &__file__, 
00154          const int &__line__, 
00155          const std::string &msg, 
00156          SerializerErrorType __err__ = ser_err_unspecified) :
00157       msg__(msg),
00158       file__(__file__),
00159       line__(__line__),
00160       err__(__err__)
00161    {}
00162 
00163    COMMON_EXPORT virtual ~SerializerError() THROW {}
00164 
00165    COMMON_EXPORT std::string file() const {return file__;}
00166    COMMON_EXPORT std::string msg() const {return msg__;}
00167    COMMON_EXPORT const char* what() const {return msg__.c_str();}
00168    COMMON_EXPORT int line() const {return line__;}
00169    COMMON_EXPORT SerializerErrorType code() const {return err__;}
00170 };
00171 
00172 COMMON_EXPORT void printSerErr(const SerializerError &err);
00173 
00174 typedef enum {
00175     ser_bin,
00176     ser_xml
00177 } ser_type_t;
00178 
00179 class SerContextBase 
00180 {
00181     friend class Serializable;
00182     friend class SerializerBase;
00183     COMMON_EXPORT static std::vector<std::pair<std::string, dyn_hash_map<std::string, short>*> > ser_control_map;
00184     std::string fname;
00185     std::string serfilename;
00186     static dyn_hash_map<std::string, short> *getMapForType(std::string);
00187     public:
00188 
00189     COMMON_EXPORT SerContextBase(std::string, std::string); 
00190     COMMON_EXPORT virtual ~SerContextBase() {}
00191     COMMON_EXPORT virtual void *getVoidContext() = 0;
00192     COMMON_EXPORT virtual const char *getRootTypename() = 0;
00193     COMMON_EXPORT static void enableSerialize(std::string, std::string, bool);
00194     COMMON_EXPORT static void enableDeserialize(std::string, std::string, bool);
00195     COMMON_EXPORT static void enforceDeserialize(std::string, std::string, bool);
00196     COMMON_EXPORT static void enableSerDes(std::string, std::string, bool);
00197     COMMON_EXPORT void enableSerialize(bool);
00198     COMMON_EXPORT void enableDeserialize(bool);
00199     COMMON_EXPORT void enforceDeserialize(bool);
00200     COMMON_EXPORT void enableSerDes(bool);
00201 
00202     COMMON_EXPORT bool serializeEnabled();
00203     COMMON_EXPORT bool deserializeEnabled();
00204     COMMON_EXPORT static bool deserializeEnforced(std::string, std::string);
00205     COMMON_EXPORT bool deserializeEnforced();
00206 
00207     COMMON_EXPORT std::string getSerFileName();
00208     COMMON_EXPORT virtual bool isContextType(Serializable *) = 0;
00209 };
00210 
00211 template <class T>
00212 class SerContext : public SerContextBase
00213 {
00214     T *scope;
00215 
00216     public:
00217 
00218     SerContext(T *scope_, std::string fname) : SerContextBase(std::string(typeid(T).name()), fname), scope(scope_) {}
00219     ~SerContext() {}
00220     void *getVoidContext() {return (void *) scope;}
00221     const char *getRootTypename() {return typeid(T).name();}
00222     T *getScope() {return scope;}
00223     bool isContextType(Serializable *s) { return (NULL != dynamic_cast<T *>(s));}
00224 };
00225 
00226 class SerFile;
00227 class SerDes;
00228 
00229 class SerializerBase {
00230     friend class Serializable;
00231 
00232     public:
00233     COMMON_EXPORT static std::vector<SerializerBase *> active_serializers;
00234     //  TODO:  make these private or protected
00235     static bool global_disable;
00236     private:
00237 
00238     SerFile *sf;
00239     SerDes *sd;
00240     SerContextBase *scon;
00241     unsigned short ser_index;
00242 
00243     std::string serializer_name;
00244 
00245     typedef dyn_hash_map<std::string, SerializerBase *> subsystem_serializers_t;
00246     COMMON_EXPORT static dyn_hash_map<std::string, subsystem_serializers_t> all_serializers;
00247 
00248     dyn_hash_map<void *, AnnotatableSparse *> *sparse_annotatable_map;
00249     dyn_hash_map<void *, AnnotatableDense *> *dense_annotatable_map;
00250     void clearAnnotationMaps();
00251     public:
00252     COMMON_EXPORT void set_annotatable_sparse_map(AnnotatableSparse *, void *);
00253     COMMON_EXPORT void set_annotatable_dense_map(AnnotatableDense *, void *);
00254     COMMON_EXPORT unsigned short getIndex();
00255     COMMON_EXPORT static void globalDisable();
00256     COMMON_EXPORT static bool serializationDisabled();
00257     COMMON_EXPORT static void globalEnable();
00258 
00259     COMMON_EXPORT virtual bool isXML() = 0;
00260     COMMON_EXPORT virtual bool isBin ()= 0;
00261     COMMON_EXPORT bool isEOF();
00262 
00263     COMMON_EXPORT SerContextBase *getContext();
00264     COMMON_EXPORT bool isInput ();
00265     COMMON_EXPORT bool isOutput ();
00266     COMMON_EXPORT AnnotatableSparse *findSparseAnnotatable(void *id);
00267     COMMON_EXPORT AnnotatableDense *findDenseAnnotatable(void *id);
00268 
00269     COMMON_EXPORT static void dumpActiveBinSerializers();
00270 
00271     COMMON_EXPORT SerializerBase(SerContextBase *scb, std::string name_, std::string filename,                 iomode_t dir, bool verbose);
00272     COMMON_EXPORT SerializerBase();
00273 
00274     COMMON_EXPORT virtual ~SerializerBase();
00275 
00276     COMMON_EXPORT virtual SerDes &getSD();
00277     COMMON_EXPORT SerFile &getSF(); 
00278     COMMON_EXPORT std::string &name() {return serializer_name;}
00279     COMMON_EXPORT static SerializerBase *getSerializer(std::string subsystem, std::string fname);
00280     COMMON_EXPORT static bool addSerializer(std::string subsystem, std::string fname, SerializerBase *sb);
00281     COMMON_EXPORT static bool removeSerializer(unsigned short);
00282     COMMON_EXPORT virtual void vector_start(unsigned long &, const char * = NULL);
00283     COMMON_EXPORT virtual void vector_end();
00284     COMMON_EXPORT virtual void hash_map_start(unsigned long &size, const char *tag = NULL);
00285     COMMON_EXPORT virtual void hash_map_end();
00286     COMMON_EXPORT virtual void multimap_start(unsigned long &size, const char *tag = NULL);
00287     COMMON_EXPORT virtual void multimap_end();
00288     COMMON_EXPORT virtual void pair_start(const char *tag = NULL);
00289     COMMON_EXPORT virtual void pair_end();
00290     COMMON_EXPORT virtual void annotation_start(AnnotationClassID &a_id, void *&lparent_id, sparse_or_dense_anno_t &lsod, const char *);
00291     COMMON_EXPORT virtual void annotation_end();
00292     COMMON_EXPORT virtual void annotation_container_start(void *&id);
00293     COMMON_EXPORT virtual void annotation_container_end();
00294     COMMON_EXPORT virtual void annotation_container_item_start(void *&id);
00295     COMMON_EXPORT virtual void annotation_container_item_end();
00296     COMMON_EXPORT void translate_base(bool &v, const char *&t);
00297     COMMON_EXPORT void translate_base(short &v, const char *&t);
00298     COMMON_EXPORT void translate_base(unsigned short &v, const char *&t);
00299     COMMON_EXPORT void translate_base(char &v, const char *&t);
00300     COMMON_EXPORT void translate_base(int &v, const char *&t);
00301     COMMON_EXPORT void translate_base(unsigned int &v, const char *&t);
00302     COMMON_EXPORT void translate_base(unsigned long &v, const char *&t);
00303     COMMON_EXPORT void translate_base(long &v, const char *&t);
00304     COMMON_EXPORT void translate_base(float &v, const char *&t);
00305     COMMON_EXPORT void translate_base(double &v, const char *&t);
00306     COMMON_EXPORT void translate_base(const char * &v, int bufsize, const char *&t);
00307     COMMON_EXPORT void translate_base(char * &v, int bufsize, const char *&t);
00308     COMMON_EXPORT void translate_base(void * &v, const char *&t);
00309     COMMON_EXPORT void translate_base(std::string &v, const char *t);
00310     COMMON_EXPORT virtual void magic_check(const char *file__, unsigned int line__);
00311 
00312     COMMON_EXPORT virtual iomode_t iomode();
00313 
00314     COMMON_EXPORT void serialize_annotations(void *, std::vector<ser_rec_t> &sers, const char * = NULL);
00315     COMMON_EXPORT bool serialize_post_annotation(void *parent_id, void *anno, AnnotationClassBase *acb, sparse_or_dense_anno_t , const char * = NULL);
00316 };
00317 
00318 SerializerBase *createSerializer(SerContextBase *, std::string, std::string, ser_type_t, iomode_t, bool = false);
00319 
00320 class AnnotatableSparse;
00321 class AnnotatableDense;
00322 class AnnotationContainerBase;
00323 
00324 COMMON_EXPORT void serialize_annotatable_id(SerializerBase *sb, void *&id, const char *tag);
00325 COMMON_EXPORT bool set_sb_annotatable_sparse_map(SerializerBase *, AnnotatableSparse *, void *);
00326 COMMON_EXPORT bool set_sb_annotatable_dense_map(SerializerBase *, AnnotatableDense *, void *);
00327 COMMON_EXPORT unsigned short get_serializer_index(SerializerBase *sb);
00328 COMMON_EXPORT void annotation_start(SerializerBase *, AnnotationClassID &, void *&, sparse_or_dense_anno_t &, const char *);
00329 COMMON_EXPORT void annotation_end(SerializerBase *);
00330 COMMON_EXPORT AnnotatableSparse *find_sparse_annotatable(SerializerBase *, void *);
00331 COMMON_EXPORT AnnotatableDense *find_dense_annotatable(SerializerBase *, void *);
00332 COMMON_EXPORT bool isEOF(SerializerBase *);
00333 COMMON_EXPORT void throw_ser_err(const char *file__, unsigned int line, const char *msg);
00334 
00335 
00336 COMMON_EXPORT void annotation_container_start(SerializerBase *sb, void *&id);
00337 COMMON_EXPORT void annotation_container_end(SerializerBase *sb);
00338 COMMON_EXPORT void annotation_container_item_start(SerializerBase *, void *&);
00339 COMMON_EXPORT void annotation_container_item_end(SerializerBase *);
00340 COMMON_EXPORT bool deserialize_container_item(SerializerBase *, void *);
00341 COMMON_EXPORT AnnotationContainerBase *get_container(void *);
00342 COMMON_EXPORT bool deserialize_container_item(AnnotationContainerBase *acb, SerializerBase *sb);
00343 
00344 template <class T>
00345 void enableSerialize(std::string fname, bool val)
00346 {
00347     serialize_printf("%s[%d]:  %s serialize for type %s\n", 
00348             FILE__, __LINE__, val ? "enabling" : "disabling", typeid(T).name());
00349     SerContextBase::enableSerialize(std::string(typeid(T).name()), fname, val);
00350 }
00351 
00352 template <class T>
00353 void enableDeserialize(std::string fname, bool val)
00354 {
00355     serialize_printf("%s[%d]:  %s deserialize for type %s\n", 
00356             FILE__, __LINE__, val ? "enabling" : "disabling", typeid(T).name());
00357     SerContextBase::enableDeserialize(std::string(typeid(T).name()), fname, val);
00358 }
00359 
00360 template <class T>
00361 void enforceDeserialize(std::string fname, bool val)
00362 {
00363     serialize_printf("%s[%d]:  %s enforced deserialize for type %s\n", 
00364             FILE__, __LINE__, val ? "enabling" : "disabling", typeid(T).name());
00365     SerContextBase::enforceDeserialize(std::string(typeid(T).name()), fname, val);
00366 }
00367 
00368 template <class T>
00369 bool deserializeEnforced(std::string fname)
00370 {
00371     return SerContextBase::deserializeEnforced(std::string(typeid(T).name()), fname);
00372 }
00373 
00374 template <class T>
00375 void enableSerDes(std::string fname, bool val)
00376 {
00377     serialize_printf("%s[%d]:  %s serialize/deserialize for type %s\n", 
00378             FILE__, __LINE__, val ? "enabling" : "disabling", typeid(T).name());
00379     SerContextBase::enableSerDes(std::string(typeid(T).name()), fname, val);
00380 }
00381 
00382 class Serializable {
00383     bool was_deserialized;
00384     static void clearContainersByID();
00385 
00386     protected:
00387     unsigned short active_serializer_index;
00388 
00389     COMMON_EXPORT Serializable() : 
00390         was_deserialized(false), 
00391         active_serializer_index((unsigned short) (-1)) {}
00392 
00393     COMMON_EXPORT virtual ~Serializable() 
00394     {
00395         if (active_serializer_index != (unsigned short) -1)
00396         {
00397             SerializerBase *sb = getExistingOutputSB(active_serializer_index);
00398             if (sb)
00399             {
00400                 SerContextBase *scb = sb->getContext();
00401                 if (scb->isContextType(this))
00402                 {
00403                     //  hrm...  not sure this works as intended.
00404                     fprintf(stderr, "%s[%d]:  TOP LEVEL SERIALIZE DONE:  removing serializer\n", FILE__, __LINE__);
00405                     sb->removeSerializer(active_serializer_index);
00406                 }
00407             }
00408         }
00409     }
00410 
00411     COMMON_EXPORT virtual Serializable *serialize_impl(SerializerBase *,  const char * = NULL) THROW_SPEC(SerializerError) = 0;
00412 
00413     public:
00414 
00415     COMMON_EXPORT unsigned short getID() {return active_serializer_index;}
00416 
00417     COMMON_EXPORT bool serialize(std::string filename, SerContextBase *scb, ser_type_t);
00418 
00419     COMMON_EXPORT bool deserialize(std::string filename, SerContextBase *scb) 
00420     {
00421         std::string sername = std::string("Deserializer");
00422 
00423         SerializerBase *serializer = createSerializer(scb, sername, filename, 
00424                 ser_bin, sd_deserialize, /*verbose*/ false);
00425 
00426         if (!serializer) 
00427         {
00428             serialize_printf("%s[%d]:  ERROR:  failed to create deserializer for %s\n", 
00429                     FILE__, __LINE__, filename.c_str());
00430             clearContainersByID();
00431             return false;
00432         }
00433 
00434         try
00435         {
00436             //  Do the serialization
00437             serialize(serializer, NULL);
00438         }
00439         catch (const SerializerError &err_)
00440         {
00441             serialize_printf("%s[%d]:  deserialize failed\n", FILE__, __LINE__);
00442             printSerErr(err_);
00443             serializer->clearAnnotationMaps();
00444             clearContainersByID();
00445             return false;
00446         }
00447         catch (...)
00448         {
00449             serialize_printf("%s[%d]:  caught unexpected exception\n", FILE__, __LINE__);
00450             serializer->clearAnnotationMaps();
00451             clearContainersByID();
00452             return false;
00453         }
00454 
00455         void *barrier_magic = (void *) 0xdeadbeef;
00456         serialize_annotatable_id(serializer, barrier_magic, NULL);
00457 
00458         if (barrier_magic != (void *)0xdeadbeef)
00459         {
00460             fprintf(stderr, "%s[%d]:  FIXME:  failed to read magic barrier\n", FILE__, __LINE__);
00461         }
00462 
00463         unsigned op_count = 0;
00464         while (1)
00465         {
00466             try
00467             {
00468                 void *my_anno = NULL;
00469                 void *parent_id = NULL;
00470                 ser_post_op_t op = sp_add_anno;
00471                 AnnotationClassBase *acb = NULL;
00472                 sparse_or_dense_anno_t sod = sparse;
00473                 AnnotationClassID a_id = 0;
00474 
00475                 serializer_printf("%s[%d]:  reading post-serialize item %d\n", 
00476                         FILE__, __LINE__, op_count);
00477 
00478                 if (!ser_operation(serializer, op, NULL))
00479                 {
00480                     if (isEOF(serializer))
00481                     {
00482                         serialize_printf("%s[%d]:  got EOF\n", FILE__, __LINE__);
00483                         serializer->clearAnnotationMaps();
00484                         clearContainersByID();
00485                         return true;
00486                     }
00487                 }
00488                 switch (op) {
00489                     case sp_add_anno:
00490                         {
00491                         annotation_start(serializer, a_id, parent_id, sod, NULL);
00492                         acb = AnnotationClassBase::findAnnotationClass(a_id);
00493                         if (!acb)
00494                         {
00495                             fprintf(stderr, "%s[%d]:  failed to find annotation type %d\n", 
00496                                     FILE__, __LINE__, a_id);
00497                             serializer->clearAnnotationMaps();
00498                             clearContainersByID();
00499                             return false;
00500                         }
00501                         else
00502                         {
00503                             serializer_printf("%s[%d]:  found annotation id %d/%d\n", 
00504                                     FILE__, __LINE__, acb->getID(), a_id);
00505                         }
00506 
00507                         my_anno = acb->allocate();
00508                         assert(my_anno);
00509 
00510                         ser_func_t sf = acb->getSerializeFunc();
00511                         if (!sf)
00512                         {
00513                             fprintf(stderr, "%s[%d]:  failed to find serialization function\n", 
00514                                     FILE__, __LINE__);
00515                             serializer->clearAnnotationMaps();
00516                             clearContainersByID();
00517                             return false;
00518                         }
00519 
00520                         //  execute the serialization function for this annotation
00521                         serializer_printf("%s[%d]:  calling serialize func for type %s\n",
00522                                 FILE__, __LINE__, acb->getTypeName());
00523 
00524                         (*sf)(my_anno, serializer, NULL);
00525 
00526                         serializer_printf("%s[%d]:  called serialize func for type %s\n",
00527                                 FILE__, __LINE__, acb->getTypeName());
00528 
00529                         annotation_end(serializer);
00530 
00531                         //  we have the (void *) annotation and the annotation type
00532                         //  now lookup the object to which it belonged in the map of 
00533                         //  annotatable objects
00534                         //  and add it as an annotation.
00535 
00536                         if (sparse == sod)
00537                         {
00538                             AnnotatableSparse *as = find_sparse_annotatable(serializer, parent_id);
00539                             if (NULL == as)
00540                             {
00541                                 fprintf(stderr, "%s[%d]:  ERROR:  cannot find anno parent id %p for anno of type %s\n",
00542                                         FILE__, __LINE__, parent_id, acb->getTypeName());
00543                             }
00544                             else
00545                             {
00546                                 assert(acb);
00547 
00548                                 if (!as->addAnnotation(my_anno, acb->getID()))
00549                                 {
00550                                     fprintf(stderr, "%s[%d]:  ERROR:  failed to add annotation here\n",
00551                                             FILE__, __LINE__);
00552                                 }
00553 
00554                                 //  Need to consider case if annotatee is itself annotatable
00555                                 //  this should be tested  (should transparently end up in
00556                                 //  the annotatable-object mapping, but not sure if it does 
00557                                 //  right now)
00558                             }
00559                         }
00560                         else if (dense == sod)
00561                         {
00562                             AnnotatableDense *ad = find_dense_annotatable(serializer, parent_id);
00563                             if (NULL == ad)
00564                             {
00565                                 fprintf(stderr, "%s[%d]:  ERROR:  cannot find anno parent id = %p\n",
00566                                         FILE__, __LINE__, (void *) parent_id);
00567                             }
00568                             else
00569                             {
00570                                 assert(acb);
00571                                 serializer_printf("%s[%d]:  reading post annotation\n", 
00572                                         FILE__, __LINE__);
00573                                 if (!ad->addAnnotation(my_anno, acb->getID()))
00574                                 {
00575                                     fprintf(stderr, "%s[%d]:  ERROR:  failed to add annotation here\n",
00576                                             FILE__, __LINE__);
00577                                 }
00578                             }
00579                         }
00580                         else
00581                         {
00582                             fprintf(stderr, "%s[%d]:  ERROR:  sparse/dense not set properly\n", 
00583                                     FILE__, __LINE__);
00584                             serializer->clearAnnotationMaps();
00585                             clearContainersByID();
00586                             return false;
00587                         }
00588                         break;
00589                         }
00590                     case sp_rem_anno:
00591                         {
00592                             fprintf(stderr, "%s[%d]:  FIXME:  not implemented\n", FILE__, __LINE__);
00593                         break;
00594                         }
00595                     case sp_add_cont_item:
00596                         {
00597                             void *parent_id = NULL;
00598                             annotation_container_item_start(serializer, parent_id);
00599                             if (!parent_id)
00600                             {
00601                                 fprintf(stderr, "%s[%d]:  NULL container with id\n", 
00602                                         FILE__, __LINE__);
00603                                 serializer->clearAnnotationMaps();
00604                                 clearContainersByID();
00605                                 return false;
00606                             }
00607 
00608                             if (!deserialize_container_item(serializer, parent_id))
00609                             {
00610                                 fprintf(stderr, "%s[%d]:  failed deser contitem w/parent %p\n", 
00611                                         FILE__, __LINE__, parent_id);
00612                                 serializer->clearAnnotationMaps();
00613                                 clearContainersByID();
00614                                 return false;
00615                             }
00616 
00617                             annotation_container_item_end(serializer);
00618                             break;
00619                         }
00620                     case sp_rem_cont_item:
00621                         {
00622                             fprintf(stderr, "%s[%d]:  FIXME:  not implemented\n", 
00623                                     FILE__, __LINE__);
00624                         break;
00625                         }
00626                     default:
00627                         fprintf(stderr, "%s[%d]:  ERROR:  bad ser operation %d\n", 
00628                                 FILE__, __LINE__, op);
00629                         serializer->clearAnnotationMaps();
00630                         clearContainersByID();
00631                         return false;
00632                 };
00633 
00634                 if (isEOF(serializer))
00635                 {
00636                     fprintf(stderr, "%s[%d]:  got EOF\n", FILE__, __LINE__);
00637                     serializer->clearAnnotationMaps();
00638                     clearContainersByID();
00639                     return true;
00640                 }
00641 
00642             }
00643             catch (const Dyninst::SerializerError &err_)
00644             {
00645                 if (isEOF(serializer))
00646                 {
00647                     serialize_printf("%s[%d]:  got EOF\n", FILE__, __LINE__);
00648                     serializer->clearAnnotationMaps();
00649                     clearContainersByID();
00650                     return true;
00651                 }
00652                 if (serializer_debug_flag()) 
00653                 {
00654                     fprintf(stderr, "%s[%d]:  deserialize caught exception\n", FILE__, __LINE__);
00655                     printSerErr(err_);
00656                 }
00657                 serializer->clearAnnotationMaps();
00658                 clearContainersByID();
00659                 return false;
00660             }
00661             catch (...)
00662             {
00663                 serialize_printf("%s[%d]:  caught unknown exception\n", FILE__, __LINE__);
00664                 if (isEOF(serializer))
00665                 {
00666                     serialize_printf("%s[%d]:  got EOF\n", FILE__, __LINE__);
00667                     serializer->clearAnnotationMaps();
00668                     clearContainersByID();
00669                     return true;
00670                 }
00671                 serializer->clearAnnotationMaps();
00672                 clearContainersByID();
00673                 return false;
00674             }
00675             op_count++;
00676         }
00677 
00678         serializer->clearAnnotationMaps();
00679         clearContainersByID();
00680         return true;
00681     }
00682 
00683     COMMON_EXPORT SerializerBase *lookupExistingSerializer();
00684     COMMON_EXPORT bool from_cache() {return was_deserialized;}
00685 
00686     COMMON_EXPORT virtual Serializable *serialize(SerializerBase *sb,  
00687             const char *tag = NULL) THROW_SPEC(SerializerError)
00688     {
00689         //  This function must be implemented in the header file so that
00690         //  the vtables of AnnotatableSparse and AnnotatableDense resolve properly
00691         //  (only matters in case of testsuite, but it's nice to have finer grain 
00692         //  tests that this allows)
00693 
00694         //  do base serialization for this class
00695 
00696         sb->magic_check(FILE__, __LINE__);
00697         Serializable *res = serialize_impl(sb, tag);
00698         sb->magic_check(FILE__, __LINE__);
00699 
00700         //  then serialize all Annotations for which a serialization function has been provided
00701         void *id = this;
00702 
00703         AnnotatableSparse *as = dynamic_cast<AnnotatableSparse *> (this);
00704         if (as)
00705         {
00706             id = as;
00707             //  since this class is annotatable, serialize its id (address)
00708             //  so that we can later build a map of all annotatable objects
00709             //  by id, and apply post-annotations to them 
00710 
00711             sb->magic_check(FILE__, __LINE__);
00712             serialize_annotatable_id(sb, id, "SparseAnnotatableObjectID");
00713             sb->magic_check(FILE__, __LINE__);
00714 
00715             if (is_input(sb))  
00716             {
00717                 if (NULL != id)
00718                 {
00719                     if (!set_sb_annotatable_sparse_map(sb, as, id))
00720                     {
00721                         fprintf(stderr, "%s[%d]:  failed to set annotatable-anno mapping here\n", 
00722                                 FILE__, __LINE__);
00723                     }
00724                 }
00725                 else
00726                     fprintf(stderr, "%s[%d]:  ERROR:  id is NULL\n", FILE__, __LINE__);
00727             }
00728 
00729             if (is_output(sb))
00730                 serialize_printf("%s[%d]:  set anno mapping for %p\n", FILE__, __LINE__, id);
00731 
00732             sb->magic_check(FILE__, __LINE__);
00733             as->serializeAnnotations(sb, tag);
00734             sb->magic_check(FILE__, __LINE__);
00735         }
00736         else
00737         {
00738             AnnotatableDense *ad = dynamic_cast<AnnotatableDense *> (this);
00739             if (ad)
00740             {
00741                 //  since this class is annotatable, serialize its id (address)
00742                 //  so that we can later build a map of all annotatable objects
00743                 //  by id, and apply post-annotations to them 
00744                 id = ad;
00745                 sb->magic_check(FILE__, __LINE__);
00746                 serialize_annotatable_id(sb, id, "DenseAnnotatableObjectID");
00747                 sb->magic_check(FILE__, __LINE__);
00748 
00749                 serialize_printf("%s[%d]:  %sserializing annotatable id %p, this = %p\n", 
00750                         FILE__, __LINE__, is_output(sb) ? "": "de", id, this);
00751 
00752                 if (is_input(sb))
00753                 {
00754                     if (NULL != id)
00755                     {
00756                         //  add id to the map of annotatable objects, mapping to "this"
00757 
00758                         if (!set_sb_annotatable_dense_map(sb, ad, id))
00759                         {
00760                             fprintf(stderr, "%s[%d]:  failed to set annotatable-annotation map\n",
00761                                     FILE__, __LINE__);
00762                         }
00763 
00764                         serialize_printf("%s[%d]:  set dense annotatable mapping for id %p\n", 
00765                                 FILE__, __LINE__, (void *)id);
00766                     }
00767                     else
00768                         fprintf(stderr, "%s[%d]:  got NULL id in deserialize\n", FILE__, __LINE__);
00769                 }
00770 
00771                 sb->magic_check(FILE__, __LINE__);
00772                 ad->serializeAnnotations(sb, tag);
00773                 sb->magic_check(FILE__, __LINE__);
00774             }
00775             else
00776             {
00777                 serialize_printf("%s[%d]:  class %s is not annotatable\n", 
00778                         FILE__, __LINE__, typeid(this).name());
00779             }
00780         }
00781 
00782         if (is_input(sb))
00783             was_deserialized = true;
00784 
00785         active_serializer_index = get_serializer_index(sb);
00786 
00787         return res;
00788     }
00789 };
00790 
00791 
00792 class AnnotationContainerBase : public Serializable
00793 {
00794     friend class Serializable;
00795     friend COMMON_EXPORT bool deserialize_container_item(SerializerBase *, void *);
00796     friend COMMON_EXPORT bool deserialize_container_item(AnnotationContainerBase *, SerializerBase *);
00797 
00798     protected:
00799         static dyn_hash_map<void *, AnnotationContainerBase *> containers_by_id;
00800         COMMON_EXPORT static void clearContainersByID();
00801 
00802         COMMON_EXPORT AnnotationContainerBase() {}
00803         COMMON_EXPORT virtual ~AnnotationContainerBase() {}
00804         COMMON_EXPORT virtual bool deserialize_item(SerializerBase *) = 0;
00805 
00806     public:
00807 
00808         COMMON_EXPORT virtual Serializable *ac_serialize_impl(SerializerBase *,  
00809                 const char * = NULL) THROW_SPEC(SerializerError) = 0;
00810 
00811         COMMON_EXPORT virtual Serializable *serialize_impl(SerializerBase *sb,  
00812                 const char *tag = NULL) THROW_SPEC(SerializerError) 
00813         {
00814             void *id = this;
00815             annotation_container_start(sb, id);
00816             //  serialize the id of this container, then call the container serialize func
00817             //serialize_annotatable_id(sb, id, "ContainerID");
00818             Serializable *res = ac_serialize_impl(sb, tag);
00819             annotation_container_end(sb);
00820 
00821             if (is_input(sb))
00822             {
00823                 //  for deserialize build a hash of container ids
00824                 containers_by_id[id] = this;
00825             }
00826             annotatable_printf("%s[%d]: %s AnnotationContainer(%p) of type %s, id = %p\n",
00827                     FILE__, __LINE__, is_input(sb) ? "deserialized" : "serialized", this,
00828                     getElementTypename(), id);     
00829             return res;
00830         }   
00831 
00832         COMMON_EXPORT virtual const char *getElementTypename() = 0; 
00833         COMMON_EXPORT static AnnotationContainerBase *getContainer(void *id)
00834         {
00835             dyn_hash_map<void *, AnnotationContainerBase *>::iterator iter;
00836 
00837             iter = containers_by_id.find(id);
00838             if (iter == containers_by_id.end())
00839             {
00840                 fprintf(stderr, "%s[%d]:  ERROR:  cannot find id %p in container-id map\n", 
00841                         FILE__, __LINE__, id);
00842                 return NULL;
00843             }
00844 
00845             return iter->second;
00846         }
00847 
00848         COMMON_EXPORT static void setContainerID(AnnotationContainerBase *acb, void *id)
00849         {
00850             //  Currently see no need to first check whether we have a duplicate here
00851             containers_by_id[id] = acb;
00852         }
00853 };
00854 
00855 
00856 template <class T>
00857 Serializable *cont_ser_func_wrapper(void *it, SerializerBase *sb, const char *)
00858 {
00859     T *itt =  (T*) it;
00860     gtranslate(sb, *itt);
00861     return NULL;
00862 }
00863 
00864 #if 0
00865 template <class T, typename IS_POINTER, typename IS_SERIALIZABLE>
00866 class SerFuncExecutor 
00867 {
00868     AnnotationClass<T> *ac;
00869 
00870     public:
00871 
00872     SerFuncExecutor(AnnotationClass<T> *ac_) : ac(ac_) {}
00873 
00874     Serializable *operator()(T &my_item, SerializerBase *sb, const char *tag = NULL) 
00875     {
00876         ser_func_t sf = ac->getSerializeFunc();
00877         assert(sf);
00878 
00879         serialize_printf("%s[%d]:  calling serialize func for type %s\n",
00880                 FILE__, __LINE__, ac->getTypeName());
00881 
00882         Serializable *res = (*sf)(&my_item, sb, tag);
00883         return res;
00884     }
00885 };
00886 
00887 template <class T>
00888 class SerFuncExecutor<T, dyn_detail::boost::true_type, dyn_detail::boost::true_type>
00889 {
00890     AnnotationClass<T> *ac;
00891 
00892     public:
00893 
00894     SerFuncExecutor(AnnotationClass<T> *ac_) : ac(ac_) {}
00895 
00896     void operator()(T &my_item, SerializerBase *sb, const char *tag = NULL) 
00897     {
00898         ser_func_t sf = ac->getSerializeFunc();
00899         assert(sf);
00900 
00901         //  T is a pointer, and we need to alloc the object
00902         my_item = (T) ac->allocate();
00903         serialize_printf("%s[%d]:  calling serialize func for type %s\n",
00904                 FILE__, __LINE__, ac->getTypeName());
00905 
00906         Serializable *sable = (*sf)(my_item, sb, tag);
00907 
00908         T res = dynamic_cast<T>(sable);
00909 
00910         if (sable && !res)
00911         {
00912             fprintf(stderr, "%s[%d]:  ERROR:  %s not Serializable ??\n", 
00913                     FILE__, __LINE__, typeid(T).name());
00914         }
00915 
00916         if (res && (res != my_item))
00917         {
00918             fprintf(stderr, "%s[%d]:  serialize func for %s did a realloc\n", 
00919                     FILE__, __LINE__, typeid(T).name());
00920             fprintf(stderr, "%s[%d]:  REMOVED DELETE\n", FILE__, __LINE__);
00921             delete my_item;
00922             my_item = res;
00923         }
00924         serialize_printf("%s[%d]:  called serialize func for type %s\n",
00925                 FILE__, __LINE__, ac->getTypeName());
00926     }
00927 };
00928 #endif
00929 
00930 template <class T>
00931 class AnnotationContainer : public AnnotationContainerBase
00932 {
00933 #if 0
00934     //  We internally manage the annotation class (which includes serialize function)
00935     //  for the elements of this container.  When the container is added as a annotation,
00936     //  the element annotation class is thus not required in addition to the annotation
00937     //  class that the user must supply for the container overall.
00938 
00939     AnnotationClass<T> *ac;
00940 #endif
00941 
00942         virtual bool deserialize_item(SerializerBase *sb)
00943         {
00944             T my_item;
00945             if (dyn_detail::boost::is_pointer<T>::value)
00946             {
00947                 //  if T is a class , memset would clobber the vptr
00948                 memset( &my_item, 0, sizeof(T));
00949             }
00950 
00951             if (!sb)
00952             {
00953                 fprintf(stderr, "%s[%d]:  FIXME:  bad param\n", FILE__, __LINE__);
00954                 return false;
00955             }
00956 #if 0 
00957             ser_func_t sf = ac->getSerializeFunc();
00958 
00959             if (!sf)
00960             {
00961                 fprintf(stderr, "%s[%d]:  failed to find serialization function\n", 
00962                         FILE__, __LINE__);
00963                 return false;
00964             }
00965 
00966             SerFuncExecutor<T, typename dyn_detail::boost::is_pointer<T>::type, 
00967                 typename dyn_detail::boost::is_base_of<Serializable, 
00968                 typename dyn_detail::boost::remove_pointer<T>::type>::type>  
00969                     sfe(ac);
00970 
00971             sfe(my_item, sb);
00972 #else
00973             gtranslate(sb, my_item);
00974 #endif
00975 
00976             if (!addItem_impl(my_item))
00977             {
00978                 fprintf(stderr, "%s[%d]:  failed to addItem after deserialize\n", FILE__, __LINE__);
00979                 return false;
00980             }
00981 
00982             return true;
00983         }
00984 
00985     public:
00986 
00987 
00988         AnnotationContainer() 
00989 #if 0
00990             : ac(NULL)
00991 #endif
00992         {
00993 #if 0
00994             ser_func_t sf = NULL;
00995 
00996             if (dyn_detail::boost::is_fundamental<T>::value)
00997             {
00998                 sf = (ser_func_t) cont_ser_func_wrapper<T>;
00999             }
01000 
01001             std::string aname = std::string(typeid(*this).name()) + std::string("_elem");
01002             ac = new AnnotationClass<T>(aname, NULL, sf);
01003 #endif
01004         }
01005 
01006         ~AnnotationContainer()
01007         {/* if (ac) delete ac; */}
01008 
01009         //  The routine that actually adds the item and manages whatever data structure
01010         //  the container is using.  Must be provided by descendant class.
01011 
01012         virtual bool addItem_impl(T t) = 0;
01013 
01014         bool addItem(T t) 
01015         {
01016             if (!addItem_impl(t))
01017             {
01018                 fprintf(stderr, "%s[%d]:  failed to add item of type %s to container\n", 
01019                         FILE__, __LINE__, typeid(T).name());
01020                 return false;
01021             }
01022 
01023             //  If a serialization has already occurred for the container, serialize this item too
01024 
01025             SerializerBase *sb = lookupExistingSerializer();
01026             if (sb)
01027             {
01028                 //  T must be either a basic type or a descendant of Serializable
01029                 ser_post_op_t op =  sp_add_cont_item;
01030                 void *id = this;
01031                 ser_operation(sb, op, NULL);
01032                 annotation_container_item_start(sb, id);
01033                 gtranslate(sb, t, NULL);
01034                 annotation_container_item_end(sb);
01035             }
01036             return true;
01037         }   
01038 
01039         virtual const char *getElementTypename() {return typeid(T).name();}
01040 
01041         virtual Serializable *ac_serialize_impl(SerializerBase *, 
01042                 const char *tag) THROW_SPEC(SerializerError) = 0;
01043 };
01044 
01045 template <typename T>
01046 void translate_vector(SerializerBase *ser, std::vector<T> &vec,
01047         const char *tag = NULL, const char *elem_tag = NULL)
01048 {
01049     unsigned long nelem = 0UL;
01050 
01051     if (ser->iomode() == sd_serialize)
01052         nelem = (unsigned long) vec.size();
01053 
01054     ser->vector_start(nelem, tag);
01055 
01056     if (ser->iomode() == sd_deserialize) 
01057     {
01058         if (vec.size())
01059             throw_ser_err(FILE__, __LINE__,"nonempty vector used to create");
01060 
01061         //  zero size vectors are allowed
01062         serialize_printf("%s[%d]:  about to resize vector to %lu\n", 
01063                 FILE__, __LINE__, nelem);
01064 
01065         if (nelem)
01066             vec.resize(nelem);
01067     }
01068 
01069     for (unsigned long i = 0; i < nelem; ++i) 
01070     {
01071         gtranslate(ser, vec[i], elem_tag);
01072 #if 0
01073         if (ser->isOutput())
01074             gtranslate(ser, vec[i], elem_tag);
01075         else
01076         {
01077             T t;
01078             gtranslate(ser, t, elem_tag);
01079             vec.push_back(t);
01080         }
01081 #endif
01082 #if 0
01083         T t;
01084         if (ser->isOutput())
01085             t = vec[i];
01086         //T &t = vec[i];
01087         //memset(&(vec[i]), 0, sizeof(T));
01088         gtranslate(ser, t, elem_tag);
01089         if (ser->isInput())
01090             vec[i] = t;
01091 #endif
01092     }
01093 
01094     ser->vector_end();
01095 }
01096 
01097 template <typename K, typename V>
01098 void translate_pair(SerializerBase *ser, std::pair<K, V> &p,
01099         const char *tag = NULL, const char *tag2 = NULL)
01100 {
01101     ser->pair_start();
01102 
01103     gtranslate(ser, p.first, tag);
01104     gtranslate(ser, p.second, tag2);
01105 
01106     ser->pair_end();
01107 }
01108 
01109 template <typename T, typename T2>
01110 struct pair_translator {
01111     void operator()(SerializerBase *ser, std::pair<T, T2> &p, 
01112             const char *tag = NULL, const char *tag2 = NULL)
01113 {
01114     ser->pair_start();
01115 
01116     gtranslate(ser,  p.first, tag);
01117     gtranslate(ser,  p.second, tag2);
01118 
01119     ser->pair_end();
01120 }
01121 };
01122 
01123 template <class S, class K, class V>
01124 void translate_dyn_hash_map(S *ser, dyn_hash_map<K, V> &map,
01125         const char *tag = NULL, const char *elem_tag = NULL)
01126 {
01127     serialize_printf("%s[%d]:  welcome to translate_dyn_hash_map<%s, %s>, size = %ld\n", 
01128             FILE__, __LINE__, typeid(K).name(), typeid(V).name(), map.size());
01129 
01130     unsigned long nelem = 0UL;
01131     nelem = map.size();
01132     ser->hash_map_start(nelem, tag);
01133 
01134     if (ser->iomode() == sd_deserialize)
01135     {
01136         if (map.size())
01137             throw_ser_err(FILE__, __LINE__,"nonempty vector used to create");
01138 
01139         for (unsigned long i = 0UL; i < nelem; ++i)
01140         {
01141             typename dyn_hash_map<K, V>::value_type mapentry;
01142             gtranslate(ser, mapentry, elem_tag);
01143             map.insert(mapentry);
01144         }
01145     }
01146     else
01147     {
01148         assert (ser->iomode() == sd_serialize);
01149         typename dyn_hash_map<K, V>::iterator iter = map.begin();
01150         while (iter != map.end())
01151         {
01152             gtranslate(ser, *iter, elem_tag);
01153             iter++;
01154         }
01155     }
01156 
01157     ser->hash_map_end();
01158 
01159     serialize_printf("%s[%d]:  leaving translate_dyn_hash_map<%s, %s>\n", 
01160             FILE__, __LINE__, typeid(K).name(), typeid(V).name());
01161 }
01162 
01163 template <class S, class K, class V>
01164 void translate_map(S *ser, std::map<K, V> &map,
01165         const char *tag = NULL, const char *elem_tag = NULL)
01166 {
01167     unsigned long nelem = 0UL;
01168     nelem = map.size();
01169     ser->map_start(nelem, tag);
01170 
01171     if (ser->iomode() == sd_deserialize)
01172     {
01173         if (map.size())
01174             throw_ser_err(FILE__, __LINE__,"nonempty vector used to create");
01175 
01176         typename std::map<K, V>::iterator lastentry = map.begin();
01177         //  cannot do any kind of bulk allocation with maps
01178         for (unsigned int i = 0; i < nelem; ++i)
01179         {
01180             K a_k;
01181             V a_v;
01182             gtranslate(ser, a_k, elem_tag);
01183             gtranslate(ser, a_v, elem_tag);
01184             map[a_k] = a_v;
01185         }
01186 
01187     }
01188     else
01189     {
01190         assert (ser->iomode() == sd_serialize);
01191         typename std::map<K, V>::iterator iter = map.begin();
01192         while (iter != map.end())
01193         {
01194             K &a_k = const_cast<K &>(iter->first);
01195             V &a_v = const_cast<V &>(iter->second);
01196             gtranslate(ser, a_k, elem_tag);
01197             gtranslate(ser, a_v, elem_tag);
01198             iter++;
01199         }
01200     }
01201     ser->map_end();
01202 }
01203 
01204 template <class K, class V, class L>
01205 struct multimap_translator
01206 {
01207     void operator()(SerializerBase *ser, std::multimap<K, V, L> &map, 
01208             const char *tag = NULL, const char *elem_tag = NULL)
01209     {
01210         unsigned long nelem = 0UL;
01211         nelem = map.size();
01212         ser->multimap_start(nelem, tag);
01213 
01214         if (ser->iomode() == sd_deserialize)
01215         {
01216             if (map.size())
01217                 throw_ser_err(FILE__, __LINE__,"nonempty vector used to create");
01218 
01219             typename std::multimap<K, V, L>::iterator lastentry = map.begin();
01220             //  cannot do any kind of bulk allocation with multimaps
01221             for (unsigned int i = 0; i < nelem; ++i)
01222             {
01223                 typename std::multimap<K, V, L>::value_type mapentry;
01224                 gtranslate(ser, mapentry, elem_tag);
01225                 //  lastentry serves as a hint as to where the new value goes 
01226                 //  (presumably near the last value inserted)
01227                 //  not sure if this really makes things more efficient.
01228                 lastentry = map.insert(lastentry, mapentry);
01229             }
01230 
01231         }
01232         else
01233         {
01234             assert (ser->iomode() == sd_serialize);
01235             typename std::multimap<K, V, L>::iterator iter = map.begin();
01236             while (iter != map.end())
01237             {
01238                 gtranslate(ser, *iter, elem_tag);
01239                 iter++;
01240             }
01241         }
01242 
01243         ser->multimap_end();
01244     }
01245 };
01246 
01247 template <class K, class V, class L>
01248 void translate_multimap(SerializerBase *ser, std::multimap<K, V, L> &map,
01249         const char *tag = NULL, const char *elem_tag = NULL)
01250 {
01251     unsigned long nelem = 0UL;
01252     nelem = map.size();
01253     ser->multimap_start(nelem, tag);
01254 
01255     if (ser->iomode() == sd_deserialize)
01256     {
01257         if (map.size())
01258             throw_ser_err(FILE__, __LINE__,"nonempty vector used to create");
01259 
01260         typename std::multimap<K, V, L>::iterator lastentry = map.begin();
01261         //  cannot do any kind of bulk allocation with multimaps
01262         for (unsigned int i = 0; i < nelem; ++i)
01263         {
01264             typename std::multimap<K, V, L>::value_type mapentry;
01265             gtranslate(ser, mapentry, elem_tag);
01266             //  lastentry serves as a hint as to where the new value goes 
01267             //  (presumably near the last value inserted)
01268             //  not sure if this really makes things more efficient.
01269             lastentry = map.insert(lastentry, mapentry);
01270         }
01271 
01272     }
01273     else
01274     {
01275         assert (ser->iomode() == sd_serialize);
01276         typename std::multimap<K, V, L>::iterator iter = map.begin();
01277         while (iter != map.end())
01278         {
01279             gtranslate(ser, *iter, elem_tag);
01280             iter++;
01281         }
01282     }
01283 
01284     ser->multimap_end();
01285 }
01286 
01287 template <class S, class K, class V>
01288 void translate_hash_map(S *ser, dyn_hash_map<K, V> &hash, 
01289         const char *tag = NULL, const char *key_tag = NULL, const char *value_tag = NULL)
01290 {   
01291     fprintf(stderr, "%s[%d]:  welcome to translate_hash_map<%s, %s>()\n", 
01292             __FILE__, __LINE__,
01293             typeid(K).name(), typeid(V).name()); 
01294 
01295     unsigned long nelem = 0UL;
01296     nelem = hash.size();
01297     ser->hash_map_start(nelem, tag);
01298 
01299     if (ser->iomode() == sd_serialize) 
01300     {
01301         typename dyn_hash_map<K,V>::iterator iter = hash.begin();
01302 
01303         while (iter != hash.end()) 
01304         {
01305             K k = iter->first;
01306             V v = iter->second;
01307             ser->translate_base(k, key_tag);
01308             ser->translate_base(v, value_tag);
01309             iter++;           
01310         }
01311     }
01312     else 
01313     {
01314         //  can we do some kind of preallocation here?
01315         for (unsigned long i = 0; i < nelem; ++i) 
01316         {
01317             K k;
01318             V v;
01319             // zero out pointers to silence complaints about assigning
01320             // new objects to non-NULL pointers
01321             if (dyn_detail::boost::is_pointer<K>::value)
01322                 memset(&k, 0, sizeof(K));
01323             if (dyn_detail::boost::is_pointer<V>::value)
01324                 memset(&v, 0, sizeof(V));
01325             ser->translate_base(k, key_tag);
01326             ser->translate_base(v, value_tag);
01327             hash[k] = v;
01328         }
01329     }
01330 
01331     ser->hash_map_end();
01332 }
01333 
01334 COMMON_EXPORT bool isBinary(Dyninst::SerializerBase *ser);
01335 COMMON_EXPORT bool isOutput(Dyninst::SerializerBase *ser);
01336 
01337 typedef void NOTYPE_T;
01338 
01339 template<typename T, typename T2 = typename dyn_detail::boost::is_enum<T>::type,
01340     typename T3 = typename dyn_detail::boost::is_base_of<Serializable, T>::type>
01341 class trans_adaptor {
01342    public:
01343       trans_adaptor()  {}
01344 
01345       T * operator()(SerializerBase *ser, T & it, 
01346               const char *tag = NULL, const char * /*tag2*/ = NULL)
01347       {
01348          ser->translate_base(it, tag);
01349          return &it;
01350       }
01351 };
01352 
01353 template <>
01354 class trans_adaptor<char *, dyn_detail::boost::false_type, 
01355       dyn_detail::boost::false_type> 
01356 {
01357    public:
01358       trans_adaptor()  {}
01359 
01360       char * * operator()(SerializerBase *ser, char * & it, 
01361               const char *tag = NULL, const char * /*tag2*/ = NULL)
01362       {
01363           int len = it ? strlen(it) : 0;
01364           ser->translate_base(it, len, tag);
01365           return &it;
01366       }
01367 };
01368 
01369 template<typename T>
01370 class trans_adaptor<T, dyn_detail::boost::false_type, 
01371       dyn_detail::boost::true_type> 
01372 {
01373    public:
01374       trans_adaptor()  {}
01375 
01376       Serializable * operator()(SerializerBase *ser, T & it, const char *tag = NULL, 
01377             const char * /*tag2*/ = NULL)
01378       {
01379          //gtranslate(ser, it, tag);
01380 
01381           serialize_printf("%s[%d]:  translating serializable: %s\n", 
01382                   FILE__, __LINE__, typeid(T).name());
01383 
01384           it.serialize(ser, tag);
01385 
01386           serialize_printf("%s[%d]:  translated serializable: %s\n", 
01387                   FILE__, __LINE__, typeid(T).name());
01388 
01389          return &it;
01390       }
01391 };
01392 
01393 template<typename T>
01394 class trans_adaptor<T, dyn_detail::boost::true_type, 
01395       dyn_detail::boost::false_type> 
01396 {
01397    public:
01398       trans_adaptor()  {}
01399 
01400       Serializable * operator()(SerializerBase *ser, T & it, const char *tag = NULL, 
01401             const char * /*tag2*/ = NULL)
01402       {
01403           
01404           if (sizeof(T) != sizeof(int)) 
01405               fprintf(stderr, "%s[%d]:  enum size is %lu, not %lu\n",
01406                       FILE__, __LINE__, sizeof(T), sizeof(int));
01407           int e_int = (int) it;
01408           ser->translate_base(e_int, tag);
01409           if (ser->isInput())
01410               it = (T) e_int;
01411 #if 0
01412          //gtranslate(ser, it, tag);
01413 
01414           serialize_printf("%s[%d]:  translating serializable: %s\n", 
01415                   FILE__, __LINE__, typeid(T).name());
01416 
01417           it.serialize(ser, tag);
01418 
01419           serialize_printf("%s[%d]:  translated serializable: %s\n", 
01420                   FILE__, __LINE__, typeid(T).name());
01421 #endif
01422 
01423           return NULL;
01424          //return &it;
01425       }
01426 };
01427 
01428 #if 0
01429 template<typename T>
01430 class trans_adaptor<std::vector<T>, dyn_detail::boost::false_type, 
01431       dyn_detail::boost::false_type> 
01432 {
01433    public:
01434       trans_adaptor() {}
01435 
01436       std::vector<T> * operator()(SerializerBase *ser, std::vector<T> &v,  
01437             const char *tag = NULL, const char *tag2 = NULL) 
01438       {
01439          translate_vector(ser, v, tag, tag2);         //  maybe catch errors here?
01440          return &v;
01441       }
01442 };
01443 #endif
01444 
01445 template <typename T, bool = dyn_detail::boost::is_base_of<Serializable, typename dyn_detail::boost::remove_pointer<T>::type>::value>
01446 class deref_adaptor 
01447 {
01448     public:
01449         deref_adaptor() {}
01450 
01451         T * operator()(SerializerBase *sb, T &it, 
01452                 const char *tag = NULL, const char *tag2 = NULL)
01453         {
01454             trans_adaptor<T> ta;
01455             ta(sb, it, tag, tag2);
01456             return &it;
01457         }
01458 };
01459 
01460 template <typename T>
01461 class deref_adaptor<T, true> 
01462 {
01463     public:
01464         deref_adaptor() {}
01465 
01466         T * operator()(SerializerBase *sb, T *&it, 
01467                 const char *tag = NULL, const char *tag2 = NULL)
01468         {
01469             //  need to allocate upon deserialize
01470             if (!isOutput(sb))
01471             {
01472                 it = new T();
01473             }
01474             gtranslate(sb, *it, tag, tag2);
01475             return it;
01476         }
01477 };
01478 
01479 template <typename T, typename T2 = typename dyn_detail::boost::is_pointer<T>::type, 
01480          typename T3 = typename dyn_detail::boost::is_base_of<Serializable,
01481          typename dyn_detail::boost::remove_pointer<T>::type>::type>
01482 class ptr_adaptor 
01483 {
01484     public:
01485         ptr_adaptor() {}
01486 
01487         T * operator()(SerializerBase *sb, T &it, 
01488                 const char *tag = NULL, const char *tag2 = NULL)
01489         {
01490             trans_adaptor<T> ta;
01491             ta(sb, it, tag, tag2);
01492             return &it;
01493         }
01494 };
01495 
01496 template <typename T>
01497 class ptr_adaptor<T, dyn_detail::boost::true_type, dyn_detail::boost::false_type> 
01498 {
01499     typedef typename dyn_detail::boost::remove_pointer<T>::type pointed_to_t;
01500 
01501     public:
01502         ptr_adaptor() {}
01503         T * operator()(SerializerBase *sb, T &it, 
01504                 const char *tag = NULL, const char *tag2 = NULL)
01505         {
01506             deref_adaptor<pointed_to_t> da;
01507             da(sb, it, tag, tag2);
01508             return &it;
01509         }
01510 };
01511 
01512 template <typename T>
01513 class ptr_adaptor<T, dyn_detail::boost::true_type, dyn_detail::boost::true_type> 
01514 {
01515     typedef typename dyn_detail::boost::remove_pointer<T>::type pointed_to_t;
01516     public:
01517         ptr_adaptor() {}
01518         T * operator()(SerializerBase *sb, T &it, 
01519                 const char *tag = NULL, const char * = NULL)
01520         {
01521             if (!isOutput(sb))
01522             {
01523                 if (it)
01524                     fprintf(stderr, "%s[%d]:  WARNING:  allocating to non-null pointer: %s\n", 
01525                             FILE__, __LINE__, typeid(T).name());
01526                 serialize_printf("%s[%d]:  allocating new %s\n", 
01527                         FILE__, __LINE__, typeid(T).name());
01528 
01529                 it = new pointed_to_t();
01530             }
01531 
01532             Serializable *res = NULL;
01533             res = it->serialize(sb, tag);
01534 
01535             if (!isOutput(sb)) 
01536             {
01537                 T res_typed = dynamic_cast<T>(res);
01538 
01539                 if (res && !res_typed)
01540                 {
01541                     fprintf(stderr, "%s[%d]:  ERROR:  ser func allocated bad type object! not %s\n", 
01542                             FILE__, __LINE__, typeid(T).name());
01543                 }
01544 
01545                 if (res_typed && (res_typed != it))
01546                 {
01547                     serialize_printf("%s[%d]:  serialize fn for %s reallocated object\n", 
01548                             FILE__, __LINE__, typeid(T).name());
01549                     delete it;
01550                     it = res_typed;
01551                 }
01552             }
01553 
01554             return &it;
01555         }
01556 };
01557 
01558 //  Another specialization:  do _not_ dereference any char *'s, they're special
01559 //  (maybe want to do this for all fundamental types)
01560 template <>
01561 class ptr_adaptor<char *, dyn_detail::boost::true_type, dyn_detail::boost::false_type> 
01562 {
01563     public:
01564         ptr_adaptor() {}
01565         char * * operator()(SerializerBase *sb, char * &it, 
01566                 const char *tag = NULL, const char *tag2 = NULL)
01567         {
01568             trans_adaptor<char *> ta;
01569             ta(sb, it, tag, tag2);
01570             return &it;
01571         }
01572 };
01573 
01574 template <typename T, bool  = dyn_detail::boost::is_const<T>::value>
01575 class const_adaptor 
01576 {
01577     public:
01578         const_adaptor() {}
01579 
01580         T *operator()(SerializerBase *sb, T &it, 
01581                 const char *tag = 0, const char *tag2 = 0)
01582         {
01583             ptr_adaptor<T> ta;
01584             T *itp = ta(sb, it, tag, tag2);
01585             return itp;
01586         }
01587 };
01588 
01589 template <typename T>
01590 class const_adaptor<T, true>
01591 {
01592     typedef typename dyn_detail::boost::remove_cv<T>::type non_const_type;
01593 
01594     public:
01595     const_adaptor() {}
01596 
01597     T *operator()(SerializerBase *sb, T &it, 
01598             const char *tag = 0, const char *tag2 = 0)
01599     {
01600         gtranslate(sb, const_cast<non_const_type &>(it), tag, tag2);
01601         return &it;
01602     }
01603 };
01604 
01605 template <typename T>
01606 void gtranslate(SerializerBase *ser, T &it, 
01607         const char *tag = NULL, const char *tag2 = NULL)
01608 {
01609    //fprintf(stderr, "%s[%d]:  welcome to gtranslate<%s, %s>(%p)\n",
01610    //      __FILE__, __LINE__,
01611    //      "SerializerBase",
01612    //      typeid(T).name(), &it);
01613 
01614    const_adaptor<T> ta;
01615    T *itp = ta(ser, it, tag, tag2);
01616 
01617    if (!itp) 
01618    {
01619       fprintf(stderr, "%s[%d]: translate adaptor failed to de/serialize\n", 
01620             __FILE__, __LINE__);
01621    }
01622 }
01623 
01624 template <typename T>
01625 void gtranslate(SerializerBase *ser, std::vector<T> &it, 
01626         const char *tag = NULL, const char *tag2 = NULL)
01627 {
01628     translate_vector(ser, it, tag, tag2);
01629 }
01630 
01631 template <typename T, typename T2>
01632 void gtranslate(SerializerBase *ser, std::pair<T, T2> &it, 
01633         const char *tag = NULL, const char *tag2 = NULL)
01634 {
01635     //translate_pair(ser, it, tag, tag2);
01636     pair_translator<T, T2> pt;
01637     pt(ser, it, tag, tag2);
01638 }
01639 
01640 template <typename K, typename V, typename L>
01641 void gtranslate(SerializerBase *ser, std::multimap<K, V, L> &it, 
01642         const char *tag = NULL, const char *tag2 = NULL)
01643 {
01644     translate_multimap(ser, it, tag, tag2);
01645 }
01646 
01647 template <typename K, typename V>
01648 void gtranslate(SerializerBase *ser, dyn_hash_map<K, V> &it, 
01649         const char *tag = NULL, const char *tag2 = NULL)
01650 {
01651     translate_dyn_hash_map(ser, it, tag, tag2);
01652 }
01653 
01654 COMMON_EXPORT bool ifxml_start_element(SerializerBase *sb, const char *tag);
01655 COMMON_EXPORT bool ifxml_end_element(SerializerBase *sb, const char * /*tag*/);
01656 COMMON_EXPORT bool sb_is_input(SerializerBase *sb);
01657 COMMON_EXPORT bool sb_is_output(SerializerBase *sb);
01658 
01659 template <typename T>
01660 void gtranslate(SerializerBase *ser, 
01661       T &it, 
01662       const char * (*to_str_func)(T), 
01663       const char *tag = NULL, 
01664       const char * /*tag2*/ = NULL)
01665 {
01666    assert(ser);
01667    int enum_int = 0;
01668    enum_int = (int) it;
01669 
01670    if (!isBinary(ser)) 
01671    {
01672       assert(isOutput(ser));
01673 
01674       // use human-readable tag
01675       const char *enum_tag = (*to_str_func)(it);
01676       std::string enum_tag_str(enum_tag);
01677       assert(enum_tag);
01678 
01679       gtranslate(ser, enum_tag_str, tag, NULL);
01680    }
01681    else 
01682    {
01683       //  just in/output raw binary value 
01684       //gtranslate(ser, it);
01685       gtranslate(ser, enum_int, tag, NULL);
01686       it = (T) enum_int;
01687    }
01688 }
01689 
01690 template <typename T>
01691 bool gtranslate_w_err(SerializerBase *ser, T &it, 
01692         const char *tag = NULL, const char *tag2 = NULL)
01693 {
01694    try 
01695    {
01696       gtranslate(ser, it, tag, tag2);
01697    }
01698 
01699    catch (const SerializerError &err_) 
01700    {
01701       fprintf(stderr, "%s[%d]:  gtranslate failed\n", __FILE__, __LINE__);
01702       printSerErr(err_);
01703       return false;
01704    }
01705    return true;
01706 }
01707 
01708 } /* namespace Dyninst */
01709 
01710 #endif
01711 
01712 #endif
01713 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1