/** ****************************************************************************** @file /common/da.h @brief Dynamicke pole Pole promenlive delky (bez nustnosti volat primo realloc) s nastavitelnym pocatekem. @author Vta @version 1.0 ******************************************************************************/ #ifndef _DA_ #define _DA_ #include #include #include "common/mm.h" #include "common/priority.h" #include "common/Log.h" #include "common/exc.h" #define MAX_RANGE 5000000 ///< Maximalni rozsah indexu (velikost pole) /// Chybove kody #define DA_ERROR_OK 0 ///< Vse je ok #define DA_ERROR_NO_SIZE 2 ///< Neni dovoleno vytvaret pole nulove delky #define DA_ERROR_RANGE 4 ///< Dataz na index nizsi nez je dovoleno #define DA_ERROR_ALLOC 5 ///< Nepovedlo se na(re)alokovat (re/malloc vratil NULL) (bude ohlidano v samotne allokaci - fatalni chyba) #define DA_TEMP_VALUE 0 ///< Hodnota, kterou se vzdy prepise obsah promenne temp /// Sablona dynamickeho pole template class DA { public: DA(/*int count=10,int beginning=0,int enlargement=1,int debug=1*/); ///< Defaultni konstruktor, hodnoty jsou nastaveny na count=10, beginning=0, enlargement=1,debug=1 /** @brief Konstruktor @param count udava prvotni pocet prvku pole @param beginning je nejmensi index, ktery se v poli pouzije - "kde pole zacina" @param enlargement znamena kolikrat se pole pri reallocu zvetsi @param debug pri hodnote 1 se provadi logovani alokace pameti */ DA(int count,int beginning=0,int enlargement=1,int debug=1); // kolik prvku, kde zacinaji, nasobky=useMoreSpace, zda-li debugovat int getError(); ///< Vrati posledni error int getMembers(); ///< Vrati pocet naalokovanych prvku int getActiveMembers(); ///< Vrati pocet aktivnich prvku - -shift+maxId+1 int getMaxId(); ///< Vraci nejvetsi zaplneny index - tj. maxId (dalsi volny prvek je tedy getMaxId()+1) int getShift(); ///< Vrati shift (tj. posunuti zacatku pole oproti 0) T* getData(); ///< Vraci pointer na data. Je nutne vzit v potaz, ze 0. index pole data2 bude odpovidat this->shift-emu indexu v poli DA. void reset(void); // Resetuje pole - nastavi nejvetsi pouzity index na to co byl na zacatku, nedojde vsak k fyzickemu vymazani pole ~DA(); ///< Destruktor /** @brief ///< Vrati nejmensi index vetsi nez from, ktery obsahuje nejaka data (tj. neobsahuje NULL), pokud zadny takovy neexistuje, vraci (shift-1). Pro "normalni" cckove pole zacinajici od 0 je navratova hodnota tedy -1. Nalezt prvni index pro Cckove pole je pak getNext(-1). @param from odkud zacinam v poli hledat (uvazuje se az nasledujici prvek) */ int getNext(int from); // int pop(T prvek); // vlozi prvek za prvek s nejvetsim indexem /** @brief Vezme a vymaze (zmensi velikost) posledni prvek @param prvek ukazatel na posledni odtrzeny prvek */ void push(T * prvek); /** @brief Nastavi imaginarne novy zacatek pole, neprovadi se kopirovani ani reallokace @param beginning udava novy zacatek pole */ void moveBeginning(int beginning); /** @brief Zmeni velikost pole, ale pouze na jedne strane. Provadi se vlastni realloc. @param toHowMany urcuje novou velikost pole */ void resize(int toHowMany); /** @brief Operator pristupu do pole @param i je index bunky v poli na kterou se dotazuji */ T & operator[] (int i); /// Vraci 1, pokud je pole prazdne nebo byl proveden reset() int isEmpty(); /** @brief Zaznamena kolikrat ma pole pri dalsim reallocu zvetsit svoji velikost @param i udava o kolikanasobek puvodni delky se pole zvetsi */ void setEnlarge(int i); /** @brief Prepise dany prvek poslednim @param id udava, kterou bunku mam zapomenout - prepsat bunkou v poli posledni */ void remove(int id); /* bug - nerozsiri pole v pripade potreby // @brief Prida prvek na prvni volne misto (pokud v poli nejsou diry, je rychlejsi pridavat na index "getMaxId()+1" @param data obsahuji data (v pripade typu int) nebo pointer na data // int add(T data); */ private: int debug; ///< Zda-li se debuguje T* array; ///< Vlastni data int maxId; ///< Nejvesti pouzity index - z pohledu uzivatele! tj. ne primo index array[] ale (index+shift)! int useMoreSpace; ///< Informace o tom, jestli se ma pole rozsirovat o vetsi kus dopredu nebo o presne, kolik je potreba, 0-presne, >0 nasobku puvodni velikosti int error; ///< Chybova hodnota @sa Chybove hlasky int howmany; ///< Kolik ma pole prvku int shift; ///< Od ktereho prvku zacina cislovani - tj. napr. od <5,7> je shift 5, howmany 3 T temp; ///< Pomocna promenna, napr. na ukladani hodnot mimo rozsah }; template DA::DA(int count,int beginning,int enlargement, int debug) // konstruktor, kolik - pocet prvku, zacatek - shift od 0, lze i zaporny, toVoid vynulovat { this->debug=debug; if (this->debug==1) { KDAnew(this); } // this->toNull=toVoid; this->useMoreSpace=enlargement; // this->useTempint=0; // this->deleteData=1; this->temp=DA_TEMP_VALUE; // this->temp=0; if (count>0) { this->shift=beginning; // if ((this->array=(T *) malloc (sizeof(T)*count))==NULL) if (this->debug==0) this->array=(T *) malloc (sizeof(T)*count); else this->array=(T *) KMemAlloc (sizeof(T)*count); if (this->array==NULL) { this->error=DA_ERROR_ALLOC; this->howmany=0; } else { this->error=DA_ERROR_OK; this->howmany=count; // howmany je max pocet prvku // if (this->toNull!=0) // vse na 0, je to cersvte naalkovovane, takze to muzu projet vse { int i; for (i=0;iarray[i]=0; } } } else { this->error=DA_ERROR_NO_SIZE; this->howmany=0; this->shift=0; this->array=NULL; } this->maxId=shift-1; // maxId je pocet prvku!!! } template DA::~DA() { if (this->debug==1) { //KDAdelete(this);///??? spatne!! } if ((this->howmany>0) /*&& (this->deleteData==1)*/) { if (this->debug==0) { free(this->array); } else { KMemFree(this->array); } } // free(this->array); } template DA::DA() { // myConstructor(10,0,1,1); // DA(10,0,1); - jenze to nefunguje :((( // konstruktor, kolik - pocet prvku, zacatek - shift od 0, lze i zaporny, toVoid vynulovat this->debug=1; if (this->debug==1) { KDAnew(this); } int count=10; int beginning=0; // this->toNull=1; this->useMoreSpace=1; // this->useTempint=0; // this->deleteData=1; this->temp=DA_TEMP_VALUE; // this->temp=0; if (count>0) { this->shift=beginning; // if ((this->array=(T *) malloc (sizeof(T)*count))==NULL) if (this->debug==0) this->array=(T *) malloc (sizeof(T)*count); else this->array=(T *) KMemAlloc (sizeof(T)*count); if (this->array==NULL) { this->error=DA_ERROR_ALLOC; this->howmany=0; } else { this->error=DA_ERROR_OK; this->howmany=count; // if (this->toNull!=0) // vse na 0, je to cersvte naalkovovane, takze to muzu projet vse { int i; for (i=0;iarray[i]=0; } } } else { this->error=DA_ERROR_NO_SIZE; this->howmany=0; this->shift=0; this->array=NULL; } this->maxId=shift-1; } template void DA::remove(int id) { if (id<(this->maxId+this->shift)) // prvek nekde uvnitr { this->array[id-this->shift]=this->array[this->maxId-this->shift]; this->array[this->maxId-this->shift]=0; this->maxId--; } else { if (id==this->maxId) // tj. byl to posledni prvek { this->array[this->maxId-this->shift]=0; this->maxId--; } } } /* template int DA::add(T data) { int i=0; while (imaxId) { if (this->array[i]==NULL) { this->array[i]=data; break; } i++; } return (i+this->shift); } */ template T* DA::getData(void) { return this->array; } template void DA::reset(void) { this->maxId=this->shift-1; } template void DA::setEnlarge(int i) { this->useMoreSpace=i; } /* template void DA::useTemp() { this->useTempint=1; } template void DA::dontuseTemp() { this->useTempint=0; } template void DA::DeleteData() { this->deleteData=1; } template void DA::dontDeleteData() { this->deleteData=0; } */ template int DA::isEmpty() { return ((-this->shift+this->maxId+1)<=0); } template int DA::getShift() { return this->shift; } template int DA::getMembers() { return this->howmany; } template int DA::getActiveMembers() { return (-this->shift+this->maxId+1); // +1 protoze pocitam i ten 0.ty resp. shift.ty } template int DA::getMaxId() { return (this->maxId); } template int DA::getError() { int e=this->error; this->error=DA_ERROR_OK; return e; } template void DA::moveBeginning (int beginning) { this->shift=beginning; this->error=DA_ERROR_OK; } template void DA::resize (int toHowMany) { if (toHowMany<0) // hehe :) { toHowMany=1; } if (this->debug==1) { this->array=(T *)KMemRealloc( this->array, (toHowMany * sizeof( T ))); } else { this->array=(T *)realloc( this->array, (toHowMany * sizeof( T ))); } if (this->array==NULL) { this->error=DA_ERROR_ALLOC; this->howmany=0; maxId=-1; } else { // if (this->toNull!=0) // chce vynulovat { int i; for (i=this->howmany;iarray[i]=0; // neprobehne nic } this->howmany=toHowMany; this->error=DA_ERROR_OK; if ((toHowMany+this->shift)<(maxId)) // pokud je maxId ve ztracene casti pole this->maxId=toHowMany+this->shift-1; // tak se vezme nejvetsi index, ktery tedka je k dispozici } } template T & DA::operator[] (int i) { if (i-this->shift>MAX_RANGE) // pokus o alokaci pole neobvykle velkeho { GLOBALLOGID(PRIORITY_DA_OUT_OF_RANGE,"Attempt to expand the array over the max range %i",MAX_RANGE); this->error=DA_ERROR_RANGE; // mimo rozsah return this->temp; // nelze vracet neco z pole, protoze by se to prepsalo } this->temp=DA_TEMP_VALUE; // nikdy nic v tempu nezustane if (this->maxIdmaxId=i; if ((i>=this->shift) && (i<(this->shift+this->howmany))) // neco co uz je v naalokovanem poli { this->error=DA_ERROR_OK; // ok return this->array[i-shift]; } else { size_t size; if (this->array!=NULL) size = this->howmany*sizeof(T); else size=0; if (i>=(this->shift+this->howmany)) // index vetsi { // this->error=3; // realokace GLOBALLOGID(PRIORITY_DA,"Realloc from %i to %i\n",this->howmany,(this->useMoreSpace+1)*this->howmany+i-(this->shift+this->howmany)+1); if (this->debug==1) { this->array=(T *)KMemRealloc( this->array, size + size*this->useMoreSpace + ((i-(this->shift+this->howmany)+1) * sizeof( T ))); } else { this->array=(T *)realloc( this->array, size + size*this->useMoreSpace + ((i-(this->shift+this->howmany)+1) * sizeof( T ))); } if (this->array==NULL) // howmany-shift je delka, howmany+shift je id maximalniho prvku { this->error=DA_ERROR_ALLOC; // nepovedlo se realokovat this->howmany=0; this->maxId=this->shift-1; return this->temp; // nelze vracet neco z pole, protoze se nenaalokovalo } else { int j=(this->useMoreSpace+1)*this->howmany+i-(this->shift+this->howmany)+1; // if (this->toNull!=0) // pokud chce vynulovat vsechny hodnoty na 0 { int i; for (i=this->howmany;iarray[i]=0; } this->howmany=j; this->error=DA_ERROR_OK; // ok return this->array[i-shift]; } } else // index mensi nez je dolni hranice { this->error=DA_ERROR_RANGE; // mimo rozsah // return 0; - nelze .. musim vratit int & return this->temp; // nelze vracet neco z pole, protoze by se to prepsalo } } } template int DA::getNext(int from) { int i=from-this->shift+1; // abych se pohyboval v poli this->array if (i<0) // pokud zadal nejake hodne male cislo - tj. byl bych v array pred 0 i=0; while ((ihowmany) && (this->array[i]==0)) i++; this->error=DA_ERROR_OK; if (i==this->howmany) return -1; // zadny vetsi uz tam neni else return i+this->shift; // vracim ten vetsi } /* // *** POP *** template int DA::pop(T prvek) // fce na vlozeni prvku na index o 1 vetsi nez nejvetsi pouzity index { if ((this->maxId+1-this->shift)>=this->howmany) // melo by to byt vzdy o 1 vetsi // chci pridat, ale jsem uz nakonci v alokovanem poli { size_t size; if (this->array!=NULL) size = this->howmany*sizeof(T); else size=0; int toHowMany=size + size*this->useMoreSpace + (1) * sizeof( T )); // rozisi v nejmensim pripade prave o ten jeden, jinak o nasobky size+1 if (this->debug==1) { this->array=(T *)KMemRealloc( this->array, (toHowMany)); } else { this->array=(T *)realloc( this->array, (toHowMany)); } if (this->array=NULL) { this->error=DA_ERROR_ALLOC; this->howmany=0; this->maxId=this->shift-1; } else { int j=((this->useMoreSpace+1)*this->howmany+1); // if (this->toNull!=0) // pokud chce vynulovat vsechny hodnoty na 0 { // je tady realloc, tedy nesmazat vse, ale az to nove int i; for (i=this->howmany;iarray[i]=0; } maxId++; this->array[this->maxId-this->shift]=prvek; this->howmany=(this->useMoreSpace+1)*this->howmany+1; this->error=DA_ERROR_OK; } } else // je tam misto { maxId++; this->array[this->maxId-this->shift]=prvek; } return maxId; } */ // *** push *** template void DA::push(T * prvek) // fce na ubrani prvku s nejvetsim indexem v poli { if (maxId>=shift) { if (prvek!=NULL) (*prvek)=this->array[maxId-this->shift]; this->maxId--; } else { this->error=DA_ERROR_RANGE; } } # endif //*****************************************************************************************