fixes for gcc 4
[dyninst.git] / dynutil / h / Annotatable.h
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: Annotatable.h,v 1.14 2008/09/15 18:37:49 jaw Exp $
43
44 #ifndef _ANNOTATABLE_
45 #define _ANNOTATABLE_
46
47 #include <cstring>
48 #include <vector>
49 #include <string>
50 #include <typeinfo>
51 #include <assert.h>
52 #include "dyntypes.h"
53 #include "util.h"
54 #include "Serialization.h"
55
56 class AnnotatableBase;
57
58 using std::vector;
59
60
61 typedef enum {
62    anno_impl_static_sparse,
63    anno_impl_static_dense,
64    anno_impl_local_dense,
65 } annotation_implementation_t;
66
67 class SerDes;
68 class SerializerBase;
69 class SerializerError;
70 void printSerErr(SerializerError &);
71 SerializerBase *getSDAnno(std::string &anno_name);
72 void dumpSDAnno();
73
74 template <class T, class ANNO_NAME_T>
75 bool init_anno_serialization(SerializerBase * = NULL);
76
77 class DLLEXPORT_COMMON AnnotatableBase
78 {
79    protected:
80       AnnotatableBase();
81       ~AnnotatableBase() {}
82
83       typedef struct 
84       {
85          int anno_id;
86 #if defined (cap_serialization)
87          SerializerBase *anno_serializer;
88 #endif
89       } anno_info_t;
90
91    private:
92
93       static std::string emptyString;
94       static int number;
95       static dyn_hash_map<std::string, anno_info_t> annotationTypes;
96       static dyn_hash_map<std::string, int> metadataTypes;
97       static dyn_hash_map<std::string, std::string> annotypes_to_typenames;
98       static int metadataNum;
99
100    public:
101
102       static int createAnnotationType(std::string &name, const char *tname, SerializerBase *);
103       static int getAnnotationType(std::string &name, const char *tname = NULL);
104       static SerializerBase *getAnnotationSerializer(std::string &name);
105       static  void dumpAnnotationSerializers();
106       static std::string &findTypeName(std::string anno_name);
107       static int getOrCreateAnnotationType(std::string &anno_name, const char *tname); 
108
109 #if 0
110       virtual int createMetadata(std::string &name);
111       virtual int getMetadata(std::string &name);
112 #endif
113
114 };
115
116 template<class T>
117 class AnnotationSet {
118    //  T is a container, so far, always a vector of something else
119
120    typedef dyn_hash_map<char *, T*> obj_map_t;
121    static std::vector<obj_map_t *> annos_by_id;
122
123    public:
124
125    AnnotationSet() {}
126    ~AnnotationSet() {}
127
128    static T *findAnnotationSet(char  *b, int anno_id) 
129    {
130       if ((unsigned)anno_id >= annos_by_id.size()) 
131       {
132          //fprintf(stderr, "%s[%d]:  no annotations for object %p\n", FILE__, __LINE__, b);
133          return NULL;
134       }
135
136       obj_map_t *anno_sets_by_obj_p = annos_by_id[anno_id];
137
138       if (NULL == anno_sets_by_obj_p) 
139       {
140          fprintf(stderr, "%s[%d]:  FIXME,  null pointer in slot %d\n", 
141                FILE__, __LINE__, anno_id);
142          return NULL;
143       }
144
145       obj_map_t &anno_sets_by_obj = *anno_sets_by_obj_p;
146       typename obj_map_t::iterator nm_iter = anno_sets_by_obj.find(b);
147
148       if (nm_iter == anno_sets_by_obj.end()) 
149       {
150          //fprintf(stderr, "%s[%d]:  no annotations of type %d for object %p\n", 
151          //      FILE__, __LINE__, anno_id, b);
152          return NULL;
153       }
154
155       return nm_iter->second;
156    }
157
158    static T *getAnnotationSet(char *b, int anno_id)
159    {
160       T *it = NULL;
161
162       if (anno_id < 0) 
163       {
164          fprintf(stderr, "%s[%d]:  BAD NEWS:  anno_id = %d\n", FILE__, __LINE__, anno_id);
165          return NULL;
166          abort();
167       }
168
169       if (NULL == (it = findAnnotationSet(b, anno_id))) 
170       {
171
172          //fprintf(stderr, "%s[%d]:  anno_id = %d, annos_by_id.size() = %d\n", 
173          //      FILE__, __LINE__, anno_id, annos_by_id.size());
174
175          while ((unsigned)anno_id >= annos_by_id.size())
176          {
177             obj_map_t *new_sets_by_obj = new obj_map_t();
178             annos_by_id.push_back(new_sets_by_obj);
179          };
180
181          obj_map_t *obj_map = annos_by_id[anno_id];
182
183          it = new T();
184          (*obj_map)[b] = it;
185       }
186
187       return it;
188    }
189
190
191 #if 0
192    static bool removeAnnotationSet(char *b, int anno_id)
193    {
194       typename obj_map_t::iterator iter = sets_by_obj.find(b);
195       if (iter == sets_by_obj.end())
196          return false;
197
198       as_id_map_t *anno_sets_by_id_ptr  = iter->second;
199       assert(anno_sets_by_id_ptr);
200       as_id_map_t &anno_sets_by_id = *anno_sets_by_id_ptr;
201
202       typename as_id_map_t::iterator nm_iter = anno_sets_by_id.find(anno_id);
203       if (nm_iter == anno_sets_by_id.end()) {
204          // sanity check that this map is not empty
205          assert(anno_sets_by_id.size());
206          return false;
207       }
208
209       delete nm_iter->second;
210       anno_sets_by_id.erase(nm_iter);
211       
212       //  if we just got rid of the last element of the map, get rid of the map
213       //  (within a map) as well.
214
215       if (!anno_sets_by_id.size()) {
216          fprintf(stderr, "%s[%d]:  DELETING\n", FILE__, __LINE__);
217          delete anno_sets_by_id_ptr;
218          sets_by_obj.erase(iter);
219       }
220
221       return true;
222    }
223 #endif
224 };
225
226 template< class T > std::vector<dyn_hash_map<char *, T*> *>
227 AnnotationSet< T >::annos_by_id;
228
229 template <class T, class ANNOTATION_NAME_T, bool SERIALIZABLE = false>
230 class AnnotatableCommon : public AnnotatableBase 
231 {
232    public:
233       AnnotatableCommon(SerializerBase *serializer) :
234          AnnotatableBase()
235       {
236 #if defined (cap_serialization)
237          static bool did_init = false;
238          if (SERIALIZABLE && !did_init) 
239          {
240             init_anno_serialization<T, ANNOTATION_NAME_T>(serializer);
241             did_init = true;
242          }
243 #endif
244       }
245
246       AnnotatableCommon() :
247          AnnotatableBase()
248       {
249          //  NULL default value required for default ctors of derived objects
250          //  thus all code that uses serializer must check for its existence
251 #if defined (cap_serialization)
252          static bool did_init = false;
253          if (SERIALIZABLE && !did_init) 
254          {
255             init_anno_serialization<T, ANNOTATION_NAME_T>(NULL);
256             did_init = true;
257          }
258 #endif
259       }
260
261       ~AnnotatableCommon() 
262       {
263       }
264
265       AnnotatableCommon(const AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE> &/*src*/) :
266          AnnotatableBase()
267       {/*hrm deep copy here or no?*/}
268
269       typedef typename std::vector<T> Container_t;
270       Container_t *initAnnotations()
271       {
272          Container_t *v = NULL;
273          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
274
275          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
276
277          if (anno_id == -1) 
278          {
279             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
280                   FILE__, __LINE__, anno_name.c_str());
281             return NULL;
282          }
283
284          v = AnnotationSet<Container_t>::getAnnotationSet((char *)this, anno_id);
285
286          if (!v) 
287          {
288             fprintf(stderr, "%s[%d]:  malloc problem\n", FILE__, __LINE__);
289             abort();
290             return NULL;
291          }
292
293          return v;
294       }
295
296
297       bool addAnnotation(T it)
298       {
299          Container_t *v = NULL;
300          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
301
302          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
303
304          if (anno_id == -1) 
305          {
306             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
307                   FILE__, __LINE__, anno_name.c_str());
308             return false;
309          }
310
311          v = AnnotationSet<std::vector<T> >::findAnnotationSet((char *)this, anno_id);
312
313          if (!v)
314          {
315             if (NULL == ( v = initAnnotations())) 
316             {
317                fprintf(stderr, "%s[%d]:  bad annotation type\n", FILE__, __LINE__);
318                return false;
319             }
320          }
321
322          if (!v) 
323          {
324             fprintf (stderr, "%s[%d]:  initAnnotations failed\n", FILE__, __LINE__);
325             return false;
326          }
327
328          v->push_back(it);
329
330 #if defined (cap_serialization)
331          if (SERIALIZABLE) 
332          {
333
334             fprintf(stderr, "%s[%d]:  serializing annotation here for %s\n", 
335                   FILE__, __LINE__, anno_name.c_str());
336
337             SerializerBase *sd_bin = getSDAnno(anno_name);
338
339             if (!sd_bin) 
340             {
341                //fprintf(stderr, "%s[%d]:  ERROR:  no serializer listed for type %s, have:\n",
342                 //     FILE__, __LINE__, anno_name.c_str());
343                //dumpSDAnno();
344
345                fprintf(stderr, "%s[%d]:  ERROR:  no serializer listed for type %s\n",
346                      FILE__, __LINE__, anno_name.c_str());
347
348                return false;
349             }
350
351             if (!gtranslate_w_err(sd_bin, /*(Serializable &)*/ it, NULL)) 
352             {
353                fprintf(stderr, "%s[%d]:  gtranslate_w_err failed\n", FILE__, __LINE__);
354                return false;
355             }
356
357             fprintf(stderr, "%s[%d]:  \tserialized annotation here for %s\n", 
358                   FILE__, __LINE__, anno_name.c_str());
359          }
360 #endif
361          return true;
362       }
363
364       void clearAnnotations()
365       {
366          Container_t *v = NULL;
367          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
368
369          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
370          
371          if (anno_id == -1) 
372          {
373             return;
374          }
375
376          v = AnnotationSet<std::vector<T> >::findAnnotationSet((char *)this, anno_id);
377
378          if (v) 
379          {
380             v->clear();
381          }
382       }
383
384       unsigned size() const 
385       {
386          Container_t *v = NULL;
387          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
388
389          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
390
391          if (anno_id == -1) 
392          {
393             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
394                   FILE__, __LINE__, anno_name.c_str());
395             return 0;
396          }
397
398          //  ahhh the things we do to get rid of constness
399          const AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE> *thc = this; 
400          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE> *th  
401             = const_cast<AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE> *> (thc);
402
403          v = AnnotationSet<Container_t>::findAnnotationSet((char *)th, anno_id);
404
405          if (!v) 
406          {
407             //fprintf(stderr, "%s[%d]:  no annotation set for id %d\n", 
408             // FILE__, __LINE__, anno_id);
409             return 0;
410          }
411
412          return v->size();
413       }
414
415       //  so called getDataStructure in case we generalize beyond vectors for annotations
416
417       std::vector<T> &getDataStructure() 
418       {
419          // use with caution since this function will assert upon failure 
420          // (it has no way to return errors)
421          // when in doubt, check size() first.
422
423          Container_t *v = NULL;
424          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
425
426          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
427
428          if (anno_id == -1) 
429          {
430             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
431                   FILE__, __LINE__, anno_name.c_str());
432             assert(0);
433          }
434
435          v = AnnotationSet<Container_t>::findAnnotationSet((char *)this, anno_id);
436
437          if (!v) 
438          {
439             if (NULL == (v = initAnnotations())) 
440             {
441                fprintf(stderr, "%s[%d]:  failed to init annotations here\n", 
442                      FILE__, __LINE__);
443                assert(0);
444             }
445          }
446
447          return *v;
448       }
449
450       T &getAnnotation(unsigned index) const
451       {
452          Container_t *v = NULL;
453          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
454
455          int anno_id = getOrCreateAnnotationType(anno_name, typeid(T).name());
456          
457          if (anno_id == -1) 
458          {
459             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
460                   FILE__, __LINE__, anno_name.c_str());
461             assert(0);
462          }
463
464          //  ahhh the things we do to get rid of constness
465          const AnnotatableCommon<T, ANNOTATION_NAME_T,  SERIALIZABLE> *thc = this; 
466          AnnotatableCommon<T, ANNOTATION_NAME_T,  SERIALIZABLE> *th  
467             = const_cast<AnnotatableCommon<T, ANNOTATION_NAME_T,  SERIALIZABLE> *> (thc);
468
469          v = AnnotationSet<Container_t>::findAnnotationSet((char *)th, anno_id);
470
471          if (!v) 
472          {
473             fprintf(stderr, "%s[%d]:  cannot find annotation set for anno type %s\n", 
474                   FILE__, __LINE__, anno_name.c_str());
475
476             v = AnnotationSet<Container_t>::getAnnotationSet((char *)th, anno_id);
477          }
478
479          assert(v);
480
481          if (index >= v->size()) 
482          {
483             fprintf(stderr, "%s[%d]:  FIXME:  index = %d -- size = %d\n", 
484                   FILE__, __LINE__, index, v->size());
485          }
486
487          assert(index < v->size());
488          return (*v)[index];
489       }
490
491       T &operator[](unsigned index) const {return getAnnotation(index);}
492 };
493
494 template <class T, class ANNOTATION_NAME_T, 
495          bool SERIALIZABLE = false, 
496          annotation_implementation_t IMPL = anno_impl_static_sparse>
497 class Annotatable : public AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>
498 {
499    public:
500       Annotatable(SerializerBase *serializer) :
501          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>(serializer)
502       {}
503
504       Annotatable() :
505          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
506       {}
507
508       ~Annotatable() 
509       {}
510
511       Annotatable(const Annotatable<T, ANNOTATION_NAME_T, SERIALIZABLE, IMPL> &/*src*/) :
512          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
513       {/*hrm deep copy here or no?*/}
514
515
516 };
517
518 template <class T, class ANNOTATION_NAME_T, bool SERIALIZABLE>
519 class Annotatable<T, ANNOTATION_NAME_T, SERIALIZABLE, anno_impl_static_dense> : public AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>
520 {
521    private:
522
523       typedef typename std::vector<T> Container_t;
524       Container_t *annotations_;
525
526    public:
527
528       Annotatable(SerializerBase *serializer) :
529          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>(serializer)
530       {}
531
532       Annotatable() :
533          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
534       {}
535
536       ~Annotatable() 
537       {}
538
539       Annotatable(const Annotatable<T, ANNOTATION_NAME_T, SERIALIZABLE, anno_impl_static_dense> &/*src*/) :
540          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
541       {/*hrm deep copy here or no?*/}
542
543       Container_t *initAnnotations()
544       {
545          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
546
547          int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, 
548                typeid(T).name());
549
550          if (anno_id == -1) 
551          {
552             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
553                   FILE__, __LINE__, anno_name.c_str());
554             return NULL;
555          }
556
557          annotations_ = AnnotationSet<Container_t>::getAnnotationSet((char *)this, anno_id);
558
559          if (annotations_) 
560          {
561             return annotations_;
562          }
563
564          if (!annotations_) 
565          {
566             fprintf(stderr, "%s[%d]:  malloc problem\n", FILE__, __LINE__);
567             abort();
568             return NULL;
569          }
570
571          return annotations_;
572       }
573
574       bool addAnnotation(T it)
575       {
576          if (!annotations_) 
577          {
578             if (NULL == initAnnotations()) 
579             {
580                fprintf(stderr, "%s[%d]:  bad annotation type\n", FILE__, __LINE__);
581                return false;
582             }
583          }
584
585          if (!annotations_) 
586          {
587             fprintf (stderr, "%s[%d]:  initAnnotations failed\n", FILE__, __LINE__);
588             return false;
589          }
590
591          annotations_->push_back(it);
592
593 #if defined (cap_serialization)
594          if (SERIALIZABLE) 
595          {
596
597             fprintf(stderr, "%s[%d]:  serializing annotation here for %s\n", 
598                   FILE__, __LINE__, anno_name.c_str());
599
600             SerializerBase *sd_bin = getSDAnno(anno_name);
601
602             if (!sd_bin) 
603             {
604                //fprintf(stderr, "%s[%d]:  ERROR:  no serializer listed for type %s, have:\n",
605                 //     FILE__, __LINE__, anno_name.c_str());
606                //dumpSDAnno();
607
608                fprintf(stderr, "%s[%d]:  ERROR:  no serializer listed for type %s\n",
609                      FILE__, __LINE__, anno_name.c_str());
610
611                return false;
612             }
613
614             if (!gtranslate_w_err(sd_bin, /*(Serializable &)*/ it, NULL)) 
615             {
616                fprintf(stderr, "%s[%d]:  gtranslate_w_err failed\n", FILE__, __LINE__);
617                return false;
618             }
619
620             fprintf(stderr, "%s[%d]:  \tserialized annotation here for %s\n", 
621                   FILE__, __LINE__, anno_name.c_str());
622          }
623 #endif
624          return true;
625       }
626
627       unsigned size() const 
628       {
629          if (!annotations_) return 0;
630          return annotations_->size();
631       }
632
633       T &getAnnotation(unsigned index) const
634       {
635          if (!annotations_) 
636          {
637             fprintf(stderr, "%s[%d]:  FATAL:  bad usage, check size before calling\n",
638                   FILE__, __LINE__);
639             abort();
640          }
641
642          if (index >= annotations_->size()) 
643          {
644             fprintf(stderr, "%s[%d]:  FATAL:  bad usage, check size before calling\n",
645                   FILE__, __LINE__);
646             abort();
647          }
648
649          return (*annotations_)[index];
650       }
651
652       T &operator[](unsigned index) const {return getAnnotation(index);}
653 };
654
655 template <class T, class ANNOTATION_NAME_T, bool SERIALIZABLE>
656 class Annotatable<T, ANNOTATION_NAME_T, SERIALIZABLE, anno_impl_local_dense> : public AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>
657 {
658    private:
659       typedef typename std::vector<T> Container_t;
660       Container_t *annotations_;
661
662    public:
663       Annotatable(SerializerBase *serializer) :
664          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>(serializer)
665       {}
666
667       Annotatable() :
668          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
669       {}
670
671       ~Annotatable() 
672       {}
673
674       Annotatable(const Annotatable<T, ANNOTATION_NAME_T, SERIALIZABLE, anno_impl_local_dense> &/*src*/) :
675          AnnotatableCommon<T, ANNOTATION_NAME_T, SERIALIZABLE>()
676       {/*hrm deep copy here or no?*/}
677
678       Container_t *initAnnotations()
679       {
680          std::string anno_name = typeid(ANNOTATION_NAME_T).name();
681
682          int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, typeid(T).name());
683          
684          if (anno_id == -1) 
685          {
686             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
687                   FILE__, __LINE__, anno_name.c_str());
688             return NULL;
689          }
690
691          annotations_ = new Container_t;
692
693          if (!annotations_) 
694          {
695             fprintf(stderr, "%s[%d]:  malloc problem\n", FILE__, __LINE__);
696             abort();
697             return NULL;
698          }
699
700          return annotations_;
701       }
702
703       bool addAnnotation(T it)
704       {
705          if (!annotations_) 
706          {
707             if (!initAnnotations()) 
708             {
709                fprintf(stderr, "%s[%d]:  failed to init annotations\n", FILE__, __LINE__);
710                return false;
711             }
712          }
713
714          annotations_->push_back(it);
715          return true;
716       }
717
718       unsigned size() const 
719       {
720          if (!annotations_) 
721          {
722             //  This is legal if we have not created the vector yet. 
723             //  The vector is created when we add the first annotation
724             return 0;
725          }
726
727          return annotations_->size();
728       }
729
730       T &getAnnotation(unsigned index) const
731       {
732          if (!annotations_) 
733          {
734             fprintf(stderr, "%s[%d]:  FATAL:  bad usage, check size before calling\n",
735                   FILE__, __LINE__);
736             abort();
737          }
738
739          if (index >= annotations_->size()) 
740          {
741             fprintf(stderr, "%s[%d]:  FATAL:  bad usage, check size before calling\n",
742                   FILE__, __LINE__);
743             abort();
744          }
745
746          return (*annotations_)[index];
747       }
748
749       T &operator[](unsigned index) const {return getAnnotation(index);}
750 };
751
752 #if 0
753 template <class S, class T, annotation_implementation_t IMPL = anno_impl_static_sparse >
754 class ImplSpecializeHelper {
755    public:
756       ImplSpecializeHelper() {}
757       ~ImplSpecializeHelper() {}
758       bool annotate(S *obj, T &anno, std::string anno_name) 
759       {
760          assert(obj);
761
762          char *tobj = (char *) obj;
763          std::vector<T> *v = NULL;
764
765          int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, typeid(T).name());
766
767          if (-1 == anno_id) 
768          {
769             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
770                   FILE__, __LINE__, anno_name.c_str());
771             return false;
772          }
773
774          fprintf(stderr, "%s[%d]: about to try to getAnnotationSet for id %d\n", 
775                FILE__, __LINE__, anno_id);
776
777          v = AnnotationSet<std::vector<T> >::getAnnotationSet(tobj, anno_id);
778
779          if (!v) 
780          {
781             fprintf(stderr, "%s[%d]:  failed to init annotations here\n", 
782                   FILE__, __LINE__);
783             assert(0);
784          }
785
786          v->push_back(anno);
787          return true;
788       }
789
790       std::vector<T> *getAnnotations(S *obj, std::string anno_name) 
791       {
792          //  does not allocate anything, should return NULL if there are none
793          assert(obj);
794          char *tobj = (char *) obj;
795          std::vector<T> *v = NULL;
796
797          int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, typeid(T).name());
798
799          if (-1 == anno_id) 
800          {
801             fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
802                   FILE__, __LINE__, anno_name.c_str());
803             return false;
804          }
805
806          v = AnnotationSet<std::vector<T> >::findAnnotationSet(tobj, anno_id);
807
808          return v;
809       }
810 };
811 #endif
812
813 template <class S, class T>
814 bool annotate(S *obj, T &anno, std::string anno_name)
815 {
816    assert(obj);
817
818    char *tobj = (char *) obj;
819    std::vector<T> *v = NULL;
820
821    int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, typeid(T).name());
822
823    if (-1 == anno_id) 
824    {
825       fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
826             FILE__, __LINE__, anno_name.c_str());
827       return false;
828    }
829
830    v = AnnotationSet<std::vector<T> >::getAnnotationSet(tobj, anno_id);
831
832    if (!v) 
833    {
834       fprintf(stderr, "%s[%d]:  failed to init annotations here\n", 
835             FILE__, __LINE__);
836       assert(0);
837    }
838
839    v->push_back(anno);
840    return true;
841 }
842
843
844 template <class S, class T>
845 std::vector<T> *getAnnotations(S *obj, std::string anno_name)
846 {
847    //  does not allocate anything, should return NULL if there are none
848    assert(obj);
849    char *tobj = (char *) obj;
850    std::vector<T> *v = NULL;
851
852    int anno_id = AnnotatableBase::getOrCreateAnnotationType(anno_name, typeid(T).name());
853
854    if (-1 == anno_id) 
855    {
856       fprintf(stderr, "%s[%d]:  failed to getOrCreateAnnotation type %s\n", 
857             FILE__, __LINE__, anno_name.c_str());
858       return false;
859    }
860
861    v = AnnotationSet<std::vector<T> >::findAnnotationSet(tobj, anno_id);
862
863    return v;
864 }
865
866 #endif