DynamicType.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "DynamicType.hxx"
00023 #include <cstdio>
00024 #include <cstring>
00025 #include <string>
00026 
00027 #include <iostream>  // needed for Debug() method
00028 #include <fstream>  // idem
00029 #include <list>    // needed in UpdateData 
00030 
00031 #include "XMLStorage.hxx"
00032 
00033 #include "ErrDynamicType.hxx"
00034 
00035 // IMPORTANT: this next flag will slow all the dynamic types mechanisms
00036 // So it can only be set (defined) when developing, testing or maintaining
00037 // dynamic types.
00038 
00039 // #define CLAM_EXTRA_CHECKS_ON_DT
00040 
00041 // Anyway this flag should be defined in the project/makefile of the test.
00042 
00043 namespace CLAM {
00044 
00046 // Construction/Destruction
00048 
00049 DynamicType::DynamicType(const int nAttr)
00050 {
00051         // the typeDescTable is initialized into the concrete dynamic type. 
00052         // because we want that table to be static.(one per concrete class)
00053         numAttr = nAttr;
00054         dynamicTable = new TDynInfo[numAttr + 1];
00055         dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false; // global modification flags.
00056         for ( unsigned i=0; i < numAttr; i++)
00057         {
00058                 dynamicTable[i].offs = -1;
00059                 dynamicTable[i].hasBeenAdded = false;
00060                 dynamicTable[i].hasBeenRemoved = false;
00061         }
00062         numActiveAttr = 0;
00063         data = 0;
00064         dataSize = 0;
00065         allocatedDataSize = 0;
00066         maxAttrSize = 0;                // initialized in method InformAll()
00067         bOwnsItsMemory = true;
00068         bPreAllocateAllAttributes = false;
00069         InitDynTableRefCounter();
00070 }
00071 
00072 DynamicType::DynamicType(const DynamicType& prototype, const bool shareData, const bool deepCopy=true)
00073 // no need of checking the concret class of the prototype, because always is called the the copy-constructor of
00074 // the concrete class. So if you try to pass a prototype of a different concrete class the compiler will complain!
00075 {
00076         typeDescTable = prototype.typeDescTable;
00077 
00078         numActiveAttr = 0;
00079         data = 0;
00080         dynamicTable=0;
00081         dataSize = 0;
00082         allocatedDataSize = 0;
00083         bPreAllocateAllAttributes = false;
00084 
00085         if (prototype.IsInstanciate())
00086         {
00087                 if (!shareData)
00088                         if (deepCopy)
00089                                 SelfDeepCopy(prototype);
00090                         else
00091                                 SelfShallowCopy(prototype);
00092                 else
00093                         SelfSharedCopy(prototype);
00094         }
00095         else //  !prototype.Instanciate()
00096                 SelfCopyPrototype(prototype);
00097 }
00098 
00099 DynamicType::DynamicType(const DynamicType& prototype)
00100 {
00101         typeDescTable = prototype.typeDescTable;
00102 
00103         numActiveAttr = 0;
00104         data = 0;
00105         dynamicTable=0;
00106         dataSize = 0;
00107         allocatedDataSize = 0;
00108         bPreAllocateAllAttributes = prototype.bPreAllocateAllAttributes;
00109 
00110 
00111         if (prototype.IsInstanciate())
00112                 SelfDeepCopy(prototype);
00113         else
00114                 SelfCopyPrototype(prototype);
00115 
00116 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00117                 FullfilsInvariant();
00118 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00119 }
00120 
00121 
00122 DynamicType::~DynamicType()
00123 {
00124         RemoveAllMem();
00125 }
00126 
00127 void DynamicType::RemoveAllMem()
00128 {
00129 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00130                 FullfilsInvariant();
00131 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00132 
00133         if (data && bOwnsItsMemory)
00134         {
00135                 for (unsigned i=0; i<numAttr; i++) 
00136                         if (AttrHasData(i))
00137                         {
00138                                 t_destructor dest = typeDescTable[i].destructObj;
00139                                 dest (data+dynamicTable[i].offs);
00140                         }
00141         }
00142         if (data) 
00143         {
00144                 delete [] data;
00145         }
00146         if (dynamicTable) {
00147                 DecrementDynTableRefCounter();
00148                 if (DynTableRefCounter() == 0)
00149                         delete [] dynamicTable;
00150         }
00151 }
00152 
00153 
00154 void DynamicType::InformAttr_(unsigned val, const char* name, unsigned size, const char* type, const bool isPtr,
00155                             const t_new fnew, const t_new_copy fcopy, const t_destructor fdestr)
00156 {
00157         CLAM_ASSERT(val<numAttr, 
00158                 "There are more registered Attributes than the "
00159                 "number defined in DYN_CLASS_TABLE macro.");
00160         CLAM_ASSERT(fnew, "in DT: a dynamic attribute don't have default-constructor !");
00161         CLAM_ASSERT(fcopy, "in DT: a dynamic attribute don't have copy constructor !");
00162 
00163         strcpy(typeDescTable[val].id, name);
00164         strcpy(typeDescTable[val].type, type);
00165         typeDescTable[val].isPointer = isPtr;
00166         typeDescTable[val].size = size;
00167         // default value. This field is used in UpdateData in Fixed offsets mode.
00168         typeDescTable[val].offset = -1;  
00169         // references to creation/destruction fuctions of the type/class
00170         typeDescTable[val].newObj = fnew;
00171         typeDescTable[val].newObjCopy = fcopy;
00172         typeDescTable[val].destructObj = fdestr;
00173         // informative flags:
00174         // flags that will be set at the AddTypedAttr_ 
00175         // (the overloaded function that calls this one)
00176         typeDescTable[val].isComponent = false;
00177         typeDescTable[val].isStorable = false;
00178         typeDescTable[val].isDynamicType = false;
00179 
00180 }
00182 // Main memory management methods: AddAttr_, RemoveAttr_ and UpdateData
00183 
00184 
00185 void DynamicType::AddAttr_ (const unsigned val, const unsigned size)
00186 {
00187         // first we check if there is need to adding the attribute
00188         TDynInfo &inf = dynamicTable[val];
00189 
00190         if (inf.hasBeenAdded) 
00191                 return;
00192 
00193         if (inf.hasBeenRemoved)
00194         {
00195                 inf.hasBeenRemoved = false;
00196                 ++numActiveAttr;
00197                 dataSize += size;
00198 
00199                 // check if we can unset the global some-removed flag.
00200                 dynamicTable[numAttr].hasBeenRemoved = false;
00201                 for (unsigned int j=0; j<numAttr; j++) {
00202                         if (dynamicTable[j].hasBeenRemoved) {
00203                                 dynamicTable[numAttr].hasBeenRemoved = true;
00204                                 break;
00205                         }
00206                 }
00207 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00208                 FullfilsInvariant();
00209 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00210 
00211                 return;
00212         }
00213         if (AttrHasData(val)) return;
00214         
00215         // At this point, the actual attribute-adding is necessary
00216 
00217         if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
00218         {  // so create a new dynamicTable
00219                 DecrementDynTableRefCounter();
00220                 TDynInfo *oldTable = dynamicTable;
00221                 dynamicTable = new TDynInfo[numAttr + 1];
00222                 memcpy(dynamicTable, oldTable, sizeof(TDynInfo)*(numAttr+1));
00223                 InitDynTableRefCounter();
00224                 // dont delete the oldTable: it's still used by at least its prototype
00225         }
00226 
00227         ++numActiveAttr;
00228         dataSize += size;
00229         dynamicTable[val].hasBeenAdded = true;
00230         dynamicTable[numAttr].hasBeenAdded = true; //this is a global (for all attribute) flag that means that Update is necessary
00231         // at this point the data and dynamicTable may contain gaps, 
00232         // but they will be compacted at Update() time.
00233 
00234 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00235                 FullfilsInvariant();
00236 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00237 
00238 }
00239 
00241 void DynamicType::RemoveAttr_(const unsigned i)
00242 {
00243         TDynInfo &inf = dynamicTable[i];
00244 
00245         if (inf.hasBeenRemoved) return;
00246 
00247         if (inf.hasBeenAdded) 
00248         {
00249                 inf.hasBeenAdded=false;
00250                 --numActiveAttr;
00251                 dataSize -= typeDescTable[i].size;
00252                 
00253                 // check if we can unset the global some-added flag.
00254                 dynamicTable[numAttr].hasBeenAdded = false;
00255                 for (unsigned int j=0; j<numAttr; j++) {
00256                         if (dynamicTable[j].hasBeenAdded) {
00257                                 dynamicTable[numAttr].hasBeenAdded = true;
00258                                 break;
00259                         }
00260                 }
00261 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00262                 FullfilsInvariant();
00263 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00264 
00265                 return;
00266         }
00267         if (!AttrHasData(i) || !data) return;
00268 
00269         // at this point the actual attribute-deletion has to be done.
00270         // but the actual deletion will take place at UpdateData() time.
00271         
00272         if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
00273         {  // so create a new dynamicTable
00274                 DecrementDynTableRefCounter();
00275                 TDynInfo *oldTable = dynamicTable;
00276                 dynamicTable = new TDynInfo[numAttr + 1];
00277                 memcpy(dynamicTable, oldTable, sizeof(TDynInfo)*(numAttr+1));
00278                 InitDynTableRefCounter();
00279                 // dont delete the oldTable: it's still used by at least its prototype
00280         }
00281 
00282         --numActiveAttr;
00283         dataSize -= typeDescTable[i].size;
00284         dynamicTable[i].hasBeenRemoved = 1;
00285         dynamicTable[numAttr].hasBeenRemoved = 1; // global flag that means Update necessary;
00286 
00287 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00288                 FullfilsInvariant();
00289 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00290 
00291 }
00292 
00293 
00295 // return whether some update has been made.
00296 bool DynamicType::UpdateData()
00297 {
00298 
00299 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00300                 FullfilsInvariant();
00301 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00302 
00303         if (!bOwnsItsMemory ) // if !bOwnsItsMemory then it will own it from that point.
00304         {
00305                 BeMemoryOwner();
00306                 return true;
00307         }
00308 
00309         // if no AddXXX or RemoveXXX has been done then the update is not necessary
00310         if (!dynamicTable[numAttr].hasBeenAdded && !dynamicTable[numAttr].hasBeenRemoved) 
00311                 return false; 
00312 
00313         // at this point. some Add / Remove has been done. 
00314         
00315         if (bPreAllocateAllAttributes) dataSize = maxAttrSize;
00316         
00317         if (dataSize <= allocatedDataSize && int(allocatedDataSize-dataSize) > shrinkThreshold)  
00318                 // this "shrinkThreshold" constant  decides when to 
00319                 // reallocate (and shrink or _compact_) memory
00320         {
00321                 UpdateDataByShrinking();
00322                 return true;
00323         } else if (dataSize==maxAttrSize && allocatedDataSize<maxAttrSize) 
00324                 // it's the first that dataSize reach the maximum. (probably by the use of bPreAllocatedAllAttr flag.
00325                 // now the offsets will be taken from the static table 
00326         {
00327                 UpdateDataGoingToPreAllocatedMode();
00328                 return true;
00329 
00330         } else if (dataSize==maxAttrSize && dataSize<=allocatedDataSize) 
00331         {
00332                 // in this PreAllocatedMode the attr. offsets are fixed by the static table.
00333                 UpdateDataInPreAllocatedMode();
00334                 return true;
00335         }
00336         
00337         // else: memory has increasead or the amount decreased is bigger than the threshold
00338         // so do it in the STANDARD MODE (reallocate and compact memory)
00339         UpdateDataByStandardMode();
00340 
00341 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00342                 FullfilsInvariant();
00343 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00344 
00345         return true;
00346 }
00348 
00349 void DynamicType::BeMemoryOwner()
00350 {
00351                 bOwnsItsMemory = true;
00352                 TDynInfo *originalTable = dynamicTable;
00353                 char* originalData = data;
00354                 data = new char[dataSize];
00355                 if (DynTableRefCounter() > 1) // then this object is different from the prototye that gave its shape
00356                 {  // so create a new dynamicTable
00357                         DecrementDynTableRefCounter();
00358                         dynamicTable = new TDynInfo[numAttr + 1];
00359                         memcpy(dynamicTable, originalTable, sizeof(TDynInfo)*(numAttr+1));
00360                         InitDynTableRefCounter();
00361                         // dont delete the oldTable: it's still used by at least its prototype
00362                 }
00363 
00364                 unsigned offs=0;
00365                 for(unsigned i=0; i<numAttr; i++)
00366                         if ((AttrHasData(i) && !dynamicTable[i].hasBeenRemoved) || dynamicTable[i].hasBeenAdded) // owhterwise doesn't need allocation
00367                         {
00368 
00369                                 t_new_copy fnewcp=typeDescTable[i].newObjCopy;
00370                                 fnewcp(data+offs, originalData+originalTable[i].offs);
00371                                 dynamicTable[i].offs = offs;
00372                                 dynamicTable[i].hasBeenAdded = dynamicTable[i].hasBeenRemoved = false;
00373                                 offs += typeDescTable[i].size;
00374                         }
00375                         else 
00376                         {       
00377                                 dynamicTable[i].hasBeenRemoved = false;
00378                                 dynamicTable[i].offs = -1;
00379                         }
00380         
00381                 allocatedDataSize = dataSize;
00382                 dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false;
00383         
00384         
00385         }
00386 
00390 void DynamicType::UpdateDataByShrinking()
00391 {
00392         
00393                 std::list< std::pair<int,int> > attrList(numAttr);  
00394                 std::list< std::pair<int,int> >::iterator it;
00395 
00396                 unsigned int i=0;
00397                 for (it=attrList.begin(); it!=attrList.end(); it++)
00398                 {
00399                         (*it).first = dynamicTable[i].offs;
00400                         (*it).second = i++;
00401                 }
00402 
00403                 attrList.sort();
00404 
00405                 unsigned offs=0;
00406                 unsigned j; // ordered attribute indes
00407                 for (it=attrList.begin(); it!=attrList.end(); it++)
00408                 {
00409                         j = (*it).second;
00410                         if (AttrHasData(j) && !dynamicTable[j].hasBeenRemoved)
00411                         {
00412                                 if (unsigned(dynamicTable[j].offs) != offs) // only move data if necessary
00413                                 {
00414                                         t_new_copy   newc  = typeDescTable[j].newObjCopy;
00415                                         t_destructor dest  = typeDescTable[j].destructObj;
00418                                         char* aux = new char[typeDescTable[j].size];
00419                                         newc(aux,data+dynamicTable[j].offs);
00420                                         dest(data+dynamicTable[j].offs);
00421                                         newc(data+offs,aux);
00422                                         dest(aux);
00423                                         delete [] aux;
00424                                         dynamicTable[j].offs = offs;
00425                                 }
00426                                 offs += typeDescTable[j].size;
00427                         }
00428                         else if (AttrHasData(j) && dynamicTable[j].hasBeenRemoved)
00429                         {
00430                                 t_destructor dest = typeDescTable[j].destructObj;
00431                                 dest (data+dynamicTable[j].offs);
00432                                 
00433                                 dynamicTable[j].offs = -1;
00434                                 dynamicTable[j].hasBeenRemoved = false;
00435                         }
00436                 } 
00437                 // now it's time for the new (added) attributes
00438                 for (i=0; i<numAttr; i++)
00439                 {
00440                         if (dynamicTable[i].hasBeenAdded)
00441                         {
00442                                 t_new fnew=typeDescTable[i].newObj;
00443                                 fnew(data+offs);
00444                                 dynamicTable[i].offs = offs;
00445                                 offs += typeDescTable[i].size;
00446                                 dynamicTable[i].hasBeenAdded = false;
00447                         }
00448                 }
00449 
00450                 dynamicTable[numAttr].hasBeenRemoved = false;
00451                 dynamicTable[numAttr].hasBeenAdded = false;
00452 }
00453 
00454 //  STANDARD MODE (reallocate and compact memory)
00455 void DynamicType::UpdateDataByStandardMode ()
00456 {
00457         char* olddata = data;
00458         data = new char[dataSize];
00459 
00460         unsigned offs=0;
00461         for (unsigned int i=0; i<numAttr; i++)
00462         {
00463                 TDynInfo & inf = dynamicTable[i];
00464                 if (AttrHasData(i)) 
00465                 {
00466                         if (dynamicTable[i].hasBeenRemoved) 
00467                         {
00468                                 t_destructor dest = typeDescTable[i].destructObj;
00469                                 dest (olddata+inf.offs);
00470                                 inf.hasBeenRemoved = false;
00471                                 inf.offs = -1;
00472                         }
00473                         else 
00474                         {
00475                                 t_new_copy   newc = typeDescTable[i].newObjCopy;
00476                                 t_destructor dest = typeDescTable[i].destructObj;
00477                                 newc(data+offs,olddata+inf.offs);
00478                                 dest(olddata+inf.offs);
00479                                 inf.offs = offs;
00480                                 offs += typeDescTable[i].size;
00481                         }
00482                 }
00483                 else  // !AttrHasData(i)
00484                 {
00485                         if (inf.hasBeenAdded)
00486                         {
00487                                 t_new fnew=typeDescTable[i].newObj;
00488                                 fnew(data+offs);
00489                                 inf.hasBeenAdded = false;
00490                                 inf.offs = offs;
00491                                 offs += typeDescTable[i].size;
00492                         }
00493 
00494                 }
00495                                 
00496         } // for
00497 
00498                 
00499         delete [] olddata;
00500         allocatedDataSize = dataSize;
00501         dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false;
00502 }
00503 
00504 void DynamicType::UpdateDataGoingToPreAllocatedMode()
00505 {
00506         // the last reallocation:
00507         char* olddata = data;
00508         data = new char[maxAttrSize];
00509         unsigned int i;
00510         // from now one we'll use these pre-fixed offsets.
00511         // the copy of attributes:
00512         for (i=0; i<numAttr; i++)
00513         {
00514                 TDynInfo & inf = dynamicTable[i];
00515                 int offs = typeDescTable[i].offset;
00516                 if (AttrHasData(i)) 
00517                 {
00518                         if (dynamicTable[i].hasBeenRemoved) 
00519                         {
00520                                 t_destructor dest = typeDescTable[i].destructObj;
00521                                 dest (olddata+inf.offs);
00522                                 inf.hasBeenRemoved = false;
00523                                 inf.offs = -1;
00524                         }
00525                         else 
00526                         {
00527                                 t_new_copy   newc = typeDescTable[i].newObjCopy;
00528                                 t_destructor dest = typeDescTable[i].destructObj;
00529                                 
00530                                 newc(data+offs,olddata+inf.offs);
00531                                 dest(olddata+inf.offs);
00532                                 inf.offs = offs;
00533                         }
00534                 }
00535                 else  // !AttrHasData(i)
00536                 {
00537                         if (inf.hasBeenAdded)
00538                         {
00539                                 t_new fnew=typeDescTable[i].newObj;
00540                                 fnew(data+offs);
00541                                 inf.hasBeenAdded = false;
00542                                 inf.offs = offs;
00543                         }
00544                 }
00545                                 
00546         } // for each attribute.
00547 
00548         delete [] olddata;
00549         allocatedDataSize = dataSize;
00550         dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false;
00551         
00552 }
00553 
00554 void DynamicType::UpdateDataInPreAllocatedMode()
00555 {
00556         // now, no reallocation.
00557         // we'll use these pre-fixed offsets. 
00558         // we need no attributes-copies. only creations and destructions:
00559         for (unsigned int i=0; i<numAttr; i++)
00560         {
00561                 TDynInfo & inf = dynamicTable[i];
00562                 int offs = typeDescTable[i].offset;
00563                 if (AttrHasData(i)) 
00564                 {
00565                         if (dynamicTable[i].hasBeenRemoved) 
00566                         {
00567                                 t_destructor dest = typeDescTable[i].destructObj;
00568                                 dest (data+inf.offs);
00569                                 inf.hasBeenRemoved = false;
00570                                 inf.offs = -1;
00571                         }
00572                         // else leave the attribute in peace.
00573                 }
00574                 else  // !AttrHasData(i)
00575                 {
00576                         if (inf.hasBeenAdded)
00577                         {
00578                                 t_new fnew=typeDescTable[i].newObj;
00579                                 fnew(data+offs);
00580                                 inf.hasBeenAdded = false;
00581                                 inf.offs = offs;
00582                         }
00583                 }
00584                                 
00585         } // for each attribute.
00586 
00587         dynamicTable[numAttr].hasBeenAdded = dynamicTable[numAttr].hasBeenRemoved = false;
00588         
00589 }
00590 
00592 // these methods are important to be inline. TODO: check if the compiler does it automatically
00593 // or should be better move them to the .hxx
00594 
00595 int DynamicType::DynTableRefCounter()
00596 {
00597         return dynamicTable[numAttr].offs;
00598 }
00599 void DynamicType::InitDynTableRefCounter()
00600 {
00601         dynamicTable[numAttr].offs = 1;       //at least the object that has created the table points to it.
00602 }
00603 
00604 
00605 
00606 
00607 
00608 int DynamicType::DecrementDynTableRefCounter()
00609 {
00610         return --dynamicTable[numAttr].offs;
00611 }
00612 int DynamicType::IncrementDynTableRefCounter()
00613 {
00614         return ++dynamicTable[numAttr].offs;
00615 }
00616 
00617 
00619 // Component interface implementation
00621 
00622 Component* DynamicType::ShallowCopy() const
00623 {
00624         DynamicType* selfCopy = &(GetDynamicTypeCopy(false,false));
00625 
00626         return selfCopy;
00627 }
00628 
00629 
00630 Component* DynamicType::DeepCopy() const
00631 {       
00632         DynamicType* selfCopy = &(GetDynamicTypeCopy(false,true));
00633 
00634         return selfCopy;
00635 };
00636 
00637 
00638 void DynamicType::SelfCopyPrototype(const DynamicType &prototype)
00639 {
00640         RemoveAllMem(); // deletes all mem in data and calls de destructor of every object.
00641 
00642         numAttr = prototype.numAttr;
00643         numActiveAttr = prototype.numActiveAttr;
00644         dataSize = prototype.dataSize;
00645         allocatedDataSize = prototype.allocatedDataSize;
00646         maxAttrSize = prototype.maxAttrSize;
00647         dynamicTable = prototype.dynamicTable;
00648         data=0;
00649         bOwnsItsMemory=true;
00650         bPreAllocateAllAttributes = prototype.bPreAllocateAllAttributes;
00651         IncrementDynTableRefCounter();
00652 }
00653 
00654 void DynamicType::SelfSharedCopy(const DynamicType &prototype)
00655 {
00656         SelfCopyPrototype(prototype);
00657 
00658         data = prototype.data;
00659 
00660         bOwnsItsMemory = false;
00661 }
00662 
00663 void DynamicType::SelfShallowCopy(const DynamicType &prototype)
00664 {
00665         CLAM_ASSERT( 
00666                 !prototype.dynamicTable[prototype.numAttr].hasBeenAdded &&      
00667                 !prototype.dynamicTable[prototype.numAttr].hasBeenRemoved,
00668                 "making a copy of a non-updated DT is not allowed since the copy share the same dynamic-info"
00669         );
00670         if (this==&prototype) return;
00671 
00672         SelfCopyPrototype(prototype);
00673 
00674         data = new char[allocatedDataSize];
00675 
00676         unsigned int i;
00677         for (i = 0; i < numAttr; i++)
00678         {
00679                 if (!ExistAttr(i)) continue;
00680                 void* pos = GetPtrToData_(i);
00681                 t_new_copy fcopy = typeDescTable[i].newObjCopy;
00682                 fcopy(pos, prototype.GetPtrToData_(i));
00683         }
00684 }
00685 
00686 void DynamicType::SelfDeepCopy(const DynamicType &prototype)
00687 {
00688         CLAM_ASSERT( 
00689                 !prototype.dynamicTable[prototype.numAttr].hasBeenAdded &&      
00690                 !prototype.dynamicTable[prototype.numAttr].hasBeenRemoved,
00691                 "making a copy of a non-updated DT is not allowed since the copy share the same dynamic-info"
00692         );
00693         if (this==&prototype) return;
00694                 
00695         SelfCopyPrototype(prototype);
00696 
00697         data = new char[allocatedDataSize];
00698 
00699         // Copies (deepCopy) all the objects pointed by this dynamic type that derives from
00700         // Component. Copies this object and then link the copy of this, with the
00701         // children copies.
00702         Component** copyChildren = new Component * [prototype.numAttr];   // could be done without a table if space efficency is needed
00703         unsigned int i;
00704         for (i = 0; i < numAttr; i++)
00705         {
00706                 if (prototype.ExistAttr(i) && typeDescTable[i].isComponent && typeDescTable[i].isPointer)
00707                         copyChildren[i] = static_cast<Component*>(prototype.GetDataAsPtr_(i))->DeepCopy();
00708                 else
00709                         copyChildren[i] = 0;
00710         }
00711 
00712         for (i = 0; i < numAttr; i++)
00713         {
00714                 if (!ExistAttr(i)) continue;
00715                 void* pos = GetPtrToData_(i);
00716                 if(copyChildren[i])
00717                         SetDataAsPtr_(i, copyChildren[i]);
00718                 else
00719                 {
00720                         //now a nested object must be replaced. It maight be a pointer not registered as it.
00721                         //the nested object will be copied from the nested object at "this"
00722                         t_new_copy fcopy = typeDescTable[i].newObjCopy;
00723                         fcopy(pos, prototype.GetPtrToData_(i));
00724                 }
00725         }
00726         delete [] copyChildren;
00727 }
00728 
00730 
00731 DynamicType& DynamicType::operator=(const DynamicType& source)
00732 {
00733         SelfDeepCopy(source);
00734 
00735 #       ifdef CLAM_EXTRA_CHECKS_ON_DT
00736                 FullfilsInvariant();
00737 #       endif //CLAM_EXTRA_CHECKS_ON_DT
00738 
00739         return *this;
00740 }
00741 
00742 
00743 
00745 // Developing aids methods: FullfilsInvariant and Debug
00746 
00747 void DynamicType::FullfilsInvariant() const
00748 {
00749         if (!typeDescTable) 
00750                 throw ErrDynamicType("in FullfilsInvariant: there's no typeDescTable. "
00751                                                          "The most likely thing is that the object      is "
00752                                                          "created with a non-macro-expanded-constructor."
00753                                                          "In that case the constructor MUST call the"
00754                                                          "MandatoryInit() method (called from constructor). Check it !");
00755 
00756         if (!dynamicTable)
00757                 return;
00758 
00759         unsigned auxAllocatedSize=0;
00760         bool someAdded = false, someRemoved = false;
00761         int incData=0, decData=0;
00762         bool *usedblock = new bool[allocatedDataSize];
00763         
00764         for (unsigned j=0; j<allocatedDataSize; j++) usedblock[j] = false;
00765 
00766         for (unsigned i=0; i<numAttr; i++)
00767         {
00768                 TDynInfo & dyninfo = dynamicTable[i];
00769                 
00770                 // check state consistency.
00771                 if (dyninfo.hasBeenAdded && dyninfo.hasBeenRemoved) 
00772                         throw ErrDynamicType("in FullfilsInvariant: an attribute has both Added & Removed flags set. Class: ", GetClassName() );
00773 
00774                 if (dyninfo.hasBeenAdded) someAdded = true;
00775                 if (dyninfo.hasBeenRemoved) someRemoved = true;
00776 
00777                 if (dyninfo.offs < -1) 
00778                         throw ErrDynamicType("in FullfilsInvariant: a dynamic offset < -1");
00779                 if( !AttrHasData(i) && dyninfo.hasBeenRemoved)  
00780                         throw ErrDynamicType(" in FullfilsInvariant: an attribute has\
00781                                 no data (offs==-1) but do has the hasBeenRemoved flag set. Class: ", GetClassName() );
00782                 
00783                 if( AttrHasData(i) && dyninfo.hasBeenAdded)  
00784                         throw ErrDynamicType(" in FullfilsInvariant: an attribute has\
00785                                 data (offs>0) but do has the hasBeenAdded flag set. Class: ", GetClassName() );
00786                 // data size calculation
00787                 if (dyninfo.offs >= 0) 
00788                 {
00789                         auxAllocatedSize += typeDescTable[i].size;
00790                         for (unsigned j=unsigned(dyninfo.offs); j<unsigned(dyninfo.offs+typeDescTable[i].size); j++)
00791                                 if (usedblock[j]) throw ErrDynamicType("in FullfilsInvariant: overlaped area in data table");
00792                                 else usedblock[j]=true;
00793                 }
00794                 if (AttrHasData(i)) 
00795                 {
00796                         if (dyninfo.hasBeenRemoved) decData += typeDescTable[i].size;
00797                         if (!data) throw ErrDynamicType("in FullfilsInvariant: An attr. has data but data==0");
00798                 }
00799                 else 
00800                         if (dyninfo.hasBeenAdded) incData += typeDescTable[i].size;
00801                 
00802                 else if (dyninfo.offs != -1) 
00803                         throw ErrDynamicType(" in FullfilsInvariant: attribute not informed with dynamic offset <> -1");
00804 
00805         }
00806         if (!bPreAllocateAllAttributes) {
00807                 if (auxAllocatedSize+incData-decData != dataSize) 
00808                         throw ErrDynamicType("in FullfilsInvariant: dataSize attribute is not consistent. Class: ", GetClassName() );
00809                 if (auxAllocatedSize + incData - decData != dataSize)
00810                         throw ErrDynamicType("in FullfilsInvariant: the dataSize is not well calculated. Class: ", GetClassName() );
00811         }
00812         if (auxAllocatedSize > allocatedDataSize) 
00813                 throw ErrDynamicType("in FullfilsInvariant: allocatedDataSize attribute is not consistent. Class: ", GetClassName() );
00814         if (dynamicTable[numAttr].hasBeenAdded != someAdded) 
00815                 throw ErrDynamicType("in FullfilsInvariant: global 'hasBeenAdded' flag inconsistent. Class: ", GetClassName() );
00816         if (dynamicTable[numAttr].hasBeenRemoved != someRemoved) 
00817                 throw ErrDynamicType("in FullfilsInvariant: global 'hasBeenRemoved' flag inconsistent. Class: ", GetClassName() );
00818         
00819         delete[] usedblock;
00820 }
00821 
00822 
00823 void DynamicType::Debug() const
00824 {
00825         TAttr * attr = 0;
00826         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"\
00827                 << std::endl << "------------------------------------------------------------------------------"<<std::endl;
00828         std::cout << "{ size, allocatedSize, maxAttrsSize } = { " << dataSize << " , " << allocatedDataSize << " , "
00829                         << maxAttrSize << " }\n";
00830         for (unsigned i=0; i<numAttr; i++)
00831         {
00832                 TDynInfo & dyninf = dynamicTable[i];
00833 
00834                 attr = &typeDescTable[i];
00835                 std::cout << std::endl;
00836                 if (dyninf.hasBeenAdded) std::cout << " A";
00837                 else std::cout << " -";
00838                 if (dyninf.hasBeenRemoved) std::cout << "R";
00839                 else std::cout << "-";
00840                 
00841 
00842                 std::cout << " [" <<i<<"] ";
00843 
00844                 std::cout << dyninf.offs << " , "<<attr->offset<<" , "<<attr->id<<" , "<<attr->type<<" , {"\
00845                         <<attr->isComponent<<","<<attr->isDynamicType<<","<<attr->isPointer<<","\
00846                         <<attr->isStorable<<"} , "<<ExistAttr(i)<<" , "<<attr->size\
00847                         <<" , ";
00848                 if(ExistAttr(i)) 
00849                         std::cout << GetPtrToData_(i);
00850                 
00851                 if(attr->isPointer && ExistAttr(i)) std::cout << " points -> " << GetDataAsPtr_(i);
00852         }
00853         std::cout<<std::endl;
00854 
00855         // Only dump when CLAM_USE_XML defined
00856         #ifdef CLAM_USE_XML
00857         XMLStorage::Dump(*this, GetClassName(), "Debug.xml");
00858         #endif// CLAM_USE_XML
00859 }
00860 
00861 }; //namespace CLAM
00862 
Generated by  doxygen 1.6.3