Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/ip_t/iv-flat.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 allows a new interval to simply overwrite
26
** any portion of older intervals that it overlaps with.
27
** Adjacent intervals with the same data are merged.
28
**
29
** Written by Kiem-Phong Vo and Glenn Fowler.
30
*/
31
32
typedef struct Flseg_s Flseg_t;
33
typedef struct Flat_s Flat_t;
34
35
struct Flat_s
36
{
37
Dtdisc_t dc; /* discipline structure for dictionary */
38
Ivfree_f freef; /* user data free */
39
Dt_t* dt;
40
Iv_t* iv;
41
int search; /* during search, use a faster compare */
42
};
43
44
struct Flseg_s
45
{
46
Ivseg_t seg; /* the actual segment */
47
Dtlink_t link;
48
};
49
50
/* create a new segment identical to "obj" */
51
static void*
52
flatmake(Dt_t* dt, void* obj, Dtdisc_t* disc)
53
{
54
Flseg_t* sg;
55
int size = ((Flat_t*)disc)->iv->size;
56
57
/* the use of sizeof(Flseg_t) is deliberate */
58
if (!(sg = newof(0, Flseg_t, 1, 2 * size)))
59
return 0;
60
fvcpy(size, sg->seg.lo = (unsigned char*)(sg + 1), ((Ivseg_t*)obj)->lo);
61
fvcpy(size, sg->seg.hi = sg->seg.lo + size, ((Ivseg_t*)obj)->hi);
62
sg->seg.data = ((Ivseg_t*)obj)->data;
63
return sg;
64
}
65
66
/* free a segment */
67
static void
68
flatfree(Dt_t* dt, void* obj, Dtdisc_t* disc)
69
{
70
if (((Flat_t*)disc)->freef && ((Ivseg_t*)obj)->data)
71
((Flat_t*)disc)->freef(((Flat_t*)disc)->iv, ((Ivseg_t*)obj)->data);
72
free(obj);
73
}
74
75
/* during build, segments are sorted by "lo" values only */
76
static int
77
flatbldcmp(Dt_t* dt, void* o1, void* o2, Dtdisc_t* disc)
78
{
79
int size = ((Flat_t*)disc)->iv->size;
80
81
return fvcmp(size, ((Ivseg_t*)o1)->lo, ((Ivseg_t*)o2)->lo);
82
}
83
84
/* during search, we are looking for a segment containing some point.
85
** since a point is a segment with identical ends, the being compared
86
** objects must be either distinct or have a containing relationship.
87
*/
88
static int
89
flatsrchcmp(Dt_t* dt, void* o1, void* o2, Dtdisc_t* disc)
90
{
91
int size = ((Flat_t*)disc)->iv->size;
92
93
if (fvcmp(size, ((Ivseg_t*)o1)->hi, ((Ivseg_t*)o2)->lo) < 0)
94
return -1;
95
else if (fvcmp(size, ((Ivseg_t*)o1)->lo, ((Ivseg_t*)o2)->hi) > 0)
96
return 1;
97
else
98
return 0;
99
}
100
101
static int
102
flatset(Iv_t* iv, unsigned char* lo, unsigned char* hi, void* data)
103
{
104
unsigned char* pt;
105
Ivseg_t seg;
106
Ivseg_t* sg;
107
Flat_t* fl;
108
Dt_t* dt;
109
unsigned char* unmatched = iv->disc->unmatched;
110
int size = iv->size;
111
112
if (!iv || !(fl = (Flat_t*)iv->data) || !(dt = fl->dt))
113
return -1;
114
if (fl->search)
115
{
116
fl->dc.comparf = flatbldcmp;
117
dtdisc(dt, &fl->dc, DT_SAMECMP/* not truthful but ok */);
118
fl->search = 0;
119
}
120
seg.lo = lo;
121
seg.hi = hi;
122
seg.data = data;
123
124
/* the possibilities for this case are:
125
** ........ ........ ........ ... ...
126
** ++++ ++++++ ++++++++++++++++
127
*/
128
if ((sg = dtprev(dt, &seg)) && fvcmp(size, fvcpy(size, pt = iv->r2, sg->hi), lo) >= 0)
129
{
130
if (fvcmp(size, pt, hi) >= 0)
131
{
132
if (data == sg->data) /* no need for new segment */
133
return 0;
134
/* set left side of old segment */
135
fvsub(size, sg->hi, lo, iv->unit);
136
if (data != unmatched && !dtinsert(dt, &seg))
137
return -1;
138
if (fvcmp(size, pt, hi) > 0)
139
{
140
/* set right side of old segment */
141
fvadd(size, seg.lo = iv->r1, hi, iv->unit);
142
seg.hi = pt;
143
seg.data = sg->data;
144
if (!dtinsert(dt, &seg))
145
return -1;
146
}
147
return 0;
148
}
149
else
150
/* set left side of old segment */
151
fvsub(size, sg->hi, lo, iv->unit);
152
}
153
154
/* the possibilities for this case are:
155
** ........ ........ ........ ... ....
156
** ++++ ++++++++ +++++++++++++++++++++++
157
*/
158
if ((sg = dtsearch(dt, &seg)))
159
{
160
if (fvcmp(size, sg->hi, hi) > 0)
161
{
162
if (data == sg->data)
163
return 0;
164
/* right side of old seg */
165
fvadd(size, sg->lo, hi, iv->unit);
166
}
167
else
168
dtdelete(dt, sg);
169
}
170
171
/* the possibilities for this case are:
172
** ........ ........ ........ ... ...
173
** +++++++ ++++++++++ ++++++++++++++++++++++++
174
*/
175
while((sg = dtnext(dt, &seg)) && fvcmp(size, sg->lo, hi) <= 0)
176
if (fvcmp(size, sg->hi, hi) > 0)
177
{
178
fvadd(size, sg->lo, hi, iv->unit);
179
break;
180
}
181
else
182
dtdelete(dt, sg);
183
184
/* mergeable with previous segment */
185
if ((sg = dtprev(dt,&seg)) && data == sg->data && fvcmp(size, (fvadd(size, iv->r1, sg->hi, iv->unit), iv->r1), lo) == 0)
186
{
187
seg.lo = fvcpy(size, iv->r2, sg->lo);
188
dtdelete(dt, sg);
189
}
190
/* mergeable with next segment */
191
if ((sg = dtnext(dt, &seg)) && data == sg->data && fvcmp(size, (fvadd(size, iv->r1, hi, iv->unit), iv->r1), sg->lo) == 0)
192
{
193
seg.hi = fvcpy(size, iv->r1, sg->hi);
194
dtdelete(dt, sg);
195
}
196
/* a new segment */
197
return data != unmatched && !dtinsert(dt, &seg) ? -1 : 0;
198
}
199
200
static int
201
flatdel(Iv_t* iv, unsigned char* lo, unsigned char* hi)
202
{
203
return flatset(iv, lo, hi, iv->disc->unmatched);
204
}
205
206
static unsigned char*
207
flatget(Iv_t* iv, unsigned char* pt)
208
{
209
Ivseg_t seg;
210
Ivseg_t* sg;
211
Flat_t* fl;
212
Dt_t* dt;
213
214
if (!(fl = (Flat_t*)iv->data) || !(dt = fl->dt))
215
return 0;
216
if (!fl->search)
217
{
218
fl->dc.comparf = flatsrchcmp;
219
dtdisc(dt, &fl->dc, DT_SAMECMP/* not truthful but ok */);
220
fl->search = 1;
221
}
222
/* see if inside some segment */
223
seg.lo = seg.hi = pt;
224
sg = (Ivseg_t*)dtsearch(dt, &seg);
225
return sg ? sg->data : iv->disc->unmatched;
226
}
227
228
static Ivseg_t*
229
flatseg(Iv_t* iv, unsigned char* pt)
230
{
231
Ivseg_t seg;
232
Flat_t* fl;
233
Dt_t* dt;
234
235
if (!(fl = (Flat_t*)iv->data) || !(dt = fl->dt))
236
return 0;
237
if (!fl->search)
238
{
239
fl->dc.comparf = flatsrchcmp;
240
dtdisc(dt, &fl->dc, DT_SAMECMP/* not truthful but ok */);
241
fl->search = 1;
242
}
243
/* find the segment containing pt or just beyond it */
244
seg.lo = seg.hi = pt;
245
return (Ivseg_t*)dtsearch(dt, &seg);
246
}
247
248
static int
249
flatevent(Iv_t* iv, int type, void* data)
250
{
251
Flat_t* fl;
252
253
switch (type)
254
{
255
case IV_OPEN:
256
if (!(fl = (Flat_t*)malloc(sizeof(Flat_t))))
257
return -1;
258
fl->search = 0;
259
DTDISC(&fl->dc,0,0,offsetof(Flseg_t,link),flatmake,flatfree,flatbldcmp,0,0,0);
260
if (!(fl->dt = dtopen(&fl->dc, Dtoset)))
261
{
262
free(fl);
263
return -1;
264
}
265
fl->freef = iv->disc->freef;
266
fl->iv = iv;
267
iv->data = (void*)fl;
268
break;
269
case IV_CLOSE:
270
if (!(fl = (Flat_t*)iv->data))
271
return -1;
272
if (fl->dt)
273
dtclose(fl->dt);
274
free(fl);
275
iv->data = 0;
276
break;
277
}
278
return 0;
279
}
280
281
static Ivmeth_t _Ivflat =
282
{
283
"flat",
284
"The flat interval method allows a new interval to simply overwrite any portion of older intervals that it overlaps with. Adjacent intervals with the same data are merged.",
285
0,
286
flatget,
287
flatset,
288
flatdel,
289
flatseg,
290
flatevent,
291
};
292
293
IVLIB(flat)
294
295