1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include "tjindex.h"
#include "tjtest.h"
#include "tjlog_code.h"
#include "tjhandler_code.h"
const char* Index::get_compName() {return "Index";}
LOGGROUNDWORK(Index)
///////////////////////////////////////////////////////////////////////////////////////////
unsigned int UniqueIndexMap::get_index(STD_list<unsigned int>::iterator& index, const STD_string& type, unsigned int max_instances) {
Log<Index> odinlog(type.c_str(),"get_index");
STD_list<unsigned int>& indices=(*this)[type];
if(index==indices.end()) assign_index(index,type);
if(max_instances && ((*index)>=max_instances)) {
ODINLOG(odinlog,errorLog) << "maximum number of indices exceeded for type " << type << STD_endl;
return 0;
}
ODINLOG(odinlog,normalDebug) << "returning index=" << *index << STD_endl;
return (*index);
}
void UniqueIndexMap::remove_index(const STD_list<unsigned int>::iterator& index, const STD_string& type) {
Log<Index> odinlog(type.c_str(),"remove_index");
STD_list<unsigned int>& indices=(*this)[type];
if(index!=indices.end()) {
ODINLOG(odinlog,normalDebug) << "Trying to remove index=" << *index << STD_endl;
indices.erase(index);
contiguous=false;
}
}
unsigned int UniqueIndexMap::assign_index(STD_list<unsigned int>::iterator& index, const STD_string& type) {
Log<Index> odinlog(type.c_str(),"assign_index");
STD_list<unsigned int>& indices=(*this)[type];
index=indices.end();
unsigned int i=0;
STD_list<unsigned int>::iterator iter;
if(contiguous){ //if the list is contiguous
iter=indices.end();
if(indices.begin()!=indices.end())//use the last member +1 or leave 0
i= *(--indices.end())+1;
} else {//if list is not complete find the first "gap"
for(iter=indices.begin();iter!=indices.end() && *iter==i;++iter)
i++;
}
index=indices.insert(iter,i);//insert i into the gap (or the end)
ODINLOG(odinlog,normalDebug) << "adding index=" << i << STD_endl;
for(;iter!=indices.end() && *iter==(i+1);++iter); //check for a gap behind
contiguous = (iter==indices.end());
return i;
}
///////////////////////////////////////////////////////////////////////////////////////////
template class SingletonHandler<UniqueIndexMap,true>;
SingletonHandler<UniqueIndexMap,true> UniqueIndexBase::indices_map;
EMPTY_TEMPL_LIST bool StaticHandler<UniqueIndexBase>::staticdone=false;
///////////////////////////////////////////////////////////////////////////////////////////
#ifndef NO_UNIT_TEST
#define INDEX_TESTSIZE 5
class IndexTest : public UnitTest {
// Test class
class UniqueIndexTest : public UniqueIndex<UniqueIndexTest> {
public:
UniqueIndexTest(){};
static const char* get_typename() {return "UniqueIndexTest";}
static unsigned int get_max_instances() {return 0;}
};
public:
IndexTest() : UnitTest("index") {}
private:
bool compare_and_report(int expected[INDEX_TESTSIZE], UniqueIndexTest* objs[INDEX_TESTSIZE], const char* txt) const {
Log<UnitTest> odinlog(this,"compare_and_report");
for(unsigned int i=0; i<INDEX_TESTSIZE; i++) {
if(expected[i]>=0) {
int returned=objs[i]->get_index();
if(expected[i]!=returned) {
ODINLOG(odinlog,errorLog) << txt << "[" << i << "]: expected/returned=" << expected[i] << "/" << returned << STD_endl;
return true;
}
}
}
return false;
}
bool check() const {
Log<UnitTest> odinlog(this,"check");
UniqueIndexTest* objs[INDEX_TESTSIZE];
for(unsigned int i=0; i<INDEX_TESTSIZE; i++) objs[i]=new UniqueIndexTest;
int expected[]={0,1,2,3,4};
if(compare_and_report(expected, objs, "alloc")) return false;
// check whether 1st deleted slot is filled by new object
delete objs[3];
delete objs[1];
objs[1]=new UniqueIndexTest;
int expected2[]={0,1,2,-1,4};
if(compare_and_report(expected2, objs, "realloc1")) return false;
objs[3]=new UniqueIndexTest;
if(compare_and_report(expected, objs, "realloc1")) return false;
UniqueIndexTest* endobj=new UniqueIndexTest;
unsigned int endobjindex_expected=INDEX_TESTSIZE;
unsigned int endobjindex=endobj->get_index();
if(endobjindex!=endobjindex_expected) {
ODINLOG(odinlog,errorLog) << "endobjindex/_expected=" << endobjindex << "/" << endobjindex_expected << STD_endl;
return false;
}
delete endobj;
// Delete in reverse order and check again
delete objs[1];
delete objs[3];
objs[1]=new UniqueIndexTest;
objs[3]=new UniqueIndexTest;
if(compare_and_report(expected, objs, "realloc2")) return false;
// Delete begin and end indices
delete objs[0];
delete objs[INDEX_TESTSIZE-1];
int expected3[]={-1,1,2,3,-1};
if(compare_and_report(expected3, objs, "begin/end")) return false;
// Re-create in reverse order
objs[INDEX_TESTSIZE-1]=new UniqueIndexTest;
int expected4[]={-1,1,2,3,0};
if(compare_and_report(expected4, objs, "begin/end(realloc1)")) return false;
objs[0]=new UniqueIndexTest;
int expected5[]={4,1,2,3,0};
if(compare_and_report(expected5, objs, "begin/end(realloc2)")) return false;
for(unsigned int i=0; i<INDEX_TESTSIZE; i++) delete objs[i];
return true;
}
};
void alloc_IndexTest() {new IndexTest();} // create test instance
#endif
|