123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- #include "cmGlobal.h"
- #include "cmRpt.h"
- #include "cmErr.h"
- #include "cmCtx.h"
- #include "cmMem.h"
- #include "cmMallocDebug.h"
- #include "cmDList.h"
-
-
- typedef struct cmDListRecd_str
- {
- void* dV;
- unsigned dN;
- struct cmDListRecd_str* prev;
- struct cmDListRecd_str* next;
- } cmDListRecd_t;
-
- typedef struct cmDListIndexRecd_str
- {
- cmDListRecd_t* r;
- struct cmDListIndexRecd_str* prev;
- struct cmDListIndexRecd_str* next;
- } cmDListIndexRecd_t;
-
- typedef struct cmDListIndex_str
- {
- unsigned id;
- cmDListCmpFunc_t cmpFunc;
- void* funcArg;
- cmDListIndexFreeFunc_t freeFunc;
- cmDListIndexRecd_t* first;
- cmDListIndexRecd_t* last;
- unsigned recdN;
- struct cmDListIndex_str* link;
- } cmDListIndex_t;
-
-
- struct cmDList_str;
-
- typedef struct cmDListIter_str
- {
- struct cmDList_str* p; // pointer to the owner cmDList
- cmDListIndex_t* x; // pointer to the index this iterator traverses
- cmDListIndexRecd_t* s; // current record
- struct cmDListIter_str* link; // p->iters list link
- } cmDListIter_t;
-
- typedef struct cmDList_str
- {
- cmErr_t err;
- cmDListRecd_t* first;
- cmDListRecd_t* last;
- unsigned recdN;
-
- cmDListIndex_t* indexes;
- cmDListIter_t* iters;
- } cmDList_t;
-
- cmDListH_t cmDListNullHandle = cmSTATIC_NULL_HANDLE;
- cmDListIterH_t cmDListIterNullHandle = cmSTATIC_NULL_HANDLE;
-
- cmDList_t* _cmDListHandleToPtr( cmDListH_t h )
- {
- cmDList_t* p = (cmDList_t*)h.h;
- assert( p!=NULL );
- return p;
- }
-
- // Given an indexId return the associated index.
- cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
- {
- cmDListIndex_t* x = p->indexes;
- for(; x!=NULL; x=x->link)
- if( x->id == indexId )
- return x;
-
- return NULL;
- }
-
- // Allocate 'n' new index records for the index 'x'.
- void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
- {
- unsigned i;
- for(i=0; i<n; ++i)
- {
- cmDListIndexRecd_t* s = cmMemAllocZ(cmDListIndexRecd_t,1);
-
- s->prev = x->last;
-
- if( x->last != NULL )
- x->last->next = s;
- else
- {
- assert( x->first == NULL );
- x->first = s;
- }
-
- x->last = s;
- }
-
- x->recdN += n;
-
- }
-
- void _cmDListRecdFree( cmDList_t* p, cmDListRecd_t* r )
- {
- if( r->prev != NULL )
- r->prev->next = r->next;
- else
- p->first = r->next;
-
- if( r->next != NULL )
- r->next->prev = r->prev;
- else
- p->last = r->prev;
-
- cmMemFree(r);
- }
-
- // Unlink and free the index record s;
- void _cmDListIndexRecdFree( cmDListIndex_t* x, cmDListIndexRecd_t* s )
- {
- if( s->prev != NULL )
- s->prev->next = s->next;
- else
- x->first = s->next;
-
- if( s->next != NULL )
- s->next->prev = s->prev;
- else
- x->last = s->prev;
-
- cmMemFree(s);
- }
-
- // Unlink and release an index.
- void _cmDListIndexFree( cmDList_t* p, cmDListIndex_t* x )
- {
- if( x == NULL )
- return;
-
- cmDListIndex_t* x0 = NULL;
- cmDListIndex_t* x1 = p->indexes;
-
- // unlink 'x' from p->indexes
- while( x1 != NULL )
- {
- if( x1 == x )
- {
- // x is the first index
- if( x0 == NULL )
- {
- assert( x1 = p->indexes );
- p->indexes = x->link;
- }
- else
- {
- x0->link = x1->link;
- }
-
- break;
- }
-
- x0 = x1;
- x1 = x1->link;
- }
-
- // 'x' must have been found
- assert( x1 == x );
-
-
- // release each index record in 'x'
- cmDListIndexRecd_t* s = x->first;
- while( s != NULL )
- {
- cmDListIndexRecd_t* ns = s->next;
- cmMemFree(s);
- s = ns;
- }
-
- if( x->freeFunc != NULL )
- x->freeFunc(x->id,x->funcArg);
-
- cmMemFree(x);
-
- }
-
- // Unlink and release the iterator 'e'.
- cmDlRC_t _cmDListIterFree( cmDListIter_t* e )
- {
- cmDList_t* p = e->p;
- cmDListIter_t* e0 = NULL;
- cmDListIter_t* e1 = p->iters;
-
- while( e1 != NULL )
- {
- if( e1 == e )
- {
- if( e0 == NULL )
- p->iters = e1->link;
- else
- e0->link = e1->link;
-
- cmMemFree(e1);
- break;
- }
-
- e0 = e1;
- e1 = e1->link;
- }
-
- if( e1 == NULL )
- return cmErrMsg(&p->err,kIterNotFoundDlRC,"The delete target iterator could not be found.");
-
- return kOkDlRC;
- }
-
- cmDlRC_t _cmDListFree( cmDList_t* p )
- {
- cmDlRC_t rc = kOkDlRC;
-
- // release all indexes
- while( p->indexes != NULL )
- _cmDListIndexFree(p,p->indexes);
-
- while( p->iters != NULL )
- _cmDListIterFree(p->iters);
-
- // release all data records
- while( p->first != NULL )
- _cmDListRecdFree(p,p->first);
-
- cmMemFree(p);
- return rc;
- }
-
-
- void _cmDListIndexUpdate( cmDList_t* p, cmDListIndex_t* x )
- {
- cmDListIndexRecd_t* first = NULL;
- cmDListIndexRecd_t* last = NULL;
-
- assert( x->recdN >= p->recdN );
-
- // for each data recd
- cmDListRecd_t* r = p->first;
- for(; r!=NULL; r=r->next)
- {
- // get the next available index record
- cmDListIndexRecd_t* a = x->first;
- assert(a!=NULL);
- x->first = x->first->next;
- if( x->first != NULL )
- x->first->prev = NULL;
-
- // The count of index records and data records should always be the same.
- assert( a != NULL );
- a->r = r;
-
- cmDListIndexRecd_t* s = first;
-
- // for each index recd that has already been sorted
- for(; s!=NULL; s=s->next)
- if( x->cmpFunc( x->funcArg, r->dV, r->dN, s->r->dV, s->r->dN ) < 0 )
- {
- // r is less than s->r
- // insert 'a' prior to 's' in the index
-
- a->next = s;
- a->prev = s->prev;
-
- // if 's' is not first
- if( s->prev != NULL )
- s->prev->next = a;
- else
- { // 's' was first - now 'a' is first
- assert( s == first );
- first = a;
- }
-
- s->prev = a;
-
- break;
- }
-
- // No records are greater than r or the index is empty - 'a' is last in the index.
- if( s == NULL )
- {
- // insert 'a' after 'last'
-
- // if the index is empty
- if( last == NULL )
- {
- first = a;
- a->prev = NULL;
- }
- else // make 'a' last in the index
- {
- a->prev = last;
- a->next = NULL;
- assert( last->next == NULL );
- last->next = a;
- }
-
- a->next = NULL;
- last = a;
- }
- }
-
- // release any index records that are not in use
- while(x->first!=NULL)
- {
- _cmDListIndexRecdFree(x,x->first);
- x->recdN -= 1;
- }
-
- assert( x->recdN == p->recdN );
-
- // Invalidate all iterators which use index x.
- cmDListIter_t* e = p->iters;
- for(; e!=NULL; e=e->link)
- if( e->x == x )
- e->s = NULL;
-
- x->first = first;
- x->last = last;
- }
-
-
- cmDlRC_t _cmDListIndexAlloc( cmDList_t* p, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
- {
- cmDListIndex_t* x;
-
- if((x =_cmDListIdToIndex(p, indexId )) != NULL )
- return cmErrMsg(&p->err,kDuplicateIndexIdDlRC,"The indexId '%i' has already been used.",indexId);
-
- x = cmMemAllocZ(cmDListIndex_t,1);
-
- x->id = indexId;
- x->cmpFunc = func;
- x->funcArg = funcArg;
- x->link = p->indexes;
- p->indexes = x;
-
-
- _cmDListIndexAllocRecds(x,p->recdN);
- _cmDListIndexUpdate(p,x);
-
- return kOkDlRC;
-
- }
-
- cmDlRC_t cmDListAlloc( cmCtx_t* ctx, cmDListH_t* hp, cmDListCmpFunc_t func, void* funcArg )
- {
- cmDlRC_t rc = kOkDlRC;
-
- if((rc = cmDListFree(hp)) != kOkDlRC )
- return rc;
-
- cmDList_t* p = cmMemAllocZ(cmDList_t,1);
- cmErrSetup(&p->err,&ctx->rpt,"cmDList");
-
- if( func!=NULL )
- if((rc = _cmDListIndexAlloc(p,0,func,funcArg)) != kOkDlRC )
- goto errLabel;
-
- hp->h = p;
-
- errLabel:
- if( rc != kOkDlRC )
- _cmDListFree(p);
-
- return rc;
- }
-
- cmDlRC_t cmDListFree( cmDListH_t* hp )
- {
- cmDlRC_t rc;
-
- if( hp==NULL || cmDListIsValid(*hp)==false)
- return kOkDlRC;
-
- cmDList_t* p = _cmDListHandleToPtr(*hp);
-
- if((rc = _cmDListFree(p)) != kOkDlRC )
- return rc;
-
- hp->h = NULL;
-
- return rc;
- }
-
- bool cmDListIsValid( cmDListH_t h )
- { return h.h != NULL; }
-
-
- cmDlRC_t cmDListInsert( cmDListH_t h, const void* recd, unsigned recdByteN, bool resyncFl )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- char* vp = cmMemAllocZ(char,sizeof(cmDListRecd_t) + recdByteN );
- cmDListRecd_t* r = (cmDListRecd_t*)vp;
-
- r->dV = r + 1;
- r->dN = recdByteN;
- memcpy( r->dV, recd, recdByteN );
-
- // Add records at the end of the data record list.
-
- // If the list is not empty
- if( p->last != NULL )
- p->last->next = r;
- else
- {
- // The list was empty
- assert( p->first == NULL );
- p->first = r;
- }
-
- r->prev = p->last;
- r->next = NULL;
- p->last = r;
- p->recdN += 1;
-
- // add a record to each index
- cmDListIndex_t* x = p->indexes;
- for(; x!=NULL; x=x->link)
- {
- if( x->recdN < p->recdN )
- _cmDListIndexAllocRecds(x,1);
-
- assert( x->recdN >= p->recdN );
-
- if( resyncFl )
- _cmDListIndexUpdate(p,x);
- }
-
-
- return kOkDlRC;
- }
-
- cmDlRC_t cmDListDelete( cmDListH_t h, const void* recd, bool resyncFl )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- cmDListIndex_t* x = p->indexes;
- cmDListIndexRecd_t* s = NULL;
- cmDListRecd_t* r = NULL;
-
- if( resyncFl==false )
- {
- r = p->first;
- for(; r!=NULL; r=r->next)
- if( r->dV == recd )
- {
- _cmDListRecdFree(p,r);
- break;
- }
-
- }
- else
- {
- // for each index
- for(; x!=NULL; x=x->link)
- {
- // for each index recd
- for(s=x->first; s!=NULL; s=s->next)
- if( s->r->dV == recd ) // if this index recd points to the deletion target
- {
- // store a ptr to the data recd to be deleted
- if( r == NULL )
- r = s->r;
- else
- {
- // the same data record should be found for all indexes
- assert( s->r == r );
- }
-
- // free the index record
- _cmDListIndexRecdFree(x,s);
-
- break;
- }
-
- // if the deletion target was not found
- if( r == NULL )
- goto errLabel;
-
- }
-
- // advance any iterators that are pointing to the deleted record
- cmDListIter_t* e = p->iters;
- for(; e!=NULL; e=e->link)
- if( e->s != NULL && e->s->r != NULL && e->s->r == r )
- e->s = e->s->next;
-
- // release the data record
- _cmDListRecdFree(p,r);
-
- }
-
- errLabel:
- if( r == NULL )
- return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The deletion target record could not be found.");
-
- assert( p->recdN > 0 );
- p->recdN -= 1;
-
- return kOkDlRC;
-
- }
-
- cmDlRC_t cmDListIndexAlloc( cmDListH_t h, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- return _cmDListIndexAlloc(p,indexId,func,funcArg);
- }
-
- cmDlRC_t cmDListIndexFree( cmDListH_t h, unsigned indexId )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- cmDListIndex_t* x;
- if((x = _cmDListIdToIndex(p,indexId)) == NULL )
- return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
-
- _cmDListIndexFree(p,x);
-
- return kOkDlRC;
- }
-
- cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFreeFunc_t func )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- cmDListIndex_t* x;
- if((x = _cmDListIdToIndex(p,indexId)) == NULL )
- return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
-
- x->freeFunc = func;
- return kOkDlRC;
- }
-
- cmDlRC_t cmDListIndexUpdateAll( cmDListH_t h )
- {
- cmDList_t* p = _cmDListHandleToPtr(h);
- cmDListIndex_t* x = p->indexes;
-
- for(; x!=NULL; x=x->link)
- _cmDListIndexUpdate(p,x);
-
- return kOkDlRC;
- }
-
-
-
- cmDListIter_t* _cmDListIterHandleToPtr( cmDListIterH_t h )
- {
- cmDListIter_t* e = (cmDListIter_t*)h.h;
- assert(e != NULL );
- return e;
- }
-
- cmDlRC_t cmDListIterAlloc( cmDListH_t h, cmDListIterH_t* iHp, unsigned indexId )
- {
- cmDlRC_t rc = kOkDlRC;
- cmDList_t* p = _cmDListHandleToPtr(h);
- cmDListIndex_t* x;
-
- if((rc = cmDListIterFree(iHp)) != kOkDlRC )
- return rc;
-
- if((x = _cmDListIdToIndex(p, indexId)) == NULL )
- return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
-
- cmDListIter_t* e = cmMemAllocZ(cmDListIter_t,1);
-
- e->p = p;
- e->x = x;
- e->s = x->first;
- e->link = p->iters;
- p->iters = e;
-
- iHp->h = e;
-
- return rc;
-
- }
-
- cmDlRC_t cmDListIterFree( cmDListIterH_t* iHp )
- {
- cmDlRC_t rc;
-
- if( iHp==NULL || cmDListIterIsValid(*iHp)==false )
- return kOkDlRC;
-
- cmDListIter_t* e = _cmDListIterHandleToPtr(*iHp);
-
- if(( rc = _cmDListIterFree( e )) != kOkDlRC )
- return rc;
-
- iHp->h = NULL;
-
- return rc;
- }
-
- bool cmDListIterIsValid( cmDListIterH_t iH )
- { return iH.h != NULL; }
-
-
- cmDlRC_t cmDListIterSeekBegin( cmDListIterH_t iH )
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
- e->s = e->x->first;
- return kOkDlRC;
- }
-
- cmDlRC_t cmDListIterSeekLast( cmDListIterH_t iH )
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
- e->s = e->x->last;
- return kOkDlRC;
- }
-
- const void* _cmDListIterGet( cmDListIter_t* e, unsigned* recdByteNRef )
- {
- if( e->s == NULL )
- {
- if( recdByteNRef != NULL )
- *recdByteNRef = 0;
- return NULL;
- }
-
- assert( e->s->r != NULL );
-
- if( recdByteNRef != NULL )
- *recdByteNRef = e->s->r->dN;
-
- return e->s->r->dN==0 ? NULL : e->s->r->dV;
- }
-
- const void* cmDListIterGet( cmDListIterH_t iH, unsigned* recdByteNRef )
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
-
- return _cmDListIterGet(e,recdByteNRef);
- }
-
- const void* cmDListIterPrev( cmDListIterH_t iH, unsigned* recdByteNRef )
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
- const void* rv = _cmDListIterGet(e,recdByteNRef);
-
- if( e->s != NULL )
- e->s = e->s->prev;
-
- return rv;
- }
-
- const void* cmDListIterNext( cmDListIterH_t iH, unsigned* recdByteNRef )
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
- const void* rv = _cmDListIterGet(e,recdByteNRef);
-
- if( e->s != NULL )
- e->s = e->s->next;
-
- return rv;
- }
-
- const void* cmDListIterFind( cmDListIterH_t iH, const void* key, unsigned keyN, unsigned* recdByteNRef)
- {
- cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
-
- cmDListIndexRecd_t* s = e->s;
-
- for(; s!=NULL; s=s->next)
- if( e->x->cmpFunc( e->x->funcArg, s->r->dV, s->r->dN, key, keyN ) == 0 )
- {
- e->s = s;
- return _cmDListIterGet(e,recdByteNRef);
- }
-
- if( recdByteNRef != NULL )
- *recdByteNRef = 0;
-
- return NULL;
- }
|