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
9static 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
89Dt_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