1 | #include "dthdr.h" |
2 | |
3 | /* List, Deque, Stack, Queue. |
4 | ** |
5 | ** Written by Kiem-Phong Vo (05/25/96) |
6 | */ |
7 | |
8 | static void* dtlist(reg Dt_t* dt, reg void* obj, reg int type) |
9 | { |
10 | reg int lk, sz, ky; |
11 | reg Dtcompar_f cmpf; |
12 | reg Dtdisc_t* disc; |
13 | reg Dtlink_t *r, *t; |
14 | reg void *key, *k; |
15 | |
16 | UNFLATTEN(dt); |
17 | disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf); |
18 | dt->type &= ~DT_FOUND; |
19 | |
20 | if(!obj) |
21 | { if(type&(DT_LAST|DT_FIRST) ) |
22 | { if((r = dt->data->head) ) |
23 | { if(type&DT_LAST) |
24 | r = r->left; |
25 | dt->data->here = r; |
26 | } |
27 | return r ? _DTOBJ(r,lk) : NIL(void*); |
28 | } |
29 | else if(type&(DT_DELETE|DT_DETACH)) |
30 | { if((dt->data->type&(DT_LIST|DT_DEQUE)) || !(r = dt->data->head)) |
31 | return NIL(void*); |
32 | else goto dt_delete; |
33 | } |
34 | else if(type&DT_CLEAR) |
35 | { if(disc->freef || disc->link < 0) |
36 | { for(r = dt->data->head; r; r = t) |
37 | { t = r->right; |
38 | if(disc->freef) |
39 | (*disc->freef)(dt,_DTOBJ(r,lk),disc); |
40 | if(disc->link < 0) |
41 | (*dt->memoryf)(dt,(void*)r,0,disc); |
42 | } |
43 | } |
44 | dt->data->head = dt->data->here = NIL(Dtlink_t*); |
45 | dt->data->size = 0; |
46 | return NIL(void*); |
47 | } |
48 | else return NIL(void*); |
49 | } |
50 | |
51 | if(type&(DT_INSERT|DT_ATTACH)) |
52 | { if(disc->makef && (type&DT_INSERT) && |
53 | !(obj = (*disc->makef)(dt,obj,disc)) ) |
54 | return NIL(void*); |
55 | if(lk >= 0) |
56 | r = _DTLNK(obj,lk); |
57 | else |
58 | { r = (Dtlink_t*)(*dt->memoryf) |
59 | (dt,NIL(void*),sizeof(Dthold_t),disc); |
60 | if(r) |
61 | ((Dthold_t*)r)->obj = obj; |
62 | else |
63 | { if(disc->makef && disc->freef && (type&DT_INSERT)) |
64 | (*disc->freef)(dt,obj,disc); |
65 | return NIL(void*); |
66 | } |
67 | } |
68 | |
69 | if(dt->data->type&DT_DEQUE) |
70 | { if(type&DT_APPEND) |
71 | goto dt_queue; |
72 | else goto dt_stack; |
73 | } |
74 | else if(dt->data->type&DT_LIST) |
75 | { if(type&DT_APPEND) |
76 | { if(!(t = dt->data->here) || !t->right) |
77 | goto dt_queue; |
78 | r->right = t->right; |
79 | r->right->left = r; |
80 | r->left = t; |
81 | r->left->right = r; |
82 | } |
83 | else |
84 | { if(!(t = dt->data->here) || t == dt->data->head) |
85 | goto dt_stack; |
86 | r->left = t->left; |
87 | r->left->right = r; |
88 | r->right = t; |
89 | r->right->left = r; |
90 | } |
91 | } |
92 | else if(dt->data->type&DT_STACK) |
93 | { dt_stack: |
94 | r->right = t = dt->data->head; |
95 | if(t) |
96 | { r->left = t->left; |
97 | t->left = r; |
98 | } |
99 | else r->left = r; |
100 | dt->data->head = r; |
101 | } |
102 | else /* if(dt->data->type&DT_QUEUE) */ |
103 | { dt_queue: |
104 | if((t = dt->data->head) ) |
105 | { t->left->right = r; |
106 | r->left = t->left; |
107 | t->left = r; |
108 | } |
109 | else |
110 | { dt->data->head = r; |
111 | r->left = r; |
112 | } |
113 | r->right = NIL(Dtlink_t*); |
114 | } |
115 | |
116 | if(dt->data->size >= 0) |
117 | dt->data->size += 1; |
118 | |
119 | dt->data->here = r; |
120 | return _DTOBJ(r,lk); |
121 | } |
122 | |
123 | if((type&DT_MATCH) || !(r = dt->data->here) || _DTOBJ(r,lk) != obj) |
124 | { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz); |
125 | for(r = dt->data->head; r; r = r->right) |
126 | { k = _DTOBJ(r,lk); k = _DTKEY(k,ky,sz); |
127 | if(_DTCMP(dt,key,k,disc,cmpf,sz) == 0) |
128 | break; |
129 | } |
130 | } |
131 | |
132 | if(!r) |
133 | return NIL(void*); |
134 | dt->type |= DT_FOUND; |
135 | |
136 | if(type&(DT_DELETE|DT_DETACH)) |
137 | { dt_delete: |
138 | if(r->right) |
139 | r->right->left = r->left; |
140 | if(r == (t = dt->data->head) ) |
141 | { dt->data->head = r->right; |
142 | if(dt->data->head) |
143 | dt->data->head->left = t->left; |
144 | } |
145 | else |
146 | { r->left->right = r->right; |
147 | if(r == t->left) |
148 | t->left = r->left; |
149 | } |
150 | |
151 | dt->data->here = r == dt->data->here ? r->right : NIL(Dtlink_t*); |
152 | dt->data->size -= 1; |
153 | |
154 | obj = _DTOBJ(r,lk); |
155 | if(disc->freef && (type&DT_DELETE)) |
156 | (*disc->freef)(dt,obj,disc); |
157 | if(disc->link < 0) |
158 | (*dt->memoryf)(dt,(void*)r,0,disc); |
159 | return obj; |
160 | } |
161 | else if(type&DT_NEXT) |
162 | r = r->right; |
163 | else if(type&DT_PREV) |
164 | r = r == dt->data->head ? NIL(Dtlink_t*) : r->left; |
165 | |
166 | dt->data->here = r; |
167 | return r ? _DTOBJ(r,lk) : NIL(void*); |
168 | } |
169 | |
170 | #ifndef KPVDEL /* to be remove next round */ |
171 | #define static |
172 | #endif |
173 | static Dtmethod_t _Dtlist = { dtlist, DT_LIST }; |
174 | static Dtmethod_t _Dtdeque = { dtlist, DT_DEQUE }; |
175 | static Dtmethod_t _Dtstack = { dtlist, DT_STACK }; |
176 | static Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE }; |
177 | |
178 | Dtmethod_t* Dtlist = &_Dtlist; |
179 | Dtmethod_t* Dtdeque = &_Dtdeque; |
180 | Dtmethod_t* Dtstack = &_Dtstack; |
181 | Dtmethod_t* Dtqueue = &_Dtqueue; |
182 | |
183 | #ifdef NoF |
184 | NoF(dtlist) |
185 | #endif |
186 | |