dtlist.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <cdt/dthdr.h>
  2. #include <stdlib.h>
  3. /* List, Deque, Stack, Queue.
  4. **
  5. ** Written by Kiem-Phong Vo (05/25/96)
  6. */
  7. static void* dtlist(Dt_t* dt, void* obj, int type)
  8. {
  9. int lk, sz, ky;
  10. Dtcompar_f cmpf;
  11. Dtdisc_t* disc;
  12. Dtlink_t *r, *t;
  13. void *key, *k;
  14. UNFLATTEN(dt);
  15. disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf);
  16. if(!obj)
  17. { if(type&(DT_LAST|DT_FIRST) )
  18. { if((r = dt->data->head) )
  19. { if(type&DT_LAST)
  20. r = r->left;
  21. dt->data->here = r;
  22. }
  23. return r ? _DTOBJ(r,lk) : NULL;
  24. }
  25. else if(type&(DT_DELETE|DT_DETACH))
  26. { if(!(r = dt->data->head))
  27. return NULL;
  28. else goto dt_delete;
  29. }
  30. else if(type&DT_CLEAR)
  31. { if(disc->freef || disc->link < 0)
  32. { for(r = dt->data->head; r; r = t)
  33. { t = r->right;
  34. if(disc->freef)
  35. disc->freef(_DTOBJ(r, lk));
  36. if(disc->link < 0)
  37. free(r);
  38. }
  39. }
  40. dt->data->head = dt->data->here = NULL;
  41. dt->data->size = 0;
  42. return NULL;
  43. }
  44. else return NULL;
  45. }
  46. if(type&DT_INSERT)
  47. { if (disc->makef && (type&DT_INSERT) && !(obj = disc->makef(obj, disc)))
  48. return NULL;
  49. if(lk >= 0)
  50. r = _DTLNK(obj,lk);
  51. else
  52. { r = malloc(sizeof(Dthold_t));
  53. if(r)
  54. ((Dthold_t*)r)->obj = obj;
  55. else
  56. { if(disc->makef && disc->freef && (type&DT_INSERT))
  57. disc->freef(obj);
  58. return NULL;
  59. }
  60. }
  61. /* if(dt->data->type&DT_QUEUE) */
  62. if((t = dt->data->head) )
  63. { t->left->right = r;
  64. r->left = t->left;
  65. t->left = r;
  66. }
  67. else
  68. { dt->data->head = r;
  69. r->left = r;
  70. }
  71. r->right = NULL;
  72. if(dt->data->size >= 0)
  73. dt->data->size += 1;
  74. dt->data->here = r;
  75. return _DTOBJ(r,lk);
  76. }
  77. if((type&DT_MATCH) || !(r = dt->data->here) || _DTOBJ(r,lk) != obj)
  78. { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz);
  79. for(r = dt->data->head; r; r = r->right)
  80. { k = _DTOBJ(r,lk); k = _DTKEY(k,ky,sz);
  81. if(_DTCMP(key, k, cmpf, sz) == 0)
  82. break;
  83. }
  84. }
  85. if(!r)
  86. return NULL;
  87. if(type&(DT_DELETE|DT_DETACH))
  88. { dt_delete:
  89. if(r->right)
  90. r->right->left = r->left;
  91. if(r == (t = dt->data->head) )
  92. { dt->data->head = r->right;
  93. if(dt->data->head)
  94. dt->data->head->left = t->left;
  95. }
  96. else
  97. { r->left->right = r->right;
  98. if(r == t->left)
  99. t->left = r->left;
  100. }
  101. dt->data->here = r == dt->data->here ? r->right : NULL;
  102. dt->data->size -= 1;
  103. obj = _DTOBJ(r,lk);
  104. if(disc->freef && (type&DT_DELETE))
  105. disc->freef(obj);
  106. if(disc->link < 0)
  107. free(r);
  108. return obj;
  109. }
  110. else if(type&DT_NEXT)
  111. r = r->right;
  112. else if(type&DT_PREV)
  113. r = r == dt->data->head ? NULL : r->left;
  114. dt->data->here = r;
  115. return r ? _DTOBJ(r,lk) : NULL;
  116. }
  117. Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE };
  118. Dtmethod_t* Dtqueue = &_Dtqueue;