Graphviz 2.29.20120208.0545
lib/cdt/dtlist.c
Go to the documentation of this file.
00001 #include        "dthdr.h"
00002 
00003 /*      List, Deque, Stack, Queue.
00004 **
00005 **      Written by Kiem-Phong Vo (05/25/96)
00006 */
00007 
00008 #if __STD_C
00009 static Void_t* dtlist(reg Dt_t* dt, reg Void_t* obj, reg int type)
00010 #else
00011 static Void_t* dtlist(dt, obj, type)
00012 reg Dt_t*       dt;
00013 reg Void_t*     obj;
00014 reg int         type;
00015 #endif
00016 {
00017         reg int         lk, sz, ky;
00018         reg Dtcompar_f  cmpf;
00019         reg Dtdisc_t*   disc;
00020         reg Dtlink_t    *r, *t;
00021         reg Void_t      *key, *k;
00022 
00023         UNFLATTEN(dt);
00024         disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf);
00025         dt->type &= ~DT_FOUND;
00026 
00027         if(!obj)
00028         {       if(type&(DT_LAST|DT_FIRST) )
00029                 {       if((r = dt->data->head) )
00030                         {       if(type&DT_LAST)
00031                                         r = r->left;
00032                                 dt->data->here = r;
00033                         }
00034                         return r ? _DTOBJ(r,lk) : NIL(Void_t*);
00035                 }
00036                 else if(type&(DT_DELETE|DT_DETACH))
00037                 {       if((dt->data->type&(DT_LIST|DT_DEQUE)) || !(r = dt->data->head))
00038                                 return NIL(Void_t*);
00039                         else    goto dt_delete;
00040                 }
00041                 else if(type&DT_CLEAR)
00042                 {       if(disc->freef || disc->link < 0)
00043                         {       for(r = dt->data->head; r; r = t)
00044                                 {       t = r->right;
00045                                         if(disc->freef)
00046                                                 (*disc->freef)(dt,_DTOBJ(r,lk),disc);
00047                                         if(disc->link < 0)
00048                                                 (*dt->memoryf)(dt,(Void_t*)r,0,disc);
00049                                 }
00050                         }
00051                         dt->data->head = dt->data->here = NIL(Dtlink_t*);
00052                         dt->data->size = 0;
00053                         return NIL(Void_t*);
00054                 }
00055                 else    return NIL(Void_t*);
00056         }
00057 
00058         if(type&(DT_INSERT|DT_ATTACH))
00059         {       if(disc->makef && (type&DT_INSERT) &&
00060                    !(obj = (*disc->makef)(dt,obj,disc)) )
00061                         return NIL(Void_t*);
00062                 if(lk >= 0)
00063                         r = _DTLNK(obj,lk);
00064                 else
00065                 {       r = (Dtlink_t*)(*dt->memoryf)
00066                                 (dt,NIL(Void_t*),sizeof(Dthold_t),disc);
00067                         if(r)
00068                                 ((Dthold_t*)r)->obj = obj;
00069                         else
00070                         {       if(disc->makef && disc->freef && (type&DT_INSERT))
00071                                         (*disc->freef)(dt,obj,disc);
00072                                 return NIL(Void_t*);
00073                         }
00074                 }
00075 
00076                 if(dt->data->type&DT_DEQUE)
00077                 {       if(type&DT_APPEND)
00078                                 goto dt_queue;
00079                         else    goto dt_stack;
00080                 }
00081                 else if(dt->data->type&DT_LIST)
00082                 {       if(type&DT_APPEND)
00083                         {       if(!(t = dt->data->here) || !t->right)
00084                                         goto dt_queue;
00085                                 r->right = t->right;
00086                                 r->right->left = r;
00087                                 r->left = t;
00088                                 r->left->right = r;
00089                         }
00090                         else
00091                         {       if(!(t = dt->data->here) || t == dt->data->head)
00092                                         goto dt_stack;
00093                                 r->left = t->left;
00094                                 r->left->right = r;
00095                                 r->right = t;
00096                                 r->right->left = r;
00097                         }
00098                 }
00099                 else if(dt->data->type&DT_STACK)
00100                 { dt_stack:
00101                         r->right = t = dt->data->head;
00102                         if(t)
00103                         {       r->left = t->left;
00104                                 t->left = r;
00105                         }
00106                         else    r->left = r;
00107                         dt->data->head = r;
00108                 }
00109                 else /* if(dt->data->type&DT_QUEUE) */
00110                 { dt_queue:
00111                         if((t = dt->data->head) )
00112                         {       t->left->right = r;
00113                                 r->left = t->left;
00114                                 t->left = r;
00115                         }
00116                         else
00117                         {       dt->data->head = r;
00118                                 r->left = r;
00119                         }
00120                         r->right = NIL(Dtlink_t*);
00121                 }
00122 
00123                 if(dt->data->size >= 0)
00124                         dt->data->size += 1;
00125 
00126                 dt->data->here = r;
00127                 return _DTOBJ(r,lk);
00128         }
00129 
00130         if((type&DT_MATCH) || !(r = dt->data->here) || _DTOBJ(r,lk) != obj)
00131         {       key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz);
00132                 for(r = dt->data->head; r; r = r->right)
00133                 {       k = _DTOBJ(r,lk); k = _DTKEY(k,ky,sz);
00134                         if(_DTCMP(dt,key,k,disc,cmpf,sz) == 0)
00135                                 break;
00136                 }
00137         }
00138 
00139         if(!r)
00140                 return NIL(Void_t*);
00141         dt->type |= DT_FOUND;
00142 
00143         if(type&(DT_DELETE|DT_DETACH))
00144         { dt_delete:
00145                 if(r->right)
00146                         r->right->left = r->left;
00147                 if(r == (t = dt->data->head) )
00148                 {       dt->data->head = r->right;
00149                         if(dt->data->head)
00150                                 dt->data->head->left = t->left;
00151                 }
00152                 else
00153                 {       r->left->right = r->right;
00154                         if(r == t->left)
00155                                 t->left = r->left;
00156                 }
00157 
00158                 dt->data->here = r == dt->data->here ? r->right : NIL(Dtlink_t*);
00159                 dt->data->size -= 1;
00160 
00161                 obj = _DTOBJ(r,lk);
00162                 if(disc->freef && (type&DT_DELETE))
00163                         (*disc->freef)(dt,obj,disc);
00164                 if(disc->link < 0)
00165                         (*dt->memoryf)(dt,(Void_t*)r,0,disc);
00166                 return obj;
00167         }
00168         else if(type&DT_NEXT)
00169                 r = r->right;
00170         else if(type&DT_PREV)
00171                 r = r == dt->data->head ? NIL(Dtlink_t*) : r->left;
00172 
00173         dt->data->here = r;
00174         return r ? _DTOBJ(r,lk) : NIL(Void_t*);
00175 }
00176 
00177 #ifndef KPVDEL  /* to be remove next round */
00178 #define static 
00179 #endif
00180 static Dtmethod_t _Dtlist  = { dtlist, DT_LIST  };
00181 static Dtmethod_t _Dtdeque  = { dtlist, DT_DEQUE  };
00182 static Dtmethod_t _Dtstack = { dtlist, DT_STACK };
00183 static Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE };
00184 
00185 __DEFINE__(Dtmethod_t*,Dtlist,&_Dtlist);
00186 __DEFINE__(Dtmethod_t*,Dtdeque,&_Dtdeque);
00187 __DEFINE__(Dtmethod_t*,Dtstack,&_Dtstack);
00188 __DEFINE__(Dtmethod_t*,Dtqueue,&_Dtqueue);
00189 
00190 #ifdef NoF
00191 NoF(dtlist)
00192 #endif