Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/librecsort/rslist.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1996-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
* Phong Vo <[email protected]> *
18
* Glenn Fowler <[email protected]> *
19
* *
20
***********************************************************************/
21
#include "rshdr.h"
22
23
/* Get a list of objects from a sorting context.
24
** Derived contexts will be unionized.
25
**
26
** Written by Kiem-Phong Vo (07/19/96)
27
*/
28
29
typedef struct _union_s
30
{ Rsobj_t* obj;
31
int pos;
32
struct _union_s* equi;
33
} Union_t;
34
35
#define ADDOBJ(list,tail,obj) (tail = tail ? (tail->right = obj) : (list = obj) )
36
37
/* Lists are kept in reverse order to ease data movement.
38
** Ties are broken by list positions to preserve stability.
39
*/
40
#if __STD_C
41
static int uninsert(Union_t** list, int n, Union_t* un)
42
#else
43
static int uninsert(list, n, un)
44
Union_t** list;
45
int n;
46
Union_t* un;
47
#endif
48
{
49
reg Rsobj_t *obj, *o;
50
reg Union_t **l, **r, **m, *p, *h;
51
reg int cmp;
52
53
obj = un->obj;
54
r = (l = list) + n;
55
56
if(n > 4)
57
{ while(l != r)
58
{ m = l + (r-l)/2;
59
o = (*m)->obj;
60
OBJCMP(o,obj,cmp);
61
if(cmp == 0)
62
l = r = m;
63
else if(cmp > 0)
64
l = l == m ? r : m;
65
else r = m;
66
}
67
}
68
else
69
{ for(r -= 1, cmp = 1; r >= l; --r)
70
{ o = (*r)->obj;
71
OBJCMP(o,obj,cmp);
72
if(cmp > 0)
73
{ l = r+1; break; }
74
else if(cmp == 0)
75
{ l = r; break; }
76
}
77
}
78
79
if(cmp == 0)
80
{ for(p = NIL(Union_t*), h = *l;; )
81
if(un->pos < h->pos || !(p=h, h=h->equi) )
82
break;
83
un->equi = h;
84
if(p) p->equi = un;
85
else *l = un;
86
}
87
else
88
{ for(r = list+n; r > l; --r)
89
*r = *(r-1);
90
*l = un; un->equi = NIL(Union_t*);
91
n += 1;
92
}
93
94
return n;
95
}
96
97
#if __STD_C
98
static Rsobj_t* unionize(Rsobj_t** objlist, int n)
99
#else
100
static Rsobj_t* unionize(objlist, n)
101
Rsobj_t** objlist;
102
int n;
103
#endif
104
{
105
reg int p, cmp;
106
reg Union_t *un, *u, *pu;
107
reg Rsobj_t *obj, *o, *e, *list, *tail;
108
Union_t **ulist, *uarray;
109
reg int n_list;
110
111
if(!(ulist = (Union_t**)vmalloc(Vmheap,n*sizeof(Union_t*))) )
112
return NIL(Rsobj_t*);
113
if(!(uarray = (Union_t*)vmalloc(Vmheap,n*sizeof(Union_t))) )
114
{ vmfree(Vmheap,ulist);
115
return NIL(Rsobj_t*);
116
}
117
118
for(p = 0, n_list = 0; p < n; ++p)
119
{ /* set up header data for quick comparisons */
120
for(obj = objlist[p]; obj; obj = obj->right)
121
OBJHEAD(obj);
122
123
uarray[p].obj = objlist[p];
124
uarray[p].pos = p;
125
n_list = uninsert(ulist,n_list,uarray+p);
126
}
127
128
list = tail = NIL(Rsobj_t*);
129
while(n_list > 0)
130
{ un = ulist[n_list -= 1];
131
if(n_list == 0 && !un->equi) /* last unmerged list */
132
{ obj = un->obj;
133
ADDOBJ(list,tail,obj);
134
}
135
else if(un->equi) /* a set of equivalence classes */
136
{ obj = un->obj; un->obj = obj->right;
137
for(;;)
138
{ u = un->equi;
139
if(un->obj)
140
n_list = uninsert(ulist,n_list,un);
141
if(!(un = u) )
142
break;
143
144
/* union with equal list of obj */
145
o = u->obj; u->obj = o->right;
146
if((e = obj->equal) )
147
e->left->right = o;
148
else obj->equal = e = o;
149
150
if((o->right = o->equal) )
151
e->left = o->equal->left;
152
else e->left = o;
153
}
154
obj->equal->left->right = NIL(Rsobj_t*);
155
156
ADDOBJ(list,tail,obj);
157
158
if(n_list == 0)
159
tail->right = NIL(Rsobj_t*);
160
}
161
else /* at least 2 distinct lists are left */
162
{ o = ulist[p = n_list-1]->obj;
163
for(obj = un->obj;; ) /* keep peeling off least objects */
164
{ un->obj = obj->right;
165
ADDOBJ(list,tail,obj);
166
167
if(!(obj = un->obj) )
168
break;
169
else
170
{ OBJCMP(obj,o,cmp);
171
if(cmp >= 0)
172
break;
173
}
174
}
175
if(obj)
176
{ if(cmp > 0) /* new min element */
177
{ ulist[n_list] = ulist[p];
178
if(p == 0)
179
{ n_list = 2;
180
ulist[0] = un;
181
}
182
else if(uninsert(ulist,p,un) == p)
183
ulist[p] = ulist[n_list];
184
else n_list += 1;
185
}
186
else /*if(cmp == 0) -- new equivalence class */
187
{ for(pu = NIL(Union_t*), u = ulist[p];; )
188
if(un->pos < u->pos ||
189
!(pu = u, u = u->equi) )
190
break;
191
un->equi = u;
192
if(pu) pu->equi = un;
193
else ulist[p] = un;
194
}
195
}
196
}
197
}
198
199
vmfree(Vmheap,ulist);
200
vmfree(Vmheap,uarray);
201
202
return list;
203
}
204
205
#if __STD_C
206
Rsobj_t* rslist(Rs_t* rs)
207
#else
208
Rsobj_t* rslist(rs)
209
Rs_t* rs;
210
#endif
211
{
212
reg Rsobj_t *list, *next, *p, *r, *t, *e;
213
reg int n, type;
214
reg uchar* k;
215
216
if((type = rs->type)&RS_SORTED)
217
return rs->sorted;
218
219
if((list = (*rs->meth->listf)(rs)) && rs->n_list > 0)
220
{ rs->list = (Rsobj_t**)vmresize(rs->vm,
221
rs->list, (rs->n_list+1)*sizeof(Rsobj_t*),
222
VM_RSCOPY|VM_RSMOVE);
223
if(!rs->list)
224
return NIL(Rsobj_t*);
225
rs->list[rs->n_list] = list;
226
rs->n_list += 1;
227
}
228
229
if(rs->n_list > 0)
230
{ list = rs->n_list > 1 ? unionize(rs->list,rs->n_list) : rs->list[0];
231
232
vmfree(rs->vm,rs->list);
233
rs->list = NIL(Rsobj_t**);
234
rs->n_list = 0;
235
}
236
237
if((type&RS_UNIQ) || !(type&RS_DATA) )
238
{ for(r = list; r; r = r->right)
239
if((e = r->equal) )
240
e->left->right = NIL(Rsobj_t*);
241
}
242
else
243
{ int (*insertf)_ARG_((Rs_t*, Rsobj_t*)) = rs->meth->insertf;
244
Rsobj_t*(*listf)_ARG_((Rs_t*)) = rs->meth->listf;
245
246
for(p = NIL(Rsobj_t*), r = list; r; r = t)
247
{ t = r->right;
248
if(!(e = r->equal) )
249
{ p = r;
250
continue;
251
}
252
253
/* resort using whole data */
254
r->right = e;
255
e->left->right = NIL(Rsobj_t*);
256
257
rs->type &= ~RS_KSAMELEN;
258
if(type&RS_DSAMELEN)
259
rs->type |= RS_KSAMELEN;
260
261
for(; r; r = next)
262
{ next = r->right;
263
264
k = r->key;
265
r->key = r->data;
266
r->data = k;
267
n = r->keylen;
268
r->keylen = r->datalen;
269
r->datalen = n;
270
271
(*insertf)(rs,r);
272
}
273
274
r = (*listf)(rs);
275
if(p)
276
p->right = r;
277
else list = r;
278
279
p = r->left;
280
p->right = t;
281
282
for(; r != t; r = r->right)
283
{ k = r->key;
284
r->key = r->data;
285
r->data = k;
286
n = r->keylen;
287
r->keylen = r->datalen;
288
r->datalen = n;
289
290
if((e = r->equal) )
291
{ e->left->right = NIL(Rsobj_t*);
292
for(; e; e = e->right)
293
{ k = e->key;
294
e->key = e->data;
295
e->data = k;
296
n = e->keylen;
297
e->keylen = e->datalen;
298
e->datalen = n;
299
}
300
}
301
}
302
303
rs->type = type;
304
}
305
}
306
307
if((type&RS_REVERSE) )
308
{ for(p = NIL(Rsobj_t*), r = list; r; r = t)
309
{ t = r->right;
310
311
if((e = r->equal) ) /* invert equal list */
312
{ reg Rsobj_t* ende;
313
for(list = r, ende = e->left; e != ende; e = next)
314
{ next = e->right;
315
e->right = list;
316
list = e;
317
}
318
list->left = r; r->right = NIL(Rsobj_t*);
319
r = ende; r->equal = list;
320
}
321
322
r->right = p;
323
p = r;
324
}
325
list = p;
326
}
327
328
if((rs->sorted = list) )
329
rs->type |= RS_SORTED;
330
return list;
331
}
332
333