Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/ip_t/iv-nested.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2000-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* Phong Vo <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
23
#include "ivlib.h"
24
25
/* This method manages nested intervals so that only points in
26
** the smallest containing intervals will be visible.
27
**
28
** Written by Kiem-Phong Vo.
29
*/
30
31
typedef struct Itvl_s Itvl_t;
32
typedef struct Nest_s Nest_t;
33
34
/* a segment [lo,hi] and associated "data". */
35
struct Itvl_s
36
{
37
Dtlink_t link; /* splay tree holder */
38
unsigned char* lo; /* low point */
39
unsigned char* hi; /* high point */
40
void* data; /* associated data */
41
};
42
43
struct Nest_s
44
{
45
Dtdisc_t dc; /* dt discipline */
46
Ivfree_f freef; /* user data free */
47
Dt_t* dt; /* to keep intervals */
48
Iv_t* flat; /* flat interval handle */
49
Iv_t* iv; /* original interval */
50
Ivdisc_t disc; /* flat discipline */
51
int changed;/* intervals changed */
52
};
53
54
/* create a new segment identical to p */
55
static void*
56
nestmake(Dt_t* dt, void* p, Dtdisc_t* disc)
57
{
58
Itvl_t* op = (Itvl_t*)p;
59
Itvl_t* np;
60
int size = ((Nest_t*)disc)->iv->size;
61
62
if (!(np = newof(0, Itvl_t, 1, 2 * size)))
63
return 0;
64
fvcpy(size, np->lo = (unsigned char*)(np + 1), op->lo);
65
fvcpy(size, np->hi = np->lo + size, op->hi);
66
np->data = op->data;
67
return np;
68
}
69
70
/* free a segment */
71
static void
72
nestfree(Dt_t* dt, void* obj, Dtdisc_t* disc)
73
{
74
if (((Nest_t*)disc)->freef && ((Itvl_t*)obj)->data)
75
((Nest_t*)disc)->freef(((Nest_t*)disc)->iv, ((Itvl_t*)obj)->data);
76
free(obj);
77
}
78
79
/* Segments are sorted so that "inside" ones are consider larger */
80
static int
81
nestcmp(Dt_t* dt, void* o1, void* o2, Dtdisc_t* disc)
82
{
83
Itvl_t* i1;
84
Itvl_t* i2;
85
int size = ((Nest_t*)disc)->iv->size;
86
int l;
87
int h;
88
89
if ((i1 = (Itvl_t*)o1) == (i2 = (Itvl_t*)o2))
90
return 0;
91
if (fvcmp(size, i1->hi, i2->lo) < 0) /* i1 is to the left of i2 */
92
return -1;
93
if (fvcmp(size, i1->lo, i2->hi) > 0) /* i1 is to the right of i2 */
94
return 1;
95
h = fvcmp(size, i1->hi, i2->hi);
96
l = fvcmp(size, i1->lo, i2->lo);
97
if (l < 0)
98
{
99
if (h >= 0) /* i1 contains i2 */
100
return -1;
101
else
102
return 0; /* i1 crossing i2 on the left */
103
}
104
else if (l == 0)
105
{
106
if (h < 0) /* i1 is contained in i2 */
107
return 1;
108
else if (h == 0) /* equal segments */
109
return 0;
110
else
111
return -1; /* i1 contains i2 */
112
}
113
else /* if (l > 0) */
114
{
115
if (h <= 0) /* i1 is contained in i2 */
116
return 1;
117
else
118
return 0; /* i1 crossing i2 on the right */
119
}
120
}
121
122
static int nestset(Iv_t* iv, unsigned char* lo, unsigned char* hi, void* data)
123
{
124
Nest_t* nst;
125
Itvl_t itvl;
126
Itvl_t* it;
127
int size = iv->size;
128
129
if (!iv || !(nst = (Nest_t*)iv->data))
130
return -1;
131
itvl.lo = lo;
132
itvl.hi = hi;
133
itvl.data = data;
134
if (!(it = (Itvl_t*)dtsearch(nst->dt, &itvl)))
135
{
136
nst->changed = 1;
137
return dtinsert(nst->dt, &itvl) ? 0 : -1;
138
}
139
else if (fvcmp(size, it->lo, lo) || fvcmp(size, it->hi, hi))
140
return -1; /* must have been a crossing element */
141
else if (it->data != data) /* just update the data */
142
{
143
nst->changed = 1;
144
it->data = data;
145
return 0;
146
}
147
else
148
return 0;
149
}
150
151
static int nestdel(Iv_t* iv, unsigned char* lo, unsigned char* hi)
152
{
153
Nest_t* nst;
154
Itvl_t itvl;
155
Itvl_t* it;
156
int size = iv->size;
157
158
if (!(nst = (Nest_t*)iv->data))
159
return -1;
160
itvl.lo = lo;
161
itvl.hi = hi;
162
if (!(it = (Itvl_t*)dtsearch(nst->dt, &itvl)) || fvcmp(size, it->lo, lo) || fvcmp(size, it->hi, hi))
163
return -1;
164
nst->changed = 1;
165
dtdelete(nst->dt, it);
166
return 0;
167
}
168
169
/* create a fresh Ivflat handle to compute maximal open segments */
170
static int nest2flat(Iv_t* iv, Nest_t* nst)
171
{
172
Itvl_t* it;
173
174
if (nst->flat)
175
ivclose(nst->flat);
176
if (!(nst->flat = ivopen(&nst->disc, ivmeth("flat"), iv->size, 0)))
177
return -1;
178
/* insert "in order" all intervals into the Ivflat handle */
179
for(it = (Itvl_t*)dtfirst(nst->dt); it; it = (Itvl_t*)dtnext(nst->dt, it))
180
ivset(nst->flat, it->lo, it->hi, it->data);
181
nst->changed = 0;
182
return 0;
183
}
184
185
static unsigned char*
186
nestget(Iv_t* iv, unsigned char* pt)
187
{
188
Nest_t* nst;
189
190
if (!(nst = (Nest_t*)iv->data) || nst->changed && nest2flat(iv, nst) < 0)
191
return 0;
192
return nst->flat ? ivget(nst->flat, pt) : 0;
193
}
194
195
static Ivseg_t*
196
nestseg(Iv_t* iv, unsigned char* pt)
197
{
198
Nest_t* nst;
199
200
if (!(nst = (Nest_t*)iv->data) || nst->changed && nest2flat(iv, nst) < 0)
201
return 0;
202
return nst->flat ? ivseg(nst->flat, pt) : 0;
203
}
204
205
static int
206
nestevent(Iv_t* iv, int type, void* data)
207
{
208
Nest_t* nst;
209
210
switch (type)
211
{
212
case IV_OPEN:
213
if (!(nst = newof(0, Nest_t, 1, 0)))
214
return -1;
215
nst->dc.makef = nestmake;
216
nst->dc.freef = nestfree;
217
nst->dc.comparf = nestcmp;
218
if (!(nst->dt = dtopen(&nst->dc, Dtoset)))
219
{
220
free(nst);
221
return -1;
222
}
223
nst->changed = 0;
224
nst->flat = 0;
225
nst->freef = iv->disc->freef;
226
nst->iv = iv;
227
nst->disc = *iv->disc;
228
nst->disc.freef = 0;
229
iv->data = (void*)nst;
230
break;
231
case IV_CLOSE:
232
if ((nst = (Nest_t*)iv->data))
233
{
234
if (nst->flat)
235
ivclose(nst->flat);
236
if (nst->dt)
237
dtclose(nst->dt);
238
free(nst);
239
iv->data = 0;
240
}
241
break;
242
}
243
return 0;
244
}
245
246
static Ivmeth_t _Ivnested =
247
{
248
"nested",
249
"The nested method manages nested intervals so that only points in the smallest containing intervals will be visible.",
250
0,
251
nestget,
252
nestset,
253
nestdel,
254
nestseg,
255
nestevent,
256
};
257
258
IVLIB(nested)
259
260