CLAM-Development  1.4.0
DynamicTypeMacros.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 
23 #include "Assert.hxx"
24 #include "TypeInfoStd.hxx"
25 #include "StaticBool.hxx"
26 #include <typeinfo>
27 
29 // Reimplementation using chained template methods
30 // These macros expand functions in the concrete (derived) class of DynamicType.
31 //
32 // Related macros:
33 // * DYNAMIC_TYPE
34 // * DYNAMIC_TYPE_USING_INTERFACE
35 // * DYN_ATTRIBUTE
36 // * DYN_CONTAINER_ATTRIBUTE
38 
39 
40 #define __COMMON_DYNAMIC_TYPE(CLASS_NAME,N) \
41 public: \
42  virtual const char* GetClassName() const { \
43  return #CLASS_NAME; \
44  }\
45  enum { eNumAttr= N }; \
46  CLAM::DynamicType& GetDynamicTypeCopy(const bool shareData=false, const bool deep=false) const\
47  { \
48  return *new CLASS_NAME(*this, shareData, deep); \
49  }\
50 protected: \
51  void MandatoryInit()\
52  {\
53  static bool staticTableInitialized = false;\
54  static TAttr staticTypeDescTable[N+1];\
55  typeDescTable = staticTypeDescTable;\
56  if(!staticTableInitialized)\
57  {\
58  staticTableInitialized=true;\
59  InformAll();\
60  }else \
61  {\
62  maxAttrSize = N ? (typeDescTable[N-1].offset+typeDescTable[N-1].size) : 0;\
63  }\
64  } \
65 public: \
66  \
67  const std::type_info & GetTypeId(unsigned n) const \
68  { \
69  return GetChainedTypeId((AttributePosition<0>*)NULL,n); \
70  } \
71  \
72  template <typename Visitor> \
73  void VisitAll (Visitor & visitor) { \
74  VisitChainedAttr((AttributePosition<0>*)NULL, visitor); \
75  } \
76  \
77  void RemoveAll () { \
78  RemoveChainedAttr((AttributePosition<0>*)NULL); \
79  } \
80  \
81  void AddAll () { \
82  AddChainedAttr((AttributePosition<0>*)NULL); \
83  } \
84 private: \
85  \
86  void InformAll () { \
87  InformChainedAttr((AttributePosition<0>*)NULL); \
88  DynamicType::InformAll(); \
89  } \
90 protected: \
91  \
92  virtual void StoreDynAttributes(CLAM::Storage & s) const { \
93  StoreChainedAttr((AttributePosition<0>*)NULL,s); \
94  } \
95  \
96  virtual void LoadDynAttributes(CLAM::Storage & s) { \
97  AddAll(); \
98  UpdateData(); \
99  LoadChainedAttr((AttributePosition<0>*)NULL,s); \
100  UpdateData(); \
101  } \
102 private: \
103  template <unsigned int NAttrib> \
104  class AttributePosition : public CLAM::DynamicType::AttributePositionBase<NAttrib> { \
105  public: \
106  typedef StaticBool<!(NAttrib>=N)> InboundsCheck; \
107  }; \
108  \
111  template <unsigned int NAttrib> \
112  void CheckAttribute (StaticFalse*inRange,AttributePosition<NAttrib>*a) { \
113  AttributePosition<(NAttrib)-1>* previous; \
114  previous->CompilationError_AttributePositionOutOfBounds(); \
115  }\
116  \
120  template <unsigned int NAttrib> \
121  void CheckAttribute (StaticTrue*inRange,AttributePosition<NAttrib>*a) { \
122  a->CompilationError_AttributeNotDefined(); \
123  }\
124  \
125  /* \
126  template <unsigned int NAttrib, typename Visitor> \
127  void VisitChainedAttr (AttributePosition<NAttrib>*a, Visitor & visitor) { \
128  CheckAttribute ((AttributePosition<NAttrib>::InboundsCheck*)NULL, \
129  (AttributePosition<NAttrib>*)NULL); \
130  }*/\
131  \
132  template <unsigned int NAttrib> \
133  void RemoveChainedAttr (AttributePosition<NAttrib>*a) { \
134  typedef typename AttributePosition<NAttrib>::InboundsCheck InboundsCheck; \
135  CheckAttribute ((InboundsCheck*)NULL, \
136  (AttributePosition<NAttrib>*)NULL); \
137  }\
138  \
139  template <unsigned int NAttrib> \
140  void AddChainedAttr (AttributePosition<NAttrib>*a) { \
141  typedef typename AttributePosition<NAttrib>::InboundsCheck InboundsCheck; \
142  CheckAttribute ((InboundsCheck*)NULL, \
143  (AttributePosition<NAttrib>*)NULL); \
144  }\
145  \
146  template <unsigned int NAttrib> \
147  void InformChainedAttr (AttributePosition<NAttrib>*a) { \
148  typedef typename AttributePosition<NAttrib>::InboundsCheck InboundsCheck; \
149  CheckAttribute ((InboundsCheck*)NULL, \
150  (AttributePosition<NAttrib>*)NULL); \
151  }\
152  \
153  template <unsigned int NAttrib> \
154  void StoreChainedAttr (AttributePosition<NAttrib>*a,CLAM::Storage & s) const { \
155  typedef typename AttributePosition<NAttrib>::InboundsCheck InboundsCheck; \
156  CheckAttribute ((InboundsCheck*)NULL, \
157  (AttributePosition<NAttrib>*)NULL); \
158  }\
159  \
160  template <unsigned int NAttrib> \
161  void LoadChainedAttr (AttributePosition<NAttrib>*a,CLAM::Storage & s) { \
162  typedef typename AttributePosition<NAttrib>::InboundsCheck InboundsCheck; \
163  CheckAttribute ((InboundsCheck*)NULL, \
164  (AttributePosition<NAttrib>*)NULL); \
165  }\
166 private: \
167  \
168  template <typename Visitor> \
169  void VisitChainedAttr (AttributePosition<N>*, Visitor & visitor) { \
170  } \
171  \
172  void RemoveChainedAttr (AttributePosition<N>*) { \
173  } \
174  \
175  void AddChainedAttr (AttributePosition<N>*) { \
176  } \
177  \
178  void InformChainedAttr (AttributePosition<N>*) { \
179  } \
180  \
181  void StoreChainedAttr (AttributePosition<N>*pos, CLAM::Storage &s) const { \
182  } \
183  \
184  void LoadChainedAttr (AttributePosition<N>*pos, CLAM::Storage &s) { \
185  } \
186  \
187  const std::type_info & GetChainedTypeId(AttributePosition<N>*pos, unsigned n) const \
188  { \
189  return typeid(void); \
190  } \
191 
192 
193 
194 #define DYNAMIC_TYPE(CLASS_NAME, N)\
195 public: \
196  CLASS_NAME() : CLAM::DynamicType(N)\
197  {\
198  MandatoryInit(); \
199  DefaultInit();\
200  }\
201  CLASS_NAME(const CLASS_NAME& prototype, const bool shareData=false, const bool deep=true)\
202  : CLAM::DynamicType(prototype, shareData, deep) { \
203  CopyInit(prototype);\
204  }\
205  __COMMON_DYNAMIC_TYPE(CLASS_NAME,N); \
206 
207 
208 #define DYNAMIC_TYPE_USING_INTERFACE(CLASS_NAME, N, INTERFACE_NAME)\
209 public: \
210  CLASS_NAME() : INTERFACE_NAME(N)\
211  {\
212  MandatoryInit(); \
213  DefaultInit();\
214  }\
215  CLASS_NAME(const CLASS_NAME& prototype, const bool shareData=false, const bool deep=true)\
216  : INTERFACE_NAME(prototype, shareData, deep) { \
217  CopyInit(prototype); \
218  }\
219  __COMMON_DYNAMIC_TYPE(CLASS_NAME,N); \
220 
221 
222 #define __COMMON_DYN_ATTRIBUTE(N,ACCESS,TYPE,NAME) \
223 private: \
224  static void* _new_##NAME(void* p)\
225  {\
226  return static_cast<void*> (new(p) TYPE());\
227  }\
228  \
229  static void* _new_##NAME(void* pos, void* orig)\
230  {\
231  TYPE* typed = static_cast< TYPE*>(orig);\
232  return static_cast<void*>( new(pos) TYPE(*typed) );\
233  }\
234  \
235  static void _destructor_##NAME(void* p)\
236  {\
237  typedef TYPE __Ty;\
238  static_cast<__Ty*>(p)->~__Ty();\
239  }\
240  \
241 \
242  struct {} CLAM_compile_time_error_Duplicated_Attribute_Index_##N;\
243  \
244 ACCESS: \
245  inline TYPE& Get##NAME() const {\
246  CLAM_DEBUG_ASSERT((N<numAttr), \
247  "There are more registered Attributes than the number " \
248  "defined in the DYNAMIC_TYPE macro.");\
249  CLAM_ASSERT(ExistAttr(N),\
250  "You are trying to access attribute " #NAME \
251  " that is not Added or not Updated.");\
252  CLAM_DEBUG_ASSERT(data, \
253  "No data allocated for the accessed dynamic type:" #NAME );\
254  void *p=data + dynamicTable[N].offs;\
255  return *static_cast<TYPE*>(p); \
256  }\
257  \
258 \
259  inline void Set##NAME(TYPE const & arg) {\
260  CLAM_DEBUG_ASSERT((N<numAttr), \
261  "There are more registered Attributes than the number " \
262  "defined in the DYNAMIC_TYPE macro.");\
263  CLAM_ASSERT(ExistAttr(N),\
264  "You are trying to access attribute " #NAME \
265  " that is not Added or not Updated.");\
266  CLAM_DEBUG_ASSERT(data, \
267  "No data allocated for the accessed dynamic type." #NAME );\
268  void* orig = (void*)(&arg);\
269  char* pos = data+dynamicTable[N].offs;\
270  _destructor_##NAME(pos);\
271  _new_##NAME(pos, orig);\
272  }\
273  inline void Add##NAME() {\
274  AddAttr_(N, sizeof(TYPE));\
275  }\
276  template <typename Visitor> \
277  inline void Visit##NAME(Visitor & visitor) { \
278  if (Has##NAME()) \
279  visitor.Accept(#NAME,Get##NAME()); \
280  }\
281  inline void Remove##NAME() { \
282  RemoveAttr_(N); \
283  }\
284  inline bool Has##NAME() const { \
285  return ExistAttr(N); \
286  } \
287 private: \
288  inline void Inform##NAME() {\
289  InformTypedAttr_(N, #NAME, sizeof(TYPE), #TYPE, false, _new_##NAME, _new_##NAME, _destructor_##NAME, (TYPE*)0);\
290  }\
291  static inline int GetSize##NAME() { return sizeof(TYPE); } \
292  static inline const char* GetType##NAME() { return #TYPE; } \
293  static inline int GetId##NAME() { return N;}\
294 public: \
295  /*inline TYPE* Get##NAME##Vector(unsigned n) { return Get_##TYPE##Vector(n); }*/ \
296 private: \
297  template <typename Visitor> \
298  void VisitChainedAttr(AttributePosition<N>*, Visitor & visitor) { \
299  Visit##NAME(visitor); \
300  VisitChainedAttr((AttributePosition<(N)+1>*)NULL, visitor); \
301  } \
302  void RemoveChainedAttr(AttributePosition<N>*) { \
303  Remove##NAME(); \
304  RemoveChainedAttr((AttributePosition<(N)+1>*)NULL); \
305  } \
306  void AddChainedAttr(AttributePosition<N>*) { \
307  Add##NAME(); \
308  AddChainedAttr((AttributePosition<(N)+1>*)NULL); \
309  } \
310  void InformChainedAttr(AttributePosition<N>*) { \
311  Inform##NAME(); \
312  InformChainedAttr((AttributePosition<(N)+1>*)NULL); \
313  } \
314  void StoreChainedAttr(AttributePosition<N>*, CLAM::Storage & s) const { \
315  Store##NAME(s); \
316  StoreChainedAttr((AttributePosition<(N)+1>*)NULL,s); \
317  } \
318  void LoadChainedAttr(AttributePosition<N>*, CLAM::Storage & s) { \
319  Load##NAME(s); \
320  LoadChainedAttr((AttributePosition<(N)+1>*)NULL,s); \
321  } \
322  const std::type_info & GetChainedTypeId(AttributePosition<N>*, unsigned n) const { \
323  if (n==N) return typeid(TYPE); \
324  return GetChainedTypeId((AttributePosition<(N)+1>*)NULL,n); \
325  } \
326 
327 
328 #define DYN_ATTRIBUTE(N,ACCESS,TYPE,NAME) \
329  __COMMON_DYN_ATTRIBUTE(N,ACCESS,TYPE,NAME) \
330 protected: \
331  void Store##NAME(CLAM::Storage & s) const { \
332  if (Has##NAME()) { \
333  StoreAttribute((CLAM::TypeInfo<TYPE >::StorableAsLeaf*)NULL, s, Get##NAME(), #NAME); \
334  } \
335  } \
336  bool Load##NAME(CLAM::Storage & s) { \
337  TYPE obj; \
338  if (!LoadAttribute((CLAM::TypeInfo<TYPE >::StorableAsLeaf*)NULL, s, obj, #NAME)) { \
339  Remove##NAME(); \
340  return false; \
341  } \
342  Set##NAME(obj); \
343  return true; \
344  } \
345 ACCESS: \
346 
347 
348 #define DYN_CONTAINER_ATTRIBUTE(N,ACCESS,TYPE,NAME,ENAME) \
349  __COMMON_DYN_ATTRIBUTE(N,ACCESS,TYPE,NAME) \
350 protected: \
351  void Store##NAME(CLAM::Storage & s) const { \
352  if (Has##NAME()) { \
353  StoreIterableAttribute(s, Get##NAME(), #NAME, #ENAME); \
354  } \
355  } \
356  bool Load##NAME(CLAM::Storage & s) { \
357  Add##NAME(); \
358  UpdateData(); \
359  if (! LoadIterableAttribute(s, Get##NAME(), #NAME, #ENAME)) { \
360  Remove##NAME(); \
361  return false; \
362  } \
363  return true; \
364  } \
365 ACCESS: \
366 
367 
368