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 | |