CLAM-Development
1.1
|
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