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
00032 #if __STD_C
00033 static void dthtab(Dt_t * dt)
00034 #else
00035 static void dthtab(dt)
00036 Dt_t *dt;
00037 #endif
00038 {
00039 reg Dtlink_t *t, *r, *p, **s, **hs, **is, **olds;
00040 reg int n;
00041
00042
00043 if ((n = dt->data->ntab) == 0)
00044 n = HSLOT;
00045 while (dt->data->size > HLOAD(n))
00046 n = HRESIZE(n);
00047 if (n <= dt->data->ntab)
00048 return;
00049
00050
00051 olds = dt->data->ntab == 0 ? NIL(Dtlink_t **) : dt->data->htab;
00052 if (!
00053 (s =
00054 (Dtlink_t **) (*dt->memoryf) (dt, olds, n * sizeof(Dtlink_t *),
00055 dt->disc)))
00056 return;
00057 olds = s + dt->data->ntab;
00058 dt->data->htab = s;
00059 dt->data->ntab = n;
00060
00061
00062 for (hs = s + n - 1; hs >= olds; --hs)
00063 *hs = NIL(Dtlink_t *);
00064 for (hs = s; hs < olds; ++hs) {
00065 for (p = NIL(Dtlink_t *), t = *hs; t; t = r) {
00066 r = t->right;
00067 if ((is = s + HINDEX(n, t->hash)) == hs)
00068 p = t;
00069 else {
00070 if (p)
00071 p->right = r;
00072 else
00073 *hs = r;
00074 t->right = *is;
00075 *is = t;
00076 }
00077 }
00078 }
00079 }
00080
00081 #if __STD_C
00082 static Void_t *dthash(Dt_t * dt, reg Void_t * obj, int type)
00083 #else
00084 static Void_t *dthash(dt, obj, type)
00085 Dt_t *dt;
00086 reg Void_t *obj;
00087 int type;
00088 #endif
00089 {
00090 reg Dtlink_t *t, *r, *p;
00091 reg Void_t *k, *key;
00092 reg uint hsh;
00093 reg int lk, sz, ky;
00094 reg Dtcompar_f cmpf;
00095 reg Dtdisc_t *disc;
00096 reg Dtlink_t **s, **ends;
00097
00098 r = 0;
00099 s = 0;
00100 UNFLATTEN(dt);
00101 INITDISC(dt, disc, ky, sz, lk, cmpf);
00102
00103 if (!obj) {
00104 if (type & (DT_NEXT | DT_PREV))
00105 goto end_walk;
00106
00107 if (dt->data->size <= 0
00108 || !(type & (DT_CLEAR | DT_FIRST | DT_LAST)))
00109 return NIL(Void_t *);
00110
00111 ends = (s = dt->data->htab) + dt->data->ntab;
00112 if (type & DT_CLEAR) {
00113 for (; s < ends; ++s) {
00114 t = *s;
00115 *s = NIL(Dtlink_t *);
00116 if (!disc->freef && disc->link >= 0)
00117 continue;
00118 while (t) {
00119 r = t->right;
00120 if (disc->freef)
00121 (*disc->freef) (dt, OBJ(t, lk), disc);
00122 if (disc->link < 0)
00123 (*dt->memoryf) (dt, (Void_t *) t, 0, disc);
00124 t = r;
00125 }
00126 }
00127 dt->data->here = NIL(Dtlink_t *);
00128 dt->data->size = 0;
00129 dt->data->loop = 0;
00130 return NIL(Void_t *);
00131 } else {
00132 t = NIL(Dtlink_t *);
00133 while (s < ends && !t)
00134 t = (type & DT_LAST) ? *--ends : *s++;
00135 if (t && (type & DT_LAST))
00136 for (; t->right; t = t->right);
00137
00138 dt->data->loop += 1;
00139 dt->data->here = t;
00140 return t ? OBJ(t, lk) : NIL(Void_t *);
00141 }
00142 }
00143
00144 if (type & (DT_MATCH | DT_SEARCH | DT_INSERT | DT_ATTACH)) {
00145 key = (type & DT_MATCH) ? obj : KEY(obj, ky, sz);
00146 hsh = HASH(dt, key, disc, sz);
00147 goto do_search;
00148 } else if (type & (DT_RENEW | DT_VSEARCH)) {
00149 r = (Dtlink_t *) obj;
00150 obj = OBJ(r, lk);
00151 key = KEY(obj, ky, sz);
00152 hsh = r->hash;
00153 goto do_search;
00154 } else {
00155 if ((t = dt->data->here) && OBJ(t, lk) == obj) {
00156 hsh = t->hash;
00157 s = dt->data->htab + HINDEX(dt->data->ntab, hsh);
00158 p = NIL(Dtlink_t *);
00159 } else {
00160 key = KEY(obj, ky, sz);
00161 hsh = HASH(dt, key, disc, sz);
00162 do_search:
00163 t = dt->data->ntab <= 0 ? NIL(Dtlink_t *) :
00164 *(s = dt->data->htab + HINDEX(dt->data->ntab, hsh));
00165 for (p = NIL(Dtlink_t *); t; p = t, t = t->right) {
00166 if (hsh == t->hash) {
00167 k = OBJ(t, lk);
00168 k = KEY(k, ky, sz);
00169 if (CMP(dt, key, k, disc, cmpf, sz) == 0)
00170 break;
00171 }
00172 }
00173 }
00174 }
00175
00176 if (type & (DT_MATCH | DT_SEARCH | DT_VSEARCH)) {
00177 if (!t)
00178 return NIL(Void_t *);
00179 if (p && (dt->data->type & DT_SET) && dt->data->loop <= 0) {
00180 p->right = t->right;
00181 t->right = *s;
00182 *s = t;
00183 }
00184 dt->data->here = t;
00185 return OBJ(t, lk);
00186 } else if (type & (DT_INSERT | DT_ATTACH)) {
00187 if (t && (dt->data->type & DT_SET)) {
00188 dt->data->here = t;
00189 return OBJ(t, lk);
00190 }
00191
00192 if (disc->makef && (type & DT_INSERT) &&
00193 !(obj = (*disc->makef) (dt, obj, disc)))
00194 return NIL(Void_t *);
00195 if (lk >= 0)
00196 r = ELT(obj, lk);
00197 else {
00198 r = (Dtlink_t *) (*dt->memoryf)
00199 (dt, NIL(Void_t *), sizeof(Dthold_t), disc);
00200 if (r)
00201 ((Dthold_t *) r)->obj = obj;
00202 else {
00203 if (disc->makef && disc->freef && (type & DT_INSERT))
00204 (*disc->freef) (dt, obj, disc);
00205 return NIL(Void_t *);
00206 }
00207 }
00208 r->hash = hsh;
00209
00210
00211 do_insert:
00212 if ((dt->data->size += 1) > HLOAD(dt->data->ntab)
00213 && dt->data->loop <= 0)
00214 dthtab(dt);
00215 if (dt->data->ntab == 0) {
00216 dt->data->size -= 1;
00217 if (disc->freef && (type & DT_INSERT))
00218 (*disc->freef) (dt, obj, disc);
00219 if (disc->link < 0)
00220 (*disc->memoryf) (dt, (Void_t *) r, 0, disc);
00221 return NIL(Void_t *);
00222 }
00223 s = dt->data->htab + HINDEX(dt->data->ntab, hsh);
00224 if (t) {
00225 r->right = t->right;
00226 t->right = r;
00227 } else {
00228 r->right = *s;
00229 *s = r;
00230 }
00231 dt->data->here = r;
00232 return obj;
00233 } else if (type & DT_NEXT) {
00234 if (t && !(p = t->right)) {
00235 for (ends = dt->data->htab + dt->data->ntab, s += 1; s < ends;
00236 ++s)
00237 if ((p = *s))
00238 break;
00239 }
00240 goto done_adj;
00241 } else if (type & DT_PREV) {
00242 if (t && !p) {
00243 if ((p = *s) != t) {
00244 while (p->right != t)
00245 p = p->right;
00246 } else {
00247 p = NIL(Dtlink_t *);
00248 for (s -= 1, ends = dt->data->htab; s >= ends; --s) {
00249 if ((p = *s)) {
00250 while (p->right)
00251 p = p->right;
00252 break;
00253 }
00254 }
00255 }
00256 }
00257 done_adj:
00258 if (!(dt->data->here = p)) {
00259 end_walk:
00260 if ((dt->data->loop -= 1) < 0)
00261 dt->data->loop = 0;
00262 if (dt->data->size > HLOAD(dt->data->ntab)
00263 && dt->data->loop <= 0)
00264 dthtab(dt);
00265 return NIL(Void_t *);
00266 } else {
00267 dt->data->type |= DT_WALK;
00268 return OBJ(p, lk);
00269 }
00270 } else if (type & DT_RENEW) {
00271 if (!t || (dt->data->type & DT_BAG))
00272 goto do_insert;
00273 else {
00274 if (disc->freef)
00275 (*disc->freef) (dt, obj, disc);
00276 if (disc->link < 0)
00277 (*dt->memoryf) (dt, (Void_t *) r, 0, disc);
00278 return t ? OBJ(t, lk) : NIL(Void_t *);
00279 }
00280 } else {
00281 if (!t)
00282 return NIL(Void_t *);
00283 else if (p)
00284 p->right = t->right;
00285 else if ((p = *s) == t)
00286 *s = t->right;
00287 else {
00288 while (p->right != t)
00289 p = p->right;
00290 p->right = t->right;
00291 }
00292 obj = OBJ(t, lk);
00293 dt->data->size -= 1;
00294 dt->data->here = p;
00295 if (disc->freef && (type & DT_DETACH))
00296 (*disc->freef) (dt, obj, disc);
00297 if (disc->link < 0)
00298 (*dt->memoryf) (dt, (Void_t *) t, 0, disc);
00299 return obj;
00300 }
00301 }
00302
00303 static Dtmethod_t _Dtset = { dthash, DT_SET };
00304 static Dtmethod_t _Dtbag = { dthash, DT_BAG };
00305
00306 __DEFINE__(Dtmethod_t *, Dtset, &_Dtset);
00307 __DEFINE__(Dtmethod_t *, Dtbag, &_Dtbag);
00308
00309 #ifndef KPVDEL
00310 Dtmethod_t _Dthash = { dthash, DT_SET };
00311
00312 __DEFINE__(Dtmethod_t *, Dthash, &_Dthash);
00313 #endif