CLAM-Development  1.4.0
DynamicType.cxx
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 #include "DynamicType.hxx"
23 #include <cstdio>
24 #include <cstring>
25 #include <string>
26 
27 #include <iostream> // needed for Debug() method
28 #include <fstream> // idem
29 #include <list> // needed in UpdateData
30 
31 #include "XMLStorage.hxx"
32 
33 #include "ErrDynamicType.hxx"
34 
35 // IMPORTANT: this next flag will slow all the dynamic types mechanisms
36 // So it can only be set (defined) when developing, testing or maintaining
37 // dynamic types.
38 
39 // #define CLAM_EXTRA_CHECKS_ON_DT
40 
41 // Anyway this flag should be defined in the project/makefile of the test.
42 
43 namespace CLAM {
44 
46 // Construction/Destruction
48 
49 DynamicType::DynamicType(const int nAttr)
50 {
51  // the typeDescTable is initialized into the concrete dynamic type.
52  // because we want that table to be static.(one per concrete class)
53  numAttr = nAttr;
54  dynamicTable = new TDynInfo[numAttr + 1];
55  dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false; // global modification flags.
56  for ( unsigned i=0; i < numAttr; i++)
57  {
58  dynamicTable[i].offs = -1;
59  dynamicTable[i].hasBeenAdded = false;
60  dynamicTable[i].hasBeenRemoved = false;
61  }
62  numActiveAttr = 0;
63  data = 0;
64  dataSize = 0;
66  maxAttrSize = 0; // initialized in method InformAll()
67  bOwnsItsMemory = true;
68  bPreAllocateAllAttributes = false;
70 }
71 
72 DynamicType::DynamicType(const DynamicType& prototype, const bool shareData, const bool deepCopy=true)
73 // no need of checking the concret class of the prototype, because always is called the the copy-constructor of
74 // the concrete class. So if you try to pass a prototype of a different concrete class the compiler will complain!
75 {
76  typeDescTable = prototype.typeDescTable;
77 
78  numActiveAttr = 0;
79  data = 0;
80  dynamicTable=0;
81  dataSize = 0;
83  bPreAllocateAllAttributes = false;
84 
85  if (prototype.IsInstanciate())
86  {
87  if (!shareData)
88  if (deepCopy)
89  SelfDeepCopy(prototype);
90  else
91  SelfShallowCopy(prototype);
92  else
93  SelfSharedCopy(prototype);
94  }
95  else // !prototype.Instanciate()
96  SelfCopyPrototype(prototype);
97 }
98 
100 {
101  typeDescTable = prototype.typeDescTable;
102 
103  numActiveAttr = 0;
104  data = 0;
105  dynamicTable=0;
106  dataSize = 0;
107  allocatedDataSize = 0;
108  bPreAllocateAllAttributes = prototype.bPreAllocateAllAttributes;
109 
110 
111  if (prototype.IsInstanciate())
112  SelfDeepCopy(prototype);
113  else
114  SelfCopyPrototype(prototype);
115 
116 # ifdef CLAM_EXTRA_CHECKS_ON_DT
118 # endif //CLAM_EXTRA_CHECKS_ON_DT
119 }
120 
121 
123 {
124  RemoveAllMem();
125 }
126 
127 void DynamicType::RemoveAllMem()
128 {
129 # ifdef CLAM_EXTRA_CHECKS_ON_DT
131 # endif //CLAM_EXTRA_CHECKS_ON_DT
132 
133  if (data && bOwnsItsMemory)
134  {
135  for (unsigned i=0; i<numAttr; i++)
136  if (AttrHasData(i))
137  {
138  t_destructor dest = typeDescTable[i].destructObj;
139  dest (data+dynamicTable[i].offs);
140  }
141  }
142  if (data)
143  {
144  delete [] data;
145  }
146  if (dynamicTable) {
148  if (DynTableRefCounter() == 0)
149  delete [] dynamicTable;
150  }
151 }
152 
153 
154 void DynamicType::InformAttr_(unsigned val, const char* name, unsigned size, const char* type, const bool isPtr,
155  const t_new fnew, const t_new_copy fcopy, const t_destructor fdestr)
156 {
157  CLAM_ASSERT(val<numAttr,
158  "There are more registered Attributes than the "
159  "number defined in DYN_CLASS_TABLE macro.");
160  CLAM_ASSERT(fnew, "in DT: a dynamic attribute don't have default-constructor !");
161  CLAM_ASSERT(fcopy, "in DT: a dynamic attribute don't have copy constructor !");
162 
163  strcpy(typeDescTable[val].id, name);
164  strcpy(typeDescTable[val].type, type);
165  typeDescTable[val].isPointer = isPtr;
166  typeDescTable[val].size = size;
167  // default value. This field is used in UpdateData in Fixed offsets mode.
168  typeDescTable[val].offset = -1;
169  // references to creation/destruction fuctions of the type/class
170  typeDescTable[val].newObj = fnew;
171  typeDescTable[val].newObjCopy = fcopy;
172  typeDescTable[val].destructObj = fdestr;
173  // informative flags:
174  // flags that will be set at the AddTypedAttr_
175  // (the overloaded function that calls this one)
176  typeDescTable[val].isComponent = false;
177  typeDescTable[val].isStorable = false;
178  typeDescTable[val].isDynamicType = false;
179 
180 }
182 // Main memory management methods: AddAttr_, RemoveAttr_ and UpdateData
183 
184 
185 void DynamicType::AddAttr_ (const unsigned val, const unsigned size)
186 {
187  // first we check if there is need to adding the attribute
188  TDynInfo &inf = dynamicTable[val];
189 
190  if (inf.hasBeenAdded)
191  return;
192 
193  if (inf.hasBeenRemoved)
194  {
195  inf.hasBeenRemoved = false;
196  ++numActiveAttr;
197  dataSize += size;
198 
199  // check if we can unset the global some-removed flag.
201  for (unsigned int j=0; j<numAttr; j++) {
202  if (dynamicTable[j].hasBeenRemoved) {
204  break;
205  }
206  }
207 # ifdef CLAM_EXTRA_CHECKS_ON_DT
209 # endif //CLAM_EXTRA_CHECKS_ON_DT
210 
211  return;
212  }
213  if (AttrHasData(val)) return;
214 
215  // At this point, the actual attribute-adding is necessary
216 
217  if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
218  { // so create a new dynamicTable
220  TDynInfo *oldTable = dynamicTable;
221  dynamicTable = new TDynInfo[numAttr + 1];
222  memcpy(dynamicTable, oldTable, sizeof(TDynInfo)*(numAttr+1));
224  // dont delete the oldTable: it's still used by at least its prototype
225  }
226 
227  ++numActiveAttr;
228  dataSize += size;
229  dynamicTable[val].hasBeenAdded = true;
230  dynamicTable[numAttr].hasBeenAdded = true; //this is a global (for all attribute) flag that means that Update is necessary
231  // at this point the data and dynamicTable may contain gaps,
232  // but they will be compacted at Update() time.
233 
234 # ifdef CLAM_EXTRA_CHECKS_ON_DT
236 # endif //CLAM_EXTRA_CHECKS_ON_DT
237 
238 }
239 
241 void DynamicType::RemoveAttr_(const unsigned i)
242 {
243  TDynInfo &inf = dynamicTable[i];
244 
245  if (inf.hasBeenRemoved) return;
246 
247  if (inf.hasBeenAdded)
248  {
249  inf.hasBeenAdded=false;
250  --numActiveAttr;
252 
253  // check if we can unset the global some-added flag.
255  for (unsigned int j=0; j<numAttr; j++) {
256  if (dynamicTable[j].hasBeenAdded) {
258  break;
259  }
260  }
261 # ifdef CLAM_EXTRA_CHECKS_ON_DT
263 # endif //CLAM_EXTRA_CHECKS_ON_DT
264 
265  return;
266  }
267  if (!AttrHasData(i) || !data) return;
268 
269  // at this point the actual attribute-deletion has to be done.
270  // but the actual deletion will take place at UpdateData() time.
271 
272  if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
273  { // so create a new dynamicTable
275  TDynInfo *oldTable = dynamicTable;
276  dynamicTable = new TDynInfo[numAttr + 1];
277  memcpy(dynamicTable, oldTable, sizeof(TDynInfo)*(numAttr+1));
279  // dont delete the oldTable: it's still used by at least its prototype
280  }
281 
282  --numActiveAttr;
285  dynamicTable[numAttr].hasBeenRemoved = 1; // global flag that means Update necessary;
286 
287 # ifdef CLAM_EXTRA_CHECKS_ON_DT
289 # endif //CLAM_EXTRA_CHECKS_ON_DT
290 
291 }
292 
293 
295 // return whether some update has been made.
297 {
298 
299 # ifdef CLAM_EXTRA_CHECKS_ON_DT
301 # endif //CLAM_EXTRA_CHECKS_ON_DT
302 
303  if (!bOwnsItsMemory ) // if !bOwnsItsMemory then it will own it from that point.
304  {
305  BeMemoryOwner();
306  return true;
307  }
308 
309  // if no AddXXX or RemoveXXX has been done then the update is not necessary
310  if (!dynamicTable[numAttr].hasBeenAdded && !dynamicTable[numAttr].hasBeenRemoved)
311  return false;
312 
313  // at this point. some Add / Remove has been done.
314 
315  if (bPreAllocateAllAttributes) dataSize = maxAttrSize;
316 
318  // this "shrinkThreshold" constant decides when to
319  // reallocate (and shrink or _compact_) memory
320  {
321  UpdateDataByShrinking();
322  return true;
324  // it's the first that dataSize reach the maximum. (probably by the use of bPreAllocatedAllAttr flag.
325  // now the offsets will be taken from the static table
326  {
327  UpdateDataGoingToPreAllocatedMode();
328  return true;
329 
331  {
332  // in this PreAllocatedMode the attr. offsets are fixed by the static table.
333  UpdateDataInPreAllocatedMode();
334  return true;
335  }
336 
337  // else: memory has increasead or the amount decreased is bigger than the threshold
338  // so do it in the STANDARD MODE (reallocate and compact memory)
339  UpdateDataByStandardMode();
340 
341 # ifdef CLAM_EXTRA_CHECKS_ON_DT
343 # endif //CLAM_EXTRA_CHECKS_ON_DT
344 
345  return true;
346 }
348 
349 void DynamicType::BeMemoryOwner()
350 {
351  bOwnsItsMemory = true;
352  TDynInfo *originalTable = dynamicTable;
353  char* originalData = data;
354  data = new char[dataSize];
355  if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
356  { // so create a new dynamicTable
358  dynamicTable = new TDynInfo[numAttr + 1];
359  memcpy(dynamicTable, originalTable, sizeof(TDynInfo)*(numAttr+1));
361  // dont delete the oldTable: it's still used by at least its prototype
362  }
363 
364  unsigned offs=0;
365  for(unsigned i=0; i<numAttr; i++)
366  if ((AttrHasData(i) && !dynamicTable[i].hasBeenRemoved) || dynamicTable[i].hasBeenAdded) // owhterwise doesn't need allocation
367  {
368 
369  t_new_copy fnewcp=typeDescTable[i].newObjCopy;
370  fnewcp(data+offs, originalData+originalTable[i].offs);
371  dynamicTable[i].offs = offs;
373  offs += typeDescTable[i].size;
374  }
375  else
376  {
377  dynamicTable[i].hasBeenRemoved = false;
378  dynamicTable[i].offs = -1;
379  }
380 
383 
384 
385  }
386 
390 void DynamicType::UpdateDataByShrinking()
391 {
392 
393  std::list< std::pair<int,int> > attrList(numAttr);
394  std::list< std::pair<int,int> >::iterator it;
395 
396  unsigned int i=0;
397  for (it=attrList.begin(); it!=attrList.end(); it++)
398  {
399  (*it).first = dynamicTable[i].offs;
400  (*it).second = i++;
401  }
402 
403  attrList.sort();
404 
405  unsigned offs=0;
406  unsigned j; // ordered attribute indes
407  for (it=attrList.begin(); it!=attrList.end(); it++)
408  {
409  j = (*it).second;
410  if (AttrHasData(j) && !dynamicTable[j].hasBeenRemoved)
411  {
412  if (unsigned(dynamicTable[j].offs) != offs) // only move data if necessary
413  {
414  t_new_copy newc = typeDescTable[j].newObjCopy;
415  t_destructor dest = typeDescTable[j].destructObj;
418  char* aux = new char[typeDescTable[j].size];
419  newc(aux,data+dynamicTable[j].offs);
420  dest(data+dynamicTable[j].offs);
421  newc(data+offs,aux);
422  dest(aux);
423  delete [] aux;
424  dynamicTable[j].offs = offs;
425  }
426  offs += typeDescTable[j].size;
427  }
428  else if (AttrHasData(j) && dynamicTable[j].hasBeenRemoved)
429  {
430  t_destructor dest = typeDescTable[j].destructObj;
431  dest (data+dynamicTable[j].offs);
432 
433  dynamicTable[j].offs = -1;
434  dynamicTable[j].hasBeenRemoved = false;
435  }
436  }
437  // now it's time for the new (added) attributes
438  for (i=0; i<numAttr; i++)
439  {
440  if (dynamicTable[i].hasBeenAdded)
441  {
442  t_new fnew=typeDescTable[i].newObj;
443  fnew(data+offs);
444  dynamicTable[i].offs = offs;
445  offs += typeDescTable[i].size;
446  dynamicTable[i].hasBeenAdded = false;
447  }
448  }
449 
452 }
453 
454 // STANDARD MODE (reallocate and compact memory)
455 void DynamicType::UpdateDataByStandardMode ()
456 {
457  char* olddata = data;
458  data = new char[dataSize];
459 
460  unsigned offs=0;
461  for (unsigned int i=0; i<numAttr; i++)
462  {
463  TDynInfo & inf = dynamicTable[i];
464  if (AttrHasData(i))
465  {
466  if (dynamicTable[i].hasBeenRemoved)
467  {
468  t_destructor dest = typeDescTable[i].destructObj;
469  dest (olddata+inf.offs);
470  inf.hasBeenRemoved = false;
471  inf.offs = -1;
472  }
473  else
474  {
475  t_new_copy newc = typeDescTable[i].newObjCopy;
476  t_destructor dest = typeDescTable[i].destructObj;
477  newc(data+offs,olddata+inf.offs);
478  dest(olddata+inf.offs);
479  inf.offs = offs;
480  offs += typeDescTable[i].size;
481  }
482  }
483  else // !AttrHasData(i)
484  {
485  if (inf.hasBeenAdded)
486  {
487  t_new fnew=typeDescTable[i].newObj;
488  fnew(data+offs);
489  inf.hasBeenAdded = false;
490  inf.offs = offs;
491  offs += typeDescTable[i].size;
492  }
493 
494  }
495 
496  } // for
497 
498 
499  delete [] olddata;
502 }
503 
504 void DynamicType::UpdateDataGoingToPreAllocatedMode()
505 {
506  // the last reallocation:
507  char* olddata = data;
508  data = new char[maxAttrSize];
509  unsigned int i;
510  // from now one we'll use these pre-fixed offsets.
511  // the copy of attributes:
512  for (i=0; i<numAttr; i++)
513  {
514  TDynInfo & inf = dynamicTable[i];
515  int offs = typeDescTable[i].offset;
516  if (AttrHasData(i))
517  {
518  if (dynamicTable[i].hasBeenRemoved)
519  {
520  t_destructor dest = typeDescTable[i].destructObj;
521  dest (olddata+inf.offs);
522  inf.hasBeenRemoved = false;
523  inf.offs = -1;
524  }
525  else
526  {
527  t_new_copy newc = typeDescTable[i].newObjCopy;
528  t_destructor dest = typeDescTable[i].destructObj;
529 
530  newc(data+offs,olddata+inf.offs);
531  dest(olddata+inf.offs);
532  inf.offs = offs;
533  }
534  }
535  else // !AttrHasData(i)
536  {
537  if (inf.hasBeenAdded)
538  {
539  t_new fnew=typeDescTable[i].newObj;
540  fnew(data+offs);
541  inf.hasBeenAdded = false;
542  inf.offs = offs;
543  }
544  }
545 
546  } // for each attribute.
547 
548  delete [] olddata;
551 
552 }
553 
554 void DynamicType::UpdateDataInPreAllocatedMode()
555 {
556  // now, no reallocation.
557  // we'll use these pre-fixed offsets.
558  // we need no attributes-copies. only creations and destructions:
559  for (unsigned int i=0; i<numAttr; i++)
560  {
561  TDynInfo & inf = dynamicTable[i];
562  int offs = typeDescTable[i].offset;
563  if (AttrHasData(i))
564  {
565  if (dynamicTable[i].hasBeenRemoved)
566  {
567  t_destructor dest = typeDescTable[i].destructObj;
568  dest (data+inf.offs);
569  inf.hasBeenRemoved = false;
570  inf.offs = -1;
571  }
572  // else leave the attribute in peace.
573  }
574  else // !AttrHasData(i)
575  {
576  if (inf.hasBeenAdded)
577  {
578  t_new fnew=typeDescTable[i].newObj;
579  fnew(data+offs);
580  inf.hasBeenAdded = false;
581  inf.offs = offs;
582  }
583  }
584 
585  } // for each attribute.
586 
588 
589 }
590 
592 // these methods are important to be inline. TODO: check if the compiler does it automatically
593 // or should be better move them to the .hxx
594 
596 {
597  return dynamicTable[numAttr].offs;
598 }
600 {
601  dynamicTable[numAttr].offs = 1; //at least the object that has created the table points to it.
602 }
603 
604 
605 
606 
607 
609 {
610  return --dynamicTable[numAttr].offs;
611 }
613 {
614  return ++dynamicTable[numAttr].offs;
615 }
616 
617 
619 // Component interface implementation
621 
623 {
624  DynamicType* selfCopy = &(GetDynamicTypeCopy(false,false));
625 
626  return selfCopy;
627 }
628 
629 
631 {
632  DynamicType* selfCopy = &(GetDynamicTypeCopy(false,true));
633 
634  return selfCopy;
635 };
636 
637 
638 void DynamicType::SelfCopyPrototype(const DynamicType &prototype)
639 {
640  RemoveAllMem(); // deletes all mem in data and calls de destructor of every object.
641 
642  numAttr = prototype.numAttr;
643  numActiveAttr = prototype.numActiveAttr;
644  dataSize = prototype.dataSize;
646  maxAttrSize = prototype.maxAttrSize;
647  dynamicTable = prototype.dynamicTable;
648  data=0;
649  bOwnsItsMemory=true;
650  bPreAllocateAllAttributes = prototype.bPreAllocateAllAttributes;
652 }
653 
654 void DynamicType::SelfSharedCopy(const DynamicType &prototype)
655 {
656  SelfCopyPrototype(prototype);
657 
658  data = prototype.data;
659 
660  bOwnsItsMemory = false;
661 }
662 
663 void DynamicType::SelfShallowCopy(const DynamicType &prototype)
664 {
665  CLAM_ASSERT(
666  !prototype.dynamicTable[prototype.numAttr].hasBeenAdded &&
667  !prototype.dynamicTable[prototype.numAttr].hasBeenRemoved,
668  "making a copy of a non-updated DT is not allowed since the copy share the same dynamic-info"
669  );
670  if (this==&prototype) return;
671 
672  SelfCopyPrototype(prototype);
673 
674  data = new char[allocatedDataSize];
675 
676  unsigned int i;
677  for (i = 0; i < numAttr; i++)
678  {
679  if (!ExistAttr(i)) continue;
680  void* pos = GetPtrToData_(i);
681  t_new_copy fcopy = typeDescTable[i].newObjCopy;
682  fcopy(pos, prototype.GetPtrToData_(i));
683  }
684 }
685 
686 void DynamicType::SelfDeepCopy(const DynamicType &prototype)
687 {
688  CLAM_ASSERT(
689  !prototype.dynamicTable[prototype.numAttr].hasBeenAdded &&
690  !prototype.dynamicTable[prototype.numAttr].hasBeenRemoved,
691  "making a copy of a non-updated DT is not allowed since the copy share the same dynamic-info"
692  );
693  if (this==&prototype) return;
694 
695  SelfCopyPrototype(prototype);
696 
697  data = new char[allocatedDataSize];
698 
699  // Copies (deepCopy) all the objects pointed by this dynamic type that derives from
700  // Component. Copies this object and then link the copy of this, with the
701  // children copies.
702  Component** copyChildren = new Component * [prototype.numAttr]; // could be done without a table if space efficency is needed
703  unsigned int i;
704  for (i = 0; i < numAttr; i++)
705  {
706  if (prototype.ExistAttr(i) && typeDescTable[i].isComponent && typeDescTable[i].isPointer)
707  copyChildren[i] = static_cast<Component*>(prototype.GetDataAsPtr_(i))->DeepCopy();
708  else
709  copyChildren[i] = 0;
710  }
711 
712  for (i = 0; i < numAttr; i++)
713  {
714  if (!ExistAttr(i)) continue;
715  void* pos = GetPtrToData_(i);
716  if(copyChildren[i])
717  SetDataAsPtr_(i, copyChildren[i]);
718  else
719  {
720  //now a nested object must be replaced. It maight be a pointer not registered as it.
721  //the nested object will be copied from the nested object at "this"
722  t_new_copy fcopy = typeDescTable[i].newObjCopy;
723  fcopy(pos, prototype.GetPtrToData_(i));
724  }
725  }
726  delete [] copyChildren;
727 }
728 
730 
732 {
733  SelfDeepCopy(source);
734 
735 # ifdef CLAM_EXTRA_CHECKS_ON_DT
737 # endif //CLAM_EXTRA_CHECKS_ON_DT
738 
739  return *this;
740 }
741 
742 
743 
745 // Developing aids methods: FullfilsInvariant and Debug
746 
748 {
749  if (!typeDescTable)
750  throw ErrDynamicType("in FullfilsInvariant: there's no typeDescTable. "
751  "The most likely thing is that the object is "
752  "created with a non-macro-expanded-constructor."
753  "In that case the constructor MUST call the"
754  "MandatoryInit() method (called from constructor). Check it !");
755 
756  if (!dynamicTable)
757  return;
758 
759  unsigned auxAllocatedSize=0;
760  bool someAdded = false, someRemoved = false;
761  int incData=0, decData=0;
762  bool *usedblock = new bool[allocatedDataSize];
763 
764  for (unsigned j=0; j<allocatedDataSize; j++) usedblock[j] = false;
765 
766  for (unsigned i=0; i<numAttr; i++)
767  {
768  TDynInfo & dyninfo = dynamicTable[i];
769 
770  // check state consistency.
771  if (dyninfo.hasBeenAdded && dyninfo.hasBeenRemoved)
772  throw ErrDynamicType("in FullfilsInvariant: an attribute has both Added & Removed flags set. Class: ", GetClassName() );
773 
774  if (dyninfo.hasBeenAdded) someAdded = true;
775  if (dyninfo.hasBeenRemoved) someRemoved = true;
776 
777  if (dyninfo.offs < -1)
778  throw ErrDynamicType("in FullfilsInvariant: a dynamic offset < -1");
779  if( !AttrHasData(i) && dyninfo.hasBeenRemoved)
780  throw ErrDynamicType(" in FullfilsInvariant: an attribute has\
781  no data (offs==-1) but do has the hasBeenRemoved flag set. Class: ", GetClassName() );
782 
783  if( AttrHasData(i) && dyninfo.hasBeenAdded)
784  throw ErrDynamicType(" in FullfilsInvariant: an attribute has\
785  data (offs>0) but do has the hasBeenAdded flag set. Class: ", GetClassName() );
786  // data size calculation
787  if (dyninfo.offs >= 0)
788  {
789  auxAllocatedSize += typeDescTable[i].size;
790  for (unsigned j=unsigned(dyninfo.offs); j<unsigned(dyninfo.offs+typeDescTable[i].size); j++)
791  if (usedblock[j]) throw ErrDynamicType("in FullfilsInvariant: overlaped area in data table");
792  else usedblock[j]=true;
793  }
794  if (AttrHasData(i))
795  {
796  if (dyninfo.hasBeenRemoved) decData += typeDescTable[i].size;
797  if (!data) throw ErrDynamicType("in FullfilsInvariant: An attr. has data but data==0");
798  }
799  else
800  if (dyninfo.hasBeenAdded) incData += typeDescTable[i].size;
801 
802  else if (dyninfo.offs != -1)
803  throw ErrDynamicType(" in FullfilsInvariant: attribute not informed with dynamic offset <> -1");
804 
805  }
806  if (!bPreAllocateAllAttributes) {
807  if (auxAllocatedSize+incData-decData != dataSize)
808  throw ErrDynamicType("in FullfilsInvariant: dataSize attribute is not consistent. Class: ", GetClassName() );
809  if (auxAllocatedSize + incData - decData != dataSize)
810  throw ErrDynamicType("in FullfilsInvariant: the dataSize is not well calculated. Class: ", GetClassName() );
811  }
812  if (auxAllocatedSize > allocatedDataSize)
813  throw ErrDynamicType("in FullfilsInvariant: allocatedDataSize attribute is not consistent. Class: ", GetClassName() );
814  if (dynamicTable[numAttr].hasBeenAdded != someAdded)
815  throw ErrDynamicType("in FullfilsInvariant: global 'hasBeenAdded' flag inconsistent. Class: ", GetClassName() );
816  if (dynamicTable[numAttr].hasBeenRemoved != someRemoved)
817  throw ErrDynamicType("in FullfilsInvariant: global 'hasBeenRemoved' flag inconsistent. Class: ", GetClassName() );
818 
819  delete[] usedblock;
820 }
821 
822 
823 void DynamicType::Debug() const
824 {
825  TAttr * attr = 0;
826  std::cout <<std::endl<<"Class Name: "<< GetClassName() << " at: " << this <<std::endl << "[#attr.], dyn_offs,statc_offs,name,type,{comp,dynType,ptr,strble},exist,size,Ptr"\
827  << std::endl << "------------------------------------------------------------------------------"<<std::endl;
828  std::cout << "{ size, allocatedSize, maxAttrsSize } = { " << dataSize << " , " << allocatedDataSize << " , "
829  << maxAttrSize << " }\n";
830  for (unsigned i=0; i<numAttr; i++)
831  {
832  TDynInfo & dyninf = dynamicTable[i];
833 
834  attr = &typeDescTable[i];
835  std::cout << std::endl;
836  if (dyninf.hasBeenAdded) std::cout << " A";
837  else std::cout << " -";
838  if (dyninf.hasBeenRemoved) std::cout << "R";
839  else std::cout << "-";
840 
841 
842  std::cout << " [" <<i<<"] ";
843 
844  std::cout << dyninf.offs << " , "<<attr->offset<<" , "<<attr->id<<" , "<<attr->type<<" , {"\
845  <<attr->isComponent<<","<<attr->isDynamicType<<","<<attr->isPointer<<","\
846  <<attr->isStorable<<"} , "<<ExistAttr(i)<<" , "<<attr->size\
847  <<" , ";
848  if(ExistAttr(i))
849  std::cout << GetPtrToData_(i);
850 
851  if(attr->isPointer && ExistAttr(i)) std::cout << " points -> " << GetDataAsPtr_(i);
852  }
853  std::cout<<std::endl;
854 
855  // Only dump when CLAM_USE_XML defined
856  #ifdef CLAM_USE_XML
857  XMLStorage::Dump(*this, GetClassName(), "Debug.xml");
858  #endif// CLAM_USE_XML
859 }
860 
861 }; //namespace CLAM
862