|
@@ -39,10 +39,10 @@ struct cmDList_str;
|
39
|
39
|
|
40
|
40
|
typedef struct cmDListIter_str
|
41
|
41
|
{
|
42
|
|
- struct cmDList_str* p;
|
43
|
|
- cmDListIndex_t* x;
|
44
|
|
- cmDListIndexRecd_t* s;
|
45
|
|
- struct cmDListIter_str* link;
|
|
42
|
+ struct cmDList_str* p; // pointer to the owner cmDList
|
|
43
|
+ cmDListIndex_t* x; // pointer to the index this iterator traverses
|
|
44
|
+ cmDListIndexRecd_t* s; // current record
|
|
45
|
+ struct cmDListIter_str* link; // p->iters list link
|
46
|
46
|
} cmDListIter_t;
|
47
|
47
|
|
48
|
48
|
typedef struct cmDList_str
|
|
@@ -66,6 +66,7 @@ cmDList_t* _cmDListHandleToPtr( cmDListH_t h )
|
66
|
66
|
return p;
|
67
|
67
|
}
|
68
|
68
|
|
|
69
|
+// Given an indexId return the associated index.
|
69
|
70
|
cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
|
70
|
71
|
{
|
71
|
72
|
cmDListIndex_t* x = p->indexes;
|
|
@@ -76,12 +77,14 @@ cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
|
76
|
77
|
return NULL;
|
77
|
78
|
}
|
78
|
79
|
|
|
80
|
+// Allocate 'n' new index records for the index 'x'.
|
79
|
81
|
void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
|
80
|
82
|
{
|
81
|
83
|
unsigned i;
|
82
|
84
|
for(i=0; i<n; ++i)
|
83
|
85
|
{
|
84
|
86
|
cmDListIndexRecd_t* s = cmMemAllocZ(cmDListIndexRecd_t,1);
|
|
87
|
+
|
85
|
88
|
s->prev = x->last;
|
86
|
89
|
|
87
|
90
|
if( x->last != NULL )
|
|
@@ -99,82 +102,6 @@ void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
|
99
|
102
|
|
100
|
103
|
}
|
101
|
104
|
|
102
|
|
-void _cmDListIndexUpdate( cmDList_t* p, cmDListIndex_t* x )
|
103
|
|
-{
|
104
|
|
- cmDListIndexRecd_t* first = NULL;
|
105
|
|
- cmDListIndexRecd_t* last = NULL;
|
106
|
|
- cmDListIndexRecd_t* avail = x->first;
|
107
|
|
-
|
108
|
|
- // for each data recd
|
109
|
|
- cmDListRecd_t* r = p->first;
|
110
|
|
- for(; r!=NULL; r=r->next)
|
111
|
|
- {
|
112
|
|
- // get the next available index record
|
113
|
|
- cmDListIndexRecd_t* a = avail;
|
114
|
|
-
|
115
|
|
- avail = avail->next;
|
116
|
|
-
|
117
|
|
- // The count of index records and data records should always be the same.
|
118
|
|
- assert( a != NULL );
|
119
|
|
- a->r = r;
|
120
|
|
-
|
121
|
|
- cmDListIndexRecd_t* s = first;
|
122
|
|
-
|
123
|
|
- // for each index recd that has already been sorted
|
124
|
|
- for(; s!=NULL; s=s->next)
|
125
|
|
- if( x->cmpFunc( x->funcArg, r->dV, r->dN, s->r->dV, s->r->dN ) < 0 )
|
126
|
|
- {
|
127
|
|
- // r is less than s->r
|
128
|
|
- // insert 'a' prior to 's' in the index
|
129
|
|
-
|
130
|
|
- a->next = s;
|
131
|
|
- a->prev = s->prev;
|
132
|
|
-
|
133
|
|
- // if 's' is not first
|
134
|
|
- if( s->prev != NULL )
|
135
|
|
- s->prev->next = a;
|
136
|
|
- else
|
137
|
|
- { // 's' was first - now 'a' is first
|
138
|
|
- assert( s == first );
|
139
|
|
- first = a;
|
140
|
|
- }
|
141
|
|
-
|
142
|
|
- s->prev = a;
|
143
|
|
-
|
144
|
|
- break;
|
145
|
|
- }
|
146
|
|
-
|
147
|
|
- // No records are greater than r or the index is empty - 'a' is last in the index.
|
148
|
|
- if( s == NULL )
|
149
|
|
- {
|
150
|
|
- // insert 'a' after 'last'
|
151
|
|
-
|
152
|
|
- // if the index is empty
|
153
|
|
- if( last == NULL )
|
154
|
|
- {
|
155
|
|
- first = a;
|
156
|
|
- a->prev = NULL;
|
157
|
|
- }
|
158
|
|
- else // make 'a' last in the index
|
159
|
|
- {
|
160
|
|
- a->prev = last;
|
161
|
|
- a->next = NULL;
|
162
|
|
- assert( last->next == NULL );
|
163
|
|
- last->next = a;
|
164
|
|
- }
|
165
|
|
-
|
166
|
|
- a->next = NULL;
|
167
|
|
- last = a;
|
168
|
|
- }
|
169
|
|
-
|
170
|
|
-
|
171
|
|
-
|
172
|
|
- }
|
173
|
|
-
|
174
|
|
- x->first = first;
|
175
|
|
- x->last = last;
|
176
|
|
-}
|
177
|
|
-
|
178
|
105
|
void _cmDListRecdFree( cmDList_t* p, cmDListRecd_t* r )
|
179
|
106
|
{
|
180
|
107
|
if( r->prev != NULL )
|
|
@@ -202,7 +129,7 @@ void _cmDListIndexRecdFree( cmDListIndex_t* x, cmDListIndexRecd_t* s )
|
202
|
129
|
s->next->prev = s->prev;
|
203
|
130
|
else
|
204
|
131
|
x->last = s->prev;
|
205
|
|
-
|
|
132
|
+
|
206
|
133
|
cmMemFree(s);
|
207
|
134
|
}
|
208
|
135
|
|
|
@@ -274,7 +201,7 @@ cmDlRC_t _cmDListIterFree( cmDListIter_t* e )
|
274
|
201
|
else
|
275
|
202
|
e0->link = e1->link;
|
276
|
203
|
|
277
|
|
- cmMemFree(e0);
|
|
204
|
+ cmMemFree(e1);
|
278
|
205
|
break;
|
279
|
206
|
}
|
280
|
207
|
|
|
@@ -307,6 +234,99 @@ cmDlRC_t _cmDListFree( cmDList_t* p )
|
307
|
234
|
return rc;
|
308
|
235
|
}
|
309
|
236
|
|
|
237
|
+
|
|
238
|
+void _cmDListIndexUpdate( cmDList_t* p, cmDListIndex_t* x )
|
|
239
|
+{
|
|
240
|
+ cmDListIndexRecd_t* first = NULL;
|
|
241
|
+ cmDListIndexRecd_t* last = NULL;
|
|
242
|
+
|
|
243
|
+ assert( x->recdN >= p->recdN );
|
|
244
|
+
|
|
245
|
+ // for each data recd
|
|
246
|
+ cmDListRecd_t* r = p->first;
|
|
247
|
+ for(; r!=NULL; r=r->next)
|
|
248
|
+ {
|
|
249
|
+ // get the next available index record
|
|
250
|
+ cmDListIndexRecd_t* a = x->first;
|
|
251
|
+ assert(a!=NULL);
|
|
252
|
+ x->first = x->first->next;
|
|
253
|
+ if( x->first != NULL )
|
|
254
|
+ x->first->prev = NULL;
|
|
255
|
+
|
|
256
|
+ // The count of index records and data records should always be the same.
|
|
257
|
+ assert( a != NULL );
|
|
258
|
+ a->r = r;
|
|
259
|
+
|
|
260
|
+ cmDListIndexRecd_t* s = first;
|
|
261
|
+
|
|
262
|
+ // for each index recd that has already been sorted
|
|
263
|
+ for(; s!=NULL; s=s->next)
|
|
264
|
+ if( x->cmpFunc( x->funcArg, r->dV, r->dN, s->r->dV, s->r->dN ) < 0 )
|
|
265
|
+ {
|
|
266
|
+ // r is less than s->r
|
|
267
|
+ // insert 'a' prior to 's' in the index
|
|
268
|
+
|
|
269
|
+ a->next = s;
|
|
270
|
+ a->prev = s->prev;
|
|
271
|
+
|
|
272
|
+ // if 's' is not first
|
|
273
|
+ if( s->prev != NULL )
|
|
274
|
+ s->prev->next = a;
|
|
275
|
+ else
|
|
276
|
+ { // 's' was first - now 'a' is first
|
|
277
|
+ assert( s == first );
|
|
278
|
+ first = a;
|
|
279
|
+ }
|
|
280
|
+
|
|
281
|
+ s->prev = a;
|
|
282
|
+
|
|
283
|
+ break;
|
|
284
|
+ }
|
|
285
|
+
|
|
286
|
+ // No records are greater than r or the index is empty - 'a' is last in the index.
|
|
287
|
+ if( s == NULL )
|
|
288
|
+ {
|
|
289
|
+ // insert 'a' after 'last'
|
|
290
|
+
|
|
291
|
+ // if the index is empty
|
|
292
|
+ if( last == NULL )
|
|
293
|
+ {
|
|
294
|
+ first = a;
|
|
295
|
+ a->prev = NULL;
|
|
296
|
+ }
|
|
297
|
+ else // make 'a' last in the index
|
|
298
|
+ {
|
|
299
|
+ a->prev = last;
|
|
300
|
+ a->next = NULL;
|
|
301
|
+ assert( last->next == NULL );
|
|
302
|
+ last->next = a;
|
|
303
|
+ }
|
|
304
|
+
|
|
305
|
+ a->next = NULL;
|
|
306
|
+ last = a;
|
|
307
|
+ }
|
|
308
|
+ }
|
|
309
|
+
|
|
310
|
+ // release any index records that are not in use
|
|
311
|
+ while(x->first!=NULL)
|
|
312
|
+ {
|
|
313
|
+ _cmDListIndexRecdFree(x,x->first);
|
|
314
|
+ x->recdN -= 1;
|
|
315
|
+ }
|
|
316
|
+
|
|
317
|
+ assert( x->recdN == p->recdN );
|
|
318
|
+
|
|
319
|
+ // Invalidate all iterators which use index x.
|
|
320
|
+ cmDListIter_t* e = p->iters;
|
|
321
|
+ for(; e!=NULL; e=e->link)
|
|
322
|
+ if( e->x == x )
|
|
323
|
+ e->s = NULL;
|
|
324
|
+
|
|
325
|
+ x->first = first;
|
|
326
|
+ x->last = last;
|
|
327
|
+}
|
|
328
|
+
|
|
329
|
+
|
310
|
330
|
cmDlRC_t _cmDListIndexAlloc( cmDList_t* p, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
|
311
|
331
|
{
|
312
|
332
|
cmDListIndex_t* x;
|
|
@@ -373,7 +393,8 @@ cmDlRC_t cmDListFree( cmDListH_t* hp )
|
373
|
393
|
bool cmDListIsValid( cmDListH_t h )
|
374
|
394
|
{ return h.h != NULL; }
|
375
|
395
|
|
376
|
|
-cmDlRC_t cmDListInsert( cmDListH_t h, const void* recd, unsigned recdByteN )
|
|
396
|
+
|
|
397
|
+cmDlRC_t cmDListInsert( cmDListH_t h, const void* recd, unsigned recdByteN, bool resyncFl )
|
377
|
398
|
{
|
378
|
399
|
cmDList_t* p = _cmDListHandleToPtr(h);
|
379
|
400
|
char* vp = cmMemAllocZ(char,sizeof(cmDListRecd_t) + recdByteN );
|
|
@@ -383,7 +404,7 @@ cmDlRC_t cmDListInsert( cmDListH_t h, const void* recd, unsigned recdByteN )
|
383
|
404
|
r->dN = recdByteN;
|
384
|
405
|
memcpy( r->dV, recd, recdByteN );
|
385
|
406
|
|
386
|
|
- // Add records at the end of the list.
|
|
407
|
+ // Add records at the end of the data record list.
|
387
|
408
|
|
388
|
409
|
// If the list is not empty
|
389
|
410
|
if( p->last != NULL )
|
|
@@ -400,51 +421,88 @@ cmDlRC_t cmDListInsert( cmDListH_t h, const void* recd, unsigned recdByteN )
|
400
|
421
|
p->last = r;
|
401
|
422
|
p->recdN += 1;
|
402
|
423
|
|
403
|
|
- // update the indexes
|
|
424
|
+ // add a record to each index
|
404
|
425
|
cmDListIndex_t* x = p->indexes;
|
405
|
426
|
for(; x!=NULL; x=x->link)
|
406
|
427
|
{
|
407
|
|
- _cmDListIndexAllocRecds(x,1);
|
408
|
|
- _cmDListIndexUpdate(p,x);
|
|
428
|
+ if( x->recdN < p->recdN )
|
|
429
|
+ _cmDListIndexAllocRecds(x,1);
|
|
430
|
+
|
|
431
|
+ assert( x->recdN >= p->recdN );
|
|
432
|
+
|
|
433
|
+ if( resyncFl )
|
|
434
|
+ _cmDListIndexUpdate(p,x);
|
409
|
435
|
}
|
|
436
|
+
|
410
|
437
|
|
411
|
438
|
return kOkDlRC;
|
412
|
439
|
}
|
413
|
440
|
|
414
|
|
-cmDlRC_t cmDListDelete( cmDListH_t h, const void* recd )
|
|
441
|
+cmDlRC_t cmDListDelete( cmDListH_t h, const void* recd, bool resyncFl )
|
415
|
442
|
{
|
416
|
|
- cmDList_t* p = _cmDListHandleToPtr(h);
|
417
|
|
- cmDListIndex_t* x = p->indexes;
|
|
443
|
+ cmDList_t* p = _cmDListHandleToPtr(h);
|
|
444
|
+ cmDListIndex_t* x = p->indexes;
|
418
|
445
|
cmDListIndexRecd_t* s = NULL;
|
419
|
|
- cmDListRecd_t* r = NULL;
|
420
|
|
-
|
421
|
|
- for(; x!=NULL; x=x->link)
|
|
446
|
+ cmDListRecd_t* r = NULL;
|
|
447
|
+
|
|
448
|
+ if( resyncFl==false )
|
422
|
449
|
{
|
423
|
|
- for(s=x->first; s!=NULL; s=s->next)
|
424
|
|
- if( s->r->dV == recd )
|
|
450
|
+ r = p->first;
|
|
451
|
+ for(; r!=NULL; r=r->next)
|
|
452
|
+ if( r->dV == recd )
|
425
|
453
|
{
|
426
|
|
- if( r == NULL )
|
427
|
|
- r = s->r;
|
428
|
|
- else
|
429
|
|
- {
|
430
|
|
- // the same data record should be found for all indexes
|
431
|
|
- assert( s->r == r );
|
432
|
|
- }
|
433
|
|
-
|
434
|
|
- _cmDListIndexRecdFree(x,s);
|
435
|
|
-
|
|
454
|
+ _cmDListRecdFree(p,r);
|
436
|
455
|
break;
|
437
|
456
|
}
|
438
|
457
|
|
439
|
|
- if( r == NULL )
|
440
|
|
- return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The delete target data record could not be found.");
|
|
458
|
+ }
|
|
459
|
+ else
|
|
460
|
+ {
|
|
461
|
+ // for each index
|
|
462
|
+ for(; x!=NULL; x=x->link)
|
|
463
|
+ {
|
|
464
|
+ // for each index recd
|
|
465
|
+ for(s=x->first; s!=NULL; s=s->next)
|
|
466
|
+ if( s->r->dV == recd ) // if this index recd points to the deletion target
|
|
467
|
+ {
|
|
468
|
+ // store a ptr to the data recd to be deleted
|
|
469
|
+ if( r == NULL )
|
|
470
|
+ r = s->r;
|
|
471
|
+ else
|
|
472
|
+ {
|
|
473
|
+ // the same data record should be found for all indexes
|
|
474
|
+ assert( s->r == r );
|
|
475
|
+ }
|
|
476
|
+
|
|
477
|
+ // free the index record
|
|
478
|
+ _cmDListIndexRecdFree(x,s);
|
|
479
|
+
|
|
480
|
+ break;
|
|
481
|
+ }
|
|
482
|
+
|
|
483
|
+ // if the deletion target was not found
|
|
484
|
+ if( r == NULL )
|
|
485
|
+ goto errLabel;
|
441
|
486
|
|
442
|
|
- // if the indexes are valid then the recd should always be found
|
443
|
|
- assert( s!=NULL );
|
|
487
|
+ }
|
|
488
|
+
|
|
489
|
+ // advance any iterators that are pointing to the deleted record
|
|
490
|
+ cmDListIter_t* e = p->iters;
|
|
491
|
+ for(; e!=NULL; e=e->link)
|
|
492
|
+ if( e->s != NULL && e->s->r != NULL && e->s->r == r )
|
|
493
|
+ e->s = e->s->next;
|
|
494
|
+
|
|
495
|
+ // release the data record
|
|
496
|
+ _cmDListRecdFree(p,r);
|
|
497
|
+
|
444
|
498
|
}
|
445
|
499
|
|
446
|
|
- // release the data record
|
447
|
|
- _cmDListRecdFree(p,r);
|
|
500
|
+ errLabel:
|
|
501
|
+ if( r == NULL )
|
|
502
|
+ return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The deletion target record could not be found.");
|
|
503
|
+
|
|
504
|
+ assert( p->recdN > 0 );
|
|
505
|
+ p->recdN -= 1;
|
448
|
506
|
|
449
|
507
|
return kOkDlRC;
|
450
|
508
|
|
|
@@ -479,6 +537,18 @@ cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFre
|
479
|
537
|
return kOkDlRC;
|
480
|
538
|
}
|
481
|
539
|
|
|
540
|
+cmDlRC_t cmDListIndexUpdateAll( cmDListH_t h )
|
|
541
|
+{
|
|
542
|
+ cmDList_t* p = _cmDListHandleToPtr(h);
|
|
543
|
+ cmDListIndex_t* x = p->indexes;
|
|
544
|
+
|
|
545
|
+ for(; x!=NULL; x=x->link)
|
|
546
|
+ _cmDListIndexUpdate(p,x);
|
|
547
|
+
|
|
548
|
+ return kOkDlRC;
|
|
549
|
+}
|
|
550
|
+
|
|
551
|
+
|
482
|
552
|
|
483
|
553
|
cmDListIter_t* _cmDListIterHandleToPtr( cmDListIterH_t h )
|
484
|
554
|
{
|
|
@@ -557,6 +627,8 @@ const void* _cmDListIterGet( cmDListIter_t* e, unsigned* recdByteNRef )
|
557
|
627
|
return NULL;
|
558
|
628
|
}
|
559
|
629
|
|
|
630
|
+ assert( e->s->r != NULL );
|
|
631
|
+
|
560
|
632
|
if( recdByteNRef != NULL )
|
561
|
633
|
*recdByteNRef = e->s->r->dN;
|
562
|
634
|
|
|
@@ -585,7 +657,7 @@ const void* cmDListIterNext( cmDListIterH_t iH, unsigned* recdByteNRef )
|
585
|
657
|
{
|
586
|
658
|
cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
|
587
|
659
|
const void* rv = _cmDListIterGet(e,recdByteNRef);
|
588
|
|
-
|
|
660
|
+
|
589
|
661
|
if( e->s != NULL )
|
590
|
662
|
e->s = e->s->next;
|
591
|
663
|
|