| 1 | #include "dthdr.h" |
| 2 | |
| 3 | /* Set a view path from dict to view. |
| 4 | ** |
| 5 | ** Written by Kiem-Phong Vo (5/25/96) |
| 6 | */ |
| 7 | |
| 8 | |
| 9 | static void* dtvsearch(Dt_t* dt, reg void* obj, reg int type) |
| 10 | { |
| 11 | Dt_t *d, *p; |
| 12 | void *o, *n, *ok, *nk; |
| 13 | int cmp, lk, sz, ky; |
| 14 | Dtcompar_f cmpf; |
| 15 | |
| 16 | /* these operations only happen at the top level */ |
| 17 | if(type&(DT_INSERT|DT_DELETE|DT_CLEAR|DT_RENEW)) |
| 18 | return (*(dt->meth->searchf))(dt,obj,type); |
| 19 | |
| 20 | if((type&(DT_MATCH|DT_SEARCH)) || /* order sets first/last done below */ |
| 21 | ((type&(DT_FIRST|DT_LAST)) && !(dt->meth->type&(DT_OBAG|DT_OSET)) ) ) |
| 22 | { for(d = dt; d; d = d->view) |
| 23 | if((o = (*(d->meth->searchf))(d,obj,type)) ) |
| 24 | break; |
| 25 | dt->walk = d; |
| 26 | return o; |
| 27 | } |
| 28 | |
| 29 | if(dt->meth->type & (DT_OBAG|DT_OSET) ) |
| 30 | { if(!(type & (DT_FIRST|DT_LAST|DT_NEXT|DT_PREV)) ) |
| 31 | return NIL(void*); |
| 32 | |
| 33 | n = nk = NIL(void*); p = NIL(Dt_t*); |
| 34 | for(d = dt; d; d = d->view) |
| 35 | { if(!(o = (*d->meth->searchf)(d, obj, type)) ) |
| 36 | continue; |
| 37 | _DTDSC(d->disc,ky,sz,lk,cmpf); |
| 38 | ok = _DTKEY(o,ky,sz); |
| 39 | |
| 40 | if(n) /* get the right one among all dictionaries */ |
| 41 | { cmp = _DTCMP(d,ok,nk,d->disc,cmpf,sz); |
| 42 | if(((type & (DT_NEXT|DT_FIRST)) && cmp < 0) || |
| 43 | ((type & (DT_PREV|DT_LAST)) && cmp > 0) ) |
| 44 | goto a_dj; |
| 45 | } |
| 46 | else /* looks good for now */ |
| 47 | { a_dj: p = d; |
| 48 | n = o; |
| 49 | nk = ok; |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | dt->walk = p; |
| 54 | return n; |
| 55 | } |
| 56 | |
| 57 | /* non-ordered methods */ |
| 58 | if(!(type & (DT_NEXT|DT_PREV)) ) |
| 59 | return NIL(void*); |
| 60 | |
| 61 | if(!dt->walk || obj != _DTOBJ(dt->walk->data->here, dt->walk->disc->link) ) |
| 62 | { for(d = dt; d; d = d->view) |
| 63 | if((o = (*(d->meth->searchf))(d, obj, DT_SEARCH)) ) |
| 64 | break; |
| 65 | dt->walk = d; |
| 66 | if(!(obj = o) ) |
| 67 | return NIL(void*); |
| 68 | } |
| 69 | |
| 70 | for(d = dt->walk, obj = (*d->meth->searchf)(d, obj, type);; ) |
| 71 | { while(obj) /* keep moving until finding an uncovered object */ |
| 72 | { for(p = dt; ; p = p->view) |
| 73 | { if(p == d) /* adjacent object is uncovered */ |
| 74 | return obj; |
| 75 | if((*(p->meth->searchf))(p, obj, DT_SEARCH) ) |
| 76 | break; |
| 77 | } |
| 78 | obj = (*d->meth->searchf)(d, obj, type); |
| 79 | } |
| 80 | |
| 81 | if(!(d = dt->walk = d->view) ) /* move on to next dictionary */ |
| 82 | return NIL(void*); |
| 83 | else if(type&DT_NEXT) |
| 84 | obj = (*(d->meth->searchf))(d,NIL(void*),DT_FIRST); |
| 85 | else obj = (*(d->meth->searchf))(d,NIL(void*),DT_LAST); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | Dt_t* dtview(reg Dt_t* dt, reg Dt_t* view) |
| 90 | { |
| 91 | reg Dt_t* d; |
| 92 | |
| 93 | UNFLATTEN(dt); |
| 94 | if(view) |
| 95 | { UNFLATTEN(view); |
| 96 | if(view->meth != dt->meth) /* must use the same method */ |
| 97 | return NIL(Dt_t*); |
| 98 | } |
| 99 | |
| 100 | /* make sure there won't be a cycle */ |
| 101 | for(d = view; d; d = d->view) |
| 102 | if(d == dt) |
| 103 | return NIL(Dt_t*); |
| 104 | |
| 105 | /* no more viewing lower dictionary */ |
| 106 | if((d = dt->view) ) |
| 107 | d->nview -= 1; |
| 108 | dt->view = dt->walk = NIL(Dt_t*); |
| 109 | |
| 110 | if(!view) |
| 111 | { dt->searchf = dt->meth->searchf; |
| 112 | return d; |
| 113 | } |
| 114 | |
| 115 | /* ok */ |
| 116 | dt->view = view; |
| 117 | dt->searchf = dtvsearch; |
| 118 | view->nview += 1; |
| 119 | |
| 120 | return view; |
| 121 | } |
| 122 | |