/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/cdt/dthash.c

Go to the documentation of this file.
00001 /* $Id: dthash.c,v 1.1.1.1 2004/12/23 04:03:59 ellson Exp $ $Revision: 1.1.1.1 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #include        "dthdr.h"
00018 
00019 #ifdef DMALLOC
00020 #include "dmalloc.h"
00021 #endif
00022 
00023 /*      Hash table.
00024 **      dt:     dictionary
00025 **      obj:    what to look for
00026 **      type:   type of search
00027 **
00028 **      Written by Kiem-Phong Vo (05/25/96)
00029 */
00030 
00031 /* resize the hash table */
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     /* compute new table size */
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     /* allocate new table */
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     /* rehash elements */
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 {              /* move to a new chain */
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) {  /* clean out all objects */
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 {                /* computing the first/last object */
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 {                    /*if(type&(DT_DELETE|DT_DETACH|DT_NEXT|DT_PREV)) */
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) {    /* move-to-front heuristic */
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         /* insert object */
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 {                    /*if(type&(DT_DELETE|DT_DETACH)) */
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                  /* for backward compatibility - remove next time */
00310 Dtmethod_t _Dthash = { dthash, DT_SET };
00311 
00312 __DEFINE__(Dtmethod_t *, Dthash, &_Dthash);
00313 #endif

Generated on Mon Mar 31 19:03:23 2008 for Graphviz by  doxygen 1.5.1