Browse Source

cmDList.h/c/Tpl.h : Initial commit.

master
Kevin Larke 8 years ago
parent
commit
042b1173f5
3 changed files with 795 additions and 0 deletions
  1. 612
    0
      cmDList.c
  2. 61
    0
      cmDList.h
  3. 122
    0
      cmDListTpl.h

+ 612
- 0
cmDList.c View File

@@ -0,0 +1,612 @@
1
+#include "cmGlobal.h"
2
+#include "cmRpt.h"
3
+#include "cmErr.h"
4
+#include "cmCtx.h"
5
+#include "cmMem.h"
6
+#include "cmMallocDebug.h"
7
+#include "cmDList.h"
8
+
9
+
10
+typedef struct cmDListRecd_str
11
+{
12
+  void*                   dV;
13
+  unsigned                dN;
14
+  struct cmDListRecd_str* prev;
15
+  struct cmDListRecd_str* next;
16
+} cmDListRecd_t;
17
+
18
+typedef struct cmDListIndexRecd_str
19
+{
20
+  cmDListRecd_t*               r;
21
+  struct cmDListIndexRecd_str* prev;
22
+  struct cmDListIndexRecd_str* next;
23
+} cmDListIndexRecd_t;
24
+
25
+typedef struct cmDListIndex_str
26
+{
27
+  unsigned                 id;
28
+  cmDListCmpFunc_t         cmpFunc;
29
+  void*                    funcArg;
30
+  cmDListIndexFreeFunc_t   freeFunc;
31
+  cmDListIndexRecd_t*      first;
32
+  cmDListIndexRecd_t*      last;
33
+  unsigned                 recdN;
34
+  struct cmDListIndex_str* link;
35
+} cmDListIndex_t;
36
+
37
+
38
+struct cmDList_str;
39
+
40
+typedef struct cmDListIter_str
41
+{
42
+  struct cmDList_str*     p;
43
+  cmDListIndex_t*         x;
44
+  cmDListIndexRecd_t*     s;
45
+  struct cmDListIter_str* link;
46
+} cmDListIter_t;
47
+
48
+typedef struct cmDList_str
49
+{
50
+  cmErr_t err;
51
+  cmDListRecd_t*  first;    
52
+  cmDListRecd_t*  last;
53
+  unsigned        recdN; 
54
+  
55
+  cmDListIndex_t* indexes;
56
+  cmDListIter_t*  iters;
57
+} cmDList_t;
58
+
59
+cmDListH_t     cmDListNullHandle      = cmSTATIC_NULL_HANDLE;
60
+cmDListIterH_t cmDListIterNullHandle  = cmSTATIC_NULL_HANDLE;
61
+
62
+cmDList_t* _cmDListHandleToPtr( cmDListH_t h )
63
+{
64
+  cmDList_t* p = (cmDList_t*)h.h;
65
+  assert( p!=NULL );
66
+  return p;
67
+}
68
+
69
+cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
70
+{
71
+  cmDListIndex_t* x = p->indexes;
72
+  for(; x!=NULL; x=x->link)
73
+    if( x->id == indexId )
74
+      return x;
75
+  
76
+  return NULL;
77
+}
78
+
79
+void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
80
+{
81
+  unsigned i;
82
+  for(i=0; i<n; ++i)
83
+  {
84
+    cmDListIndexRecd_t* s = cmMemAllocZ(cmDListIndexRecd_t,1);
85
+    s->prev = x->last;
86
+    
87
+    if( x->last != NULL )
88
+      x->last->next = s;
89
+    else
90
+    {
91
+      assert( x->first == NULL );
92
+      x->first = s;
93
+    }
94
+
95
+    x->last = s;
96
+  }
97
+
98
+  x->recdN += n;
99
+
100
+}
101
+
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
+void _cmDListRecdFree( cmDList_t* p, cmDListRecd_t* r )
179
+{
180
+  if( r->prev != NULL )
181
+    r->prev->next = r->next;
182
+  else
183
+    p->first = r->next;
184
+
185
+  if( r->next != NULL )
186
+    r->next->prev = r->prev;
187
+  else
188
+    p->last = r->prev;
189
+
190
+  cmMemFree(r);
191
+}
192
+
193
+// Unlink and free the index record s;
194
+void _cmDListIndexRecdFree( cmDListIndex_t* x, cmDListIndexRecd_t* s )
195
+{
196
+  if( s->prev != NULL )
197
+    s->prev->next = s->next;
198
+  else
199
+    x->first = s->next;
200
+
201
+  if( s->next != NULL )
202
+    s->next->prev = s->prev;
203
+  else
204
+    x->last = s->prev;
205
+  
206
+  cmMemFree(s);  
207
+}
208
+
209
+// Unlink and release an index.
210
+void _cmDListIndexFree( cmDList_t* p, cmDListIndex_t* x )
211
+{
212
+  if( x == NULL )
213
+    return;
214
+  
215
+  cmDListIndex_t* x0 = NULL;
216
+  cmDListIndex_t* x1 = p->indexes;
217
+
218
+  // unlink 'x' from p->indexes
219
+  while( x1 != NULL )
220
+  {
221
+    if( x1 == x )
222
+    {
223
+      // x is the first index
224
+      if( x0 == NULL )
225
+      {
226
+        assert( x1 = p->indexes );
227
+        p->indexes = x->link;
228
+      }
229
+      else
230
+      {
231
+        x0->link = x1->link;        
232
+      }
233
+
234
+      break;
235
+    }
236
+    
237
+    x0 = x1;
238
+    x1 = x1->link;
239
+  }
240
+
241
+  // 'x' must have been found
242
+  assert( x1 == x );
243
+
244
+
245
+  // release each index record in 'x'
246
+  cmDListIndexRecd_t* s  = x->first;
247
+  while( s != NULL )
248
+  {
249
+    cmDListIndexRecd_t* ns = s->next;
250
+    cmMemFree(s);
251
+    s = ns;
252
+  }
253
+
254
+  if( x->freeFunc != NULL )
255
+    x->freeFunc(x->id,x->funcArg);
256
+  
257
+  cmMemFree(x);
258
+
259
+}
260
+
261
+// Unlink and release the iterator 'e'.
262
+cmDlRC_t _cmDListIterFree( cmDListIter_t* e )
263
+{
264
+  cmDList_t*     p  = e->p;
265
+  cmDListIter_t* e0 = NULL;
266
+  cmDListIter_t* e1 = p->iters;
267
+  
268
+  while( e1 != NULL )
269
+  {
270
+    if( e1 == e )
271
+    {
272
+      if( e0 == NULL )
273
+        p->iters = e1->link;
274
+      else
275
+        e0->link = e1->link;
276
+
277
+      cmMemFree(e0);
278
+      break;
279
+    }
280
+
281
+    e0 = e1;
282
+    e1 = e1->link;
283
+  }
284
+
285
+  if( e1 == NULL )
286
+    return cmErrMsg(&p->err,kIterNotFoundDlRC,"The delete target iterator could not be found.");
287
+
288
+  return kOkDlRC;  
289
+}
290
+
291
+cmDlRC_t _cmDListFree( cmDList_t* p )
292
+{
293
+  cmDlRC_t rc = kOkDlRC;
294
+
295
+  // release all indexes
296
+  while( p->indexes != NULL )
297
+    _cmDListIndexFree(p,p->indexes);
298
+
299
+  while( p->iters != NULL )
300
+    _cmDListIterFree(p->iters);
301
+
302
+  // release all data records
303
+  while( p->first != NULL )
304
+    _cmDListRecdFree(p,p->first);
305
+
306
+  cmMemFree(p);
307
+  return rc;
308
+}
309
+
310
+cmDlRC_t _cmDListIndexAlloc( cmDList_t* p, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
311
+{
312
+  cmDListIndex_t* x;
313
+
314
+  if((x =_cmDListIdToIndex(p, indexId )) != NULL )
315
+    return cmErrMsg(&p->err,kDuplicateIndexIdDlRC,"The indexId '%i' has already been used.",indexId);
316
+
317
+  x = cmMemAllocZ(cmDListIndex_t,1);
318
+
319
+  x->id      = indexId;
320
+  x->cmpFunc = func;
321
+  x->funcArg = funcArg;
322
+  x->link    = p->indexes;
323
+  p->indexes = x;
324
+
325
+  
326
+  _cmDListIndexAllocRecds(x,p->recdN);
327
+  _cmDListIndexUpdate(p,x);
328
+
329
+  return kOkDlRC;
330
+  
331
+}
332
+
333
+cmDlRC_t cmDListAlloc( cmCtx_t* ctx, cmDListH_t* hp, cmDListCmpFunc_t func, void* funcArg )
334
+{
335
+  cmDlRC_t rc = kOkDlRC;
336
+  
337
+  if((rc = cmDListFree(hp)) != kOkDlRC )
338
+    return rc;
339
+
340
+  cmDList_t* p = cmMemAllocZ(cmDList_t,1);
341
+  cmErrSetup(&p->err,&ctx->rpt,"cmDList");
342
+
343
+  if( func!=NULL )
344
+    if((rc = _cmDListIndexAlloc(p,0,func,funcArg)) != kOkDlRC )
345
+      goto errLabel; 
346
+
347
+  hp->h = p;
348
+
349
+ errLabel:
350
+  if( rc != kOkDlRC )
351
+    _cmDListFree(p);
352
+
353
+  return rc;
354
+}
355
+
356
+cmDlRC_t cmDListFree(   cmDListH_t* hp )
357
+{
358
+  cmDlRC_t rc;
359
+
360
+  if( hp==NULL || cmDListIsValid(*hp)==false)
361
+    return kOkDlRC;
362
+
363
+  cmDList_t* p = _cmDListHandleToPtr(*hp);
364
+
365
+  if((rc = _cmDListFree(p)) != kOkDlRC )
366
+    return rc;
367
+
368
+  hp->h = NULL;
369
+
370
+  return rc;  
371
+}
372
+
373
+bool     cmDListIsValid( cmDListH_t h )
374
+{ return h.h != NULL; }
375
+
376
+cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN )
377
+{
378
+  cmDList_t*     p  = _cmDListHandleToPtr(h);
379
+  char*          vp = cmMemAllocZ(char,sizeof(cmDListRecd_t) + recdByteN );
380
+  cmDListRecd_t* r  = (cmDListRecd_t*)vp;
381
+  
382
+  r->dV = r + 1;
383
+  r->dN = recdByteN;
384
+  memcpy( r->dV, recd, recdByteN );
385
+
386
+  // Add records at the end of the list.
387
+
388
+  // If the list is not empty
389
+  if( p->last != NULL )
390
+    p->last->next = r;
391
+  else
392
+  {
393
+    // The list was empty
394
+    assert( p->first == NULL );
395
+    p->first = r;
396
+  }
397
+
398
+  r->prev   = p->last;
399
+  r->next   = NULL;
400
+  p->last   = r;
401
+  p->recdN += 1;
402
+
403
+  // update the indexes
404
+  cmDListIndex_t* x = p->indexes;
405
+  for(; x!=NULL; x=x->link)
406
+  {
407
+    _cmDListIndexAllocRecds(x,1);
408
+    _cmDListIndexUpdate(p,x);
409
+  }
410
+  
411
+  return kOkDlRC;
412
+}
413
+
414
+cmDlRC_t cmDListDelete( cmDListH_t  h, const void* recd )
415
+{
416
+  cmDList_t*      p = _cmDListHandleToPtr(h);
417
+  cmDListIndex_t* x = p->indexes;
418
+  cmDListIndexRecd_t* s = NULL;
419
+  cmDListRecd_t* r = NULL;
420
+  
421
+  for(; x!=NULL; x=x->link)
422
+  {
423
+    for(s=x->first; s!=NULL; s=s->next)
424
+      if( s->r->dV == recd )
425
+      {
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
+        
436
+        break;
437
+      }
438
+
439
+    if( r == NULL )
440
+      return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The delete target data record could not be found.");
441
+    
442
+    // if the indexes are valid then the recd should always be found
443
+    assert( s!=NULL );
444
+  }
445
+
446
+  // release the data record
447
+  _cmDListRecdFree(p,r);
448
+
449
+  return kOkDlRC;
450
+  
451
+}
452
+
453
+cmDlRC_t cmDListIndexAlloc( cmDListH_t h, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
454
+{
455
+  cmDList_t*      p = _cmDListHandleToPtr(h);
456
+  return _cmDListIndexAlloc(p,indexId,func,funcArg);
457
+}
458
+
459
+cmDlRC_t cmDListIndexFree( cmDListH_t h, unsigned indexId )
460
+{
461
+  cmDList_t*      p = _cmDListHandleToPtr(h);
462
+  cmDListIndex_t* x;
463
+  if((x = _cmDListIdToIndex(p,indexId)) == NULL )
464
+    return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
465
+
466
+  _cmDListIndexFree(p,x);
467
+
468
+  return kOkDlRC;
469
+}
470
+
471
+cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFreeFunc_t func )
472
+{
473
+  cmDList_t* p = _cmDListHandleToPtr(h);
474
+  cmDListIndex_t* x;
475
+  if((x = _cmDListIdToIndex(p,indexId)) == NULL )
476
+    return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
477
+
478
+  x->freeFunc = func;
479
+  return kOkDlRC;
480
+}
481
+
482
+
483
+cmDListIter_t* _cmDListIterHandleToPtr( cmDListIterH_t h )
484
+{
485
+  cmDListIter_t* e = (cmDListIter_t*)h.h;
486
+  assert(e != NULL );
487
+  return e;
488
+}
489
+
490
+cmDlRC_t    cmDListIterAlloc( cmDListH_t h, cmDListIterH_t* iHp, unsigned indexId )
491
+{
492
+  cmDlRC_t       rc = kOkDlRC;
493
+  cmDList_t*      p = _cmDListHandleToPtr(h);
494
+  cmDListIndex_t* x;
495
+
496
+  if((rc = cmDListIterFree(iHp)) != kOkDlRC )
497
+    return rc;
498
+  
499
+  if((x = _cmDListIdToIndex(p, indexId)) == NULL )
500
+    return cmErrMsg(&p->err,kInvalidIndexDlRC,"The indexId '%i' could not be found.",indexId);
501
+
502
+  cmDListIter_t* e = cmMemAllocZ(cmDListIter_t,1);
503
+
504
+  e->p     = p;
505
+  e->x     = x;
506
+  e->s     = x->first;
507
+  e->link  = p->iters;
508
+  p->iters = e;
509
+
510
+  iHp->h = e;
511
+
512
+  return rc;
513
+  
514
+}
515
+
516
+cmDlRC_t    cmDListIterFree(  cmDListIterH_t* iHp )
517
+{
518
+  cmDlRC_t rc;
519
+  
520
+  if( iHp==NULL || cmDListIterIsValid(*iHp)==false )
521
+    return kOkDlRC;
522
+
523
+  cmDListIter_t* e = _cmDListIterHandleToPtr(*iHp);
524
+
525
+  if(( rc = _cmDListIterFree( e )) != kOkDlRC )
526
+    return rc;
527
+
528
+  iHp->h = NULL;
529
+  
530
+  return rc;  
531
+}
532
+
533
+bool        cmDListIterIsValid( cmDListIterH_t iH )
534
+{ return iH.h != NULL; }
535
+
536
+
537
+cmDlRC_t    cmDListIterSeekBegin( cmDListIterH_t  iH )
538
+{
539
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
540
+  e->s = e->x->first;
541
+  return kOkDlRC;
542
+}
543
+
544
+cmDlRC_t    cmDListIterSeekLast( cmDListIterH_t  iH )
545
+{
546
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
547
+  e->s = e->x->last;
548
+  return kOkDlRC;
549
+}
550
+
551
+const void* _cmDListIterGet(   cmDListIter_t*  e, unsigned* recdByteNRef )
552
+{
553
+  if( e->s == NULL )
554
+  {
555
+    if( recdByteNRef != NULL )
556
+      *recdByteNRef = 0;
557
+    return NULL;
558
+  }
559
+
560
+  if( recdByteNRef != NULL )
561
+    *recdByteNRef = e->s->r->dN;
562
+
563
+  return e->s->r->dN==0 ? NULL : e->s->r->dV;
564
+}
565
+
566
+const void* cmDListIterGet(   cmDListIterH_t  iH, unsigned* recdByteNRef )
567
+{
568
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
569
+
570
+  return _cmDListIterGet(e,recdByteNRef);
571
+}
572
+
573
+const void* cmDListIterPrev(  cmDListIterH_t  iH, unsigned* recdByteNRef )
574
+{
575
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
576
+  const void*   rv = _cmDListIterGet(e,recdByteNRef);
577
+
578
+  if( e->s != NULL )
579
+    e->s = e->s->prev;
580
+
581
+  return rv;
582
+}
583
+
584
+const void* cmDListIterNext( cmDListIterH_t  iH, unsigned* recdByteNRef )
585
+{
586
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
587
+  const void*   rv = _cmDListIterGet(e,recdByteNRef);
588
+
589
+  if( e->s != NULL )
590
+    e->s = e->s->next;
591
+
592
+  return rv;
593
+}
594
+
595
+const void* cmDListIterFind( cmDListIterH_t  iH, const void* key, unsigned keyN, unsigned* recdByteNRef)
596
+{
597
+  cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
598
+
599
+  cmDListIndexRecd_t* s = e->s;
600
+
601
+  for(; s!=NULL; s=s->next)
602
+    if( e->x->cmpFunc( e->x->funcArg, s->r->dV, s->r->dN, key, keyN ) == 0 )
603
+    {
604
+      e->s = s;
605
+      return _cmDListIterGet(e,recdByteNRef);
606
+    }
607
+
608
+  if( recdByteNRef != NULL )
609
+    *recdByteNRef = 0;
610
+
611
+  return NULL;
612
+}

+ 61
- 0
cmDList.h View File

@@ -0,0 +1,61 @@
1
+
2
+#ifndef cmDList_h
3
+#define cmDList_h
4
+
5
+#ifdef __cplusplus
6
+extern "C" {
7
+#endif
8
+
9
+  enum
10
+  {
11
+    kOkDlRC = cmOkRC,
12
+    kDuplicateIndexIdDlRC,
13
+    kInvalidIndexDlRC,
14
+    kIterNotFoundDlRC,
15
+    kDataRecdNotFoundDlRC,
16
+    
17
+  };
18
+
19
+  typedef unsigned   cmDlRC_t;
20
+  typedef cmHandle_t cmDListH_t;
21
+  typedef cmHandle_t cmDListIterH_t;
22
+
23
+  extern cmDListH_t     cmDListNullHandle;
24
+  extern cmDListIterH_t cmDListIterNullHandle;
25
+
26
+  // Return <  0 if v0 <  v1
27
+  //        == 0 if v0 == v1
28
+  //        >  0 if v0 >  v1
29
+  typedef int (*cmDListCmpFunc_t)( void* arg, const void* v0, unsigned v0N, const void* v1, unsigned v1N );
30
+  
31
+  typedef void (*cmDListIndexFreeFunc_t)( unsigned indexId, void* arg );
32
+
33
+  // If 'f' is not NULL then a default index with an indexId==0 will be automatically created.
34
+  cmDlRC_t cmDListAlloc( cmCtx_t* ctx, cmDListH_t* hp, cmDListCmpFunc_t f, void* farg );
35
+  cmDlRC_t cmDListFree(   cmDListH_t* hp );
36
+  bool     cmDListIsValid( cmDListH_t h );
37
+  cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN );
38
+  cmDlRC_t cmDListDelete( cmDListH_t  h, const void* recd );
39
+
40
+  
41
+  cmDlRC_t cmDListIndexAlloc(   cmDListH_t h, unsigned indexId, cmDListCmpFunc_t f, void* farg );
42
+  cmDlRC_t cmDListIndexFree(    cmDListH_t h, unsigned indexId );
43
+  cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFreeFunc_t func );
44
+
45
+ 
46
+  cmDlRC_t    cmDListIterAlloc( cmDListH_t h, cmDListIterH_t* iHp, unsigned indexId );
47
+  cmDlRC_t    cmDListIterFree(      cmDListIterH_t* iHp );
48
+  bool        cmDListIterIsValid(   cmDListIterH_t  iH );
49
+  cmDlRC_t    cmDListIterSeekBegin( cmDListIterH_t  iH );
50
+  cmDlRC_t    cmDListIterSeekEnd(   cmDListIterH_t  iH );
51
+  const void* cmDListIterGet(       cmDListIterH_t  iH, unsigned* recdByteNRef );
52
+  const void* cmDListIterPrev(      cmDListIterH_t  iH, unsigned* recdByteNRef );
53
+  const void* cmDListIterNext(      cmDListIterH_t  iH, unsigned* recdByteNRef );
54
+  const void* cmDListIterFind(      cmDListIterH_t  iH, const void* key, unsigned keyN, unsigned* recdByteNRef);
55
+
56
+
57
+#ifdef __cplusplus
58
+}
59
+#endif
60
+
61
+#endif

+ 122
- 0
cmDListTpl.h View File

@@ -0,0 +1,122 @@
1
+
2
+// The following two macros must be defined prior to including this code:
3
+// #define cmSFX(a) a##_MySuffix
4
+// #define cmTYPE   My_Type 
5
+
6
+// Also define cmGEN_HDR to generate the .h code and/or
7
+// cmGEN_CODE to generate the .c code
8
+
9
+#ifdef cmGEN_HDR
10
+
11
+typedef int (*cmSFX(cmDListFunc))( void* arg, const cmTYPE* v0, const cmTYPE* v1 );
12
+
13
+cmDlRC_t cmSFX(cmDListAlloc)( cmCtx_t* ctx, cmDListH_t* hp, cmSFX(cmDListFunc) func, void* funcArg );
14
+
15
+cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd );
16
+cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd );
17
+
18
+cmDlRC_t cmSFX(cmDListAllocIndex)( cmDListH_t h, unsigned indexId, cmSFX(cmDListFunc) f, void* farg );
19
+
20
+const cmTYPE* cmSFX(cmDListIterGet)(       cmDListIterH_t  iH );
21
+const cmTYPE* cmSFX(cmDListIterPrev)(      cmDListIterH_t  iH );
22
+const cmTYPE* cmSFX(cmDListIterNext)(      cmDListIterH_t  iH );
23
+const cmTYPE* cmSFX(cmDListIterFind)(      cmDListIterH_t  iH, const cmTYPE* key);
24
+
25
+#endif // cmGEN_HDR
26
+
27
+
28
+#ifdef cmGEN_CODE
29
+
30
+typedef struct
31
+{
32
+  cmSFX(cmDListFunc) func;
33
+  void*               funcArg;
34
+} cmSFX(_cmDListArg);
35
+
36
+// This function is called when the index identified by indexId is about to be deleted.
37
+// It is used to cleanup the arg record created by cmSFX(cmDListIndexAlloc()).
38
+void cmSFX(_cmDListIndexOnFree)( unsigned indexId, void* arg )
39
+{
40
+  cmMemFree(arg);
41
+}
42
+
43
+// Proxy function used to cast generic compare function to the user defined compare function.
44
+int cmSFX(_cmDListCmp)( void* arg, const void* v0, unsigned vn0, const void* v1, unsigned vn1 )
45
+{
46
+  assert(vn0==vn1 && sizeof(cmTYPE)==vn0);
47
+  cmSFX(_cmDListArg)* a = (cmSFX(_cmDListArg)*)arg;
48
+  return a->func(a->funcArg,(const cmTYPE*)v0,(const cmTYPE*)v1);
49
+}
50
+
51
+cmDlRC_t cmSFX(cmDListAlloc)( cmCtx_t* ctx, cmDListH_t* hp, cmSFX(cmDListFunc) func, void* funcArg )
52
+{
53
+  cmDlRC_t rc;
54
+  cmSFX(_cmDListArg)* a = NULL;
55
+
56
+  if( func != NULL )
57
+  {
58
+    // allocate a record to redirect the compare function callback
59
+    a = cmMemAllocZ(cmSFX(_cmDListArg),1);
60
+    a->func    = func;
61
+    a->funcArg = funcArg;
62
+  }
63
+  
64
+  if((rc = cmDListAlloc(ctx,hp,cmSFX(_cmDListCmp),a)) != kOkDlRC )
65
+    return rc;
66
+
67
+  if( func != NULL )
68
+    if((rc = cmDListIndexSetFreeFunc(*hp,0,cmSFX(_cmDListIndexOnFree))) != kOkDlRC )
69
+      cmDListFree(hp);
70
+
71
+  return rc;
72
+}
73
+
74
+
75
+cmDlRC_t cmSFX(cmDListIndexAlloc)(   cmDListH_t h, unsigned indexId, cmSFX(cmDListFunc) func, void* funcArg )
76
+{
77
+  cmDlRC_t rc;
78
+  
79
+  // allocate a record to redirect the compare function callback
80
+  cmSFX(_cmDListArg)* a = cmMemAllocZ(cmSFX(_cmDListArg),1);
81
+  a->func    = func;
82
+  a->funcArg = funcArg;
83
+
84
+  // allocate the index
85
+  if((rc = cmDListIndexAlloc(h,indexId,cmSFX(_cmDListCmp),a)) != kOkDlRC )
86
+  {
87
+    cmMemFree(a);
88
+    goto errLabel;
89
+  }
90
+
91
+  // set the index clean up handler
92
+  if((rc = cmDListIndexSetFreeFunc(h,indexId,cmSFX(_cmDListIndexOnFree))) != kOkDlRC )
93
+    cmDListIndexFree(h,indexId);
94
+  
95
+ errLabel:
96
+  return rc;
97
+}
98
+
99
+cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd )
100
+{ return cmDListInsert(h,recd,sizeof(recd)); }
101
+
102
+cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd )
103
+{ return cmDListDelete(h,recd);  }
104
+
105
+
106
+const cmTYPE* cmSFX(cmDListIterGet)(  cmDListIterH_t  iH )
107
+{ return (const cmTYPE*)cmDListIterGet(iH,NULL);}
108
+
109
+const cmTYPE* cmSFX(cmDListIterPrev)(      cmDListIterH_t  iH )
110
+{ return (const cmTYPE*)cmDListIterPrev(iH,NULL); }
111
+
112
+const cmTYPE* cmSFX(cmDListIterNext)(      cmDListIterH_t  iH )
113
+{ return (const cmTYPE*)cmDListIterNext(iH,NULL); }
114
+
115
+const cmTYPE* cmSFX(cmDListIterFind)(      cmDListIterH_t  iH, const cmTYPE* key)
116
+{  return (const cmTYPE*)cmDListIterFind(iH,key,sizeof(cmTYPE),NULL); }
117
+
118
+#endif // cmGEN_CODE
119
+
120
+
121
+#undef cmSFX
122
+#undef cmTYPE

Loading…
Cancel
Save