00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "dthdr.h"
00018
00019 #ifdef DMALLOC
00020 #include "dmalloc.h"
00021 #endif
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #if __STD_C
00032 static Void_t *dttree(Dt_t * dt, Void_t * obj, int type)
00033 #else
00034 static Void_t *dttree(dt, obj, type)
00035 Dt_t *dt;
00036 Void_t *obj;
00037 int type;
00038 #endif
00039 {
00040 reg Dtlink_t *root, *t;
00041 reg int cmp, lk, sz, ky;
00042 reg Void_t *k, *key;
00043 reg Dtcompar_f cmpf;
00044 reg Dtdisc_t *disc;
00045 reg Dtlink_t *l, *r, *me;
00046 Dtlink_t link;
00047
00048 me = 0;
00049 UNFLATTEN(dt);
00050 INITDISC(dt, disc, ky, sz, lk, cmpf);
00051
00052 root = dt->data->here;
00053 if (!obj) {
00054 if (!root || !(type & (DT_CLEAR | DT_FIRST | DT_LAST)))
00055 return NIL(Void_t *);
00056
00057 if (type & DT_CLEAR) {
00058 if (disc->freef || disc->link < 0) {
00059 do {
00060 while ((t = root->left))
00061 RROTATE(root, t);
00062 t = root->right;
00063 if (disc->freef)
00064 (*disc->freef) (dt, OBJ(root, lk), disc);
00065 if (disc->link < 0)
00066 (*dt->memoryf) (dt, (Void_t *) root, 0, disc);
00067 } while ((root = t));
00068 }
00069
00070 dt->data->size = 0;
00071 dt->data->here = NIL(Dtlink_t *);
00072 return NIL(Void_t *);
00073 } else {
00074 if (type & DT_LAST) {
00075 while ((t = root->right))
00076 LROTATE(root, t);
00077 } else {
00078 while ((t = root->left))
00079 RROTATE(root, t);
00080 }
00081
00082 dt->data->here = root;
00083 return OBJ(root, lk);
00084 }
00085 }
00086
00087
00088 l = r = &link;
00089
00090 if (type & (DT_MATCH | DT_SEARCH | DT_INSERT | DT_ATTACH)) {
00091 key = (type & DT_MATCH) ? obj : KEY(obj, ky, sz);
00092 if (root)
00093 goto do_search;
00094 } else if (type & DT_RENEW) {
00095 me = (Dtlink_t *) obj;
00096 obj = OBJ(me, lk);
00097 key = KEY(obj, ky, sz);
00098 if (root)
00099 goto do_search;
00100 } else if (root && OBJ(root, lk) != obj) {
00101 key = KEY(obj, ky, sz);
00102 do_search:
00103 while (1) {
00104 k = OBJ(root, lk);
00105 k = KEY(k, ky, sz);
00106 if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) == 0)
00107 break;
00108 else if (cmp < 0) {
00109 if ((t = root->left)) {
00110 k = OBJ(t, lk);
00111 k = KEY(k, ky, sz);
00112 if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) < 0) {
00113 RROTATE(root, t);
00114 RLINK(r, root);
00115 if (!(root = root->left))
00116 break;
00117 } else if (cmp == 0) {
00118 RROTATE(root, t);
00119 break;
00120 } else {
00121 LLINK(l, t);
00122 RLINK(r, root);
00123 if (!(root = t->right))
00124 break;
00125 }
00126 } else {
00127 RLINK(r, root);
00128 root = NIL(Dtlink_t *);
00129 break;
00130 }
00131 } else {
00132 if ((t = root->right)) {
00133 k = OBJ(t, lk);
00134 k = KEY(k, ky, sz);
00135 if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) > 0) {
00136 LROTATE(root, t);
00137 LLINK(l, root);
00138 if (!(root = root->right))
00139 break;
00140 } else if (cmp == 0) {
00141 LROTATE(root, t);
00142 break;
00143 } else {
00144 RLINK(r, t);
00145 LLINK(l, root);
00146 if (!(root = t->left))
00147 break;
00148 }
00149 } else {
00150 LLINK(l, root);
00151 root = NIL(Dtlink_t *);
00152 break;
00153 }
00154 }
00155 }
00156 }
00157
00158 if (root) {
00159 l->right = root->left;
00160 r->left = root->right;
00161
00162 if (type & (DT_SEARCH | DT_MATCH)) {
00163 has_root:
00164 root->left = link.right;
00165 root->right = link.left;
00166 if ((dt->meth->type & DT_OBAG)
00167 && (type & (DT_SEARCH | DT_MATCH))) {
00168 key = OBJ(root, lk);
00169 key = KEY(key, ky, sz);
00170 while ((t = root->left)) {
00171 k = OBJ(t, lk);
00172 k = KEY(k, ky, sz);
00173 if (CMP(dt, key, k, disc, cmpf, sz) != 0)
00174 break;
00175 RROTATE(root, t);
00176 }
00177 }
00178 dt->data->here = root;
00179 return OBJ(root, lk);
00180 } else if (type & DT_NEXT) {
00181 root->left = link.right;
00182 root->right = NIL(Dtlink_t *);
00183 link.right = root;
00184 dt_next:
00185 if ((root = link.left)) {
00186 while ((t = root->left))
00187 RROTATE(root, t);
00188 link.left = root->right;
00189 goto has_root;
00190 } else
00191 goto no_root;
00192 } else if (type & DT_PREV) {
00193 root->right = link.left;
00194 root->left = NIL(Dtlink_t *);
00195 link.left = root;
00196 dt_prev:
00197 if ((root = link.right)) {
00198 while ((t = root->right))
00199 LROTATE(root, t);
00200 link.right = root->left;
00201 goto has_root;
00202 } else
00203 goto no_root;
00204 } else if (type & (DT_DELETE | DT_DETACH)) {
00205 obj = OBJ(root, lk);
00206 if (disc->freef && (type & DT_DELETE))
00207 (*disc->freef) (dt, obj, disc);
00208 if (disc->link < 0)
00209 (*dt->memoryf) (dt, (Void_t *) root, 0, disc);
00210 if ((dt->data->size -= 1) < 0)
00211 dt->data->size = -1;
00212 goto no_root;
00213 } else if (type & (DT_INSERT | DT_ATTACH)) {
00214 if (dt->meth->type & DT_OSET)
00215 goto has_root;
00216 else {
00217 root->left = NIL(Dtlink_t *);
00218 root->right = link.left;
00219 link.left = root;
00220 goto dt_insert;
00221 }
00222 } else if (type & DT_RENEW) {
00223 if (dt->meth->type & DT_OSET) {
00224 if (disc->freef)
00225 (*disc->freef) (dt, obj, disc);
00226 if (disc->link < 0)
00227 (*dt->memoryf) (dt, (Void_t *) me, 0, disc);
00228 } else {
00229 me->left = NIL(Dtlink_t *);
00230 me->right = link.left;
00231 link.left = me;
00232 dt->data->size += 1;
00233 }
00234 goto has_root;
00235 }
00236 } else {
00237 r->left = NIL(Dtlink_t *);
00238 l->right = NIL(Dtlink_t *);
00239
00240 if (type & (DT_SEARCH | DT_MATCH)) {
00241 no_root:
00242 while ((t = r->left))
00243 r = t;
00244 r->left = link.right;
00245 dt->data->here = link.left;
00246 return (type & DT_DELETE) ? obj : NIL(Void_t *);
00247 } else if (type & (DT_INSERT | DT_ATTACH)) {
00248 dt_insert:
00249 if (disc->makef && (type & DT_INSERT))
00250 obj = (*disc->makef) (dt, obj, disc);
00251 if (obj) {
00252 if (lk >= 0)
00253 root = ELT(obj, lk);
00254 else {
00255 root = (Dtlink_t *) (*dt->memoryf)
00256 (dt, NIL(Void_t *), sizeof(Dthold_t), disc);
00257 if (root)
00258 ((Dthold_t *) root)->obj = obj;
00259 else if (disc->makef && disc->freef &&
00260 (type & DT_INSERT))
00261 (*disc->freef) (dt, obj, disc);
00262 }
00263 }
00264 if (root) {
00265 if (dt->data->size >= 0)
00266 dt->data->size += 1;
00267 goto has_root;
00268 } else
00269 goto no_root;
00270 } else if (type & DT_NEXT)
00271 goto dt_next;
00272 else if (type & DT_PREV)
00273 goto dt_prev;
00274 else if (type & DT_RENEW) {
00275 root = me;
00276 dt->data->size += 1;
00277 goto has_root;
00278 } else {
00279 obj = NIL(Void_t *);
00280 goto no_root;
00281 }
00282 }
00283
00284 return NIL(Void_t *);
00285 }
00286
00287
00288 static Dtmethod_t _Dtoset = { dttree, DT_OSET };
00289 static Dtmethod_t _Dtobag = { dttree, DT_OBAG };
00290
00291 __DEFINE__(Dtmethod_t *, Dtoset, &_Dtoset);
00292 __DEFINE__(Dtmethod_t *, Dtobag, &_Dtobag);
00293
00294 #ifndef KPVDEL
00295 Dtmethod_t _Dttree = { dttree, DT_OSET };
00296
00297 __DEFINE__(Dtmethod_t *, Dtorder, &_Dttree);
00298 __DEFINE__(Dtmethod_t *, Dttree, &_Dttree);
00299 #endif