Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/librecsort/rsprocess.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
/* Process a bunch of records
24
**
25
** Written by Kiem-Phong Vo (07/08/96)
26
*/
27
28
#define RS_ALLOC 1024
29
#define RSALLOC(rs,r) ((r = rs->free) ? ((rs->free = r->right),r) : (r = rsalloc(rs)) )
30
#define RSFREE(rs,r) (r->right = rs->free, rs->free = r)
31
32
#if __STD_C
33
static Rsobj_t* rsalloc(Rs_t* rs)
34
#else
35
static Rsobj_t* rsalloc(rs)
36
Rs_t* rs;
37
#endif
38
{
39
reg Rsobj_t *r, *endr;
40
41
if(!(rs->free = r = (Rsobj_t*)vmalloc(rs->vm,RS_ALLOC*sizeof(Rsobj_t))) )
42
return NIL(Rsobj_t*);
43
for(endr = r + RS_ALLOC-1; r < endr; ++r)
44
r->right = r+1;
45
r->right = NIL(Rsobj_t*);
46
47
r = rs->free;
48
rs->free = r->right;
49
return r;
50
}
51
52
#if __STD_C
53
ssize_t rsprocess(Rs_t* rs, Void_t* argdata, ssize_t s_data)
54
#else
55
ssize_t rsprocess(rs, argdata, s_data)
56
Rs_t* rs; /* Rs_t sort context */
57
Void_t* argdata; /* data string */
58
ssize_t s_data; /* data size */
59
#endif
60
{
61
reg Rsobj_t* r;
62
reg ssize_t datalen;
63
reg uchar* data = (uchar*)argdata;
64
reg ssize_t dsamelen = rs->disc->type&RS_DSAMELEN;
65
reg ssize_t d = rs->disc->data;
66
int (*insertf)_ARG_((Rs_t*, Rsobj_t*)) = rs->meth->insertf;
67
Rsdefkey_f defkeyf = rs->disc->defkeyf;
68
ssize_t key = rs->disc->key;
69
ssize_t keylen = rs->disc->keylen;
70
reg uchar *m_key, *c_key, *endd;
71
reg ssize_t s_key, k, s_process, c_max, s_loop, p_loop;
72
reg int single, n;
73
74
if((single = s_data <= 0 ? 1 : 0) ) /* a single record */
75
s_data = dsamelen ? d : -s_data;
76
77
if(dsamelen && d <= 0 && !single) /* avoid infinite loop */
78
return -1;
79
80
if((c_max = rs->c_max) <= 0)
81
c_max = s_data;
82
83
if((rs->type&RS_SORTED) )
84
{ if(rs->sorted)
85
return -1;
86
rs->type &= ~RS_SORTED;
87
}
88
89
/* reset record counter */
90
rs->count = 0;
91
92
/* space for keys */
93
m_key = c_key = NIL(uchar*);
94
s_key = 0;
95
96
if(defkeyf) /* max expansion for key */
97
{ if(key <= 0)
98
key = mbcoll() ? 64 : 4;
99
}
100
else if(dsamelen) /* embedded key with fixed length */
101
{ datalen = d;
102
if(keylen <= 0)
103
keylen += datalen - key;
104
}
105
106
for(s_process = 0;; )
107
{ if((s_loop = s_data) > c_max && !single) /* max amount per loop */
108
s_loop = c_max;
109
110
if((rs->c_size += s_loop) > c_max && (r = (*rs->meth->listf)(rs)) )
111
{ /* start a new sorted chain */
112
Rsobj_t** list;
113
list = (Rsobj_t**)vmresize(rs->vm, rs->list,
114
(rs->n_list+1)*sizeof(Rsobj_t*),
115
VM_RSCOPY|VM_RSMOVE);
116
if(!list)
117
return -1;
118
else rs->list = list;
119
rs->list[rs->n_list] = r;
120
rs->n_list += 1;
121
rs->c_size = s_loop;
122
}
123
124
p_loop = 0; /* accumulate amount processed in this loop */
125
126
if(!defkeyf && dsamelen) /* fast loop for a common case */
127
{ while(s_loop >= datalen)
128
{ if(!RSALLOC(rs,r))
129
return -1;
130
r->data = data;
131
r->datalen = datalen;
132
r->key = r->data+key;
133
r->keylen = keylen;
134
135
if(rs->events & RS_READ)
136
{ if((n = rsnotify(rs,RS_READ,r,(Void_t*)0,rs->disc))<0)
137
return -1;
138
if(n == RS_DELETE)
139
{ RSFREE(rs, r);
140
goto delete_key;
141
}
142
if(r->data != data)
143
{ if(!(endd = (uchar*)vmalloc(rs->vm,r->datalen)) || !(r->data = (uchar*)memcpy(endd, r->data, r->datalen)))
144
return -1;
145
r->key = r->data+key;
146
}
147
}
148
if((*insertf)(rs,r) < 0)
149
return -1;
150
rs->count += 1;
151
152
delete_key:
153
data += datalen;
154
s_loop -= datalen;
155
p_loop += datalen;
156
}
157
goto next_loop;
158
}
159
160
do
161
{ if(single)
162
datalen = s_data;
163
else if(dsamelen) /* fixed length records */
164
{ if(s_loop < d)
165
break;
166
datalen = d;
167
}
168
#if _PACKAGE_ast
169
else if (d & ~0xff) /* Recfmt_t record descriptor */
170
{ if ((datalen = reclen(d, data, s_loop)) <= 0 || s_loop < datalen)
171
break;
172
}
173
#endif
174
else /* records separated by some separator */
175
{ if(!(endd = (uchar*)memchr(data,(int)d,s_loop)) )
176
break;
177
datalen = (endd - data) + 1;
178
}
179
180
if(!RSALLOC(rs,r))
181
return -1;
182
183
r->data = data;
184
r->datalen = datalen;
185
186
for (;;)
187
{ if(!defkeyf) /* key is part of data */
188
{ r->key = r->data+key;
189
if((r->keylen = keylen) <= 0)
190
r->keylen += r->datalen - key;
191
}
192
else /* key must be constructed separately */
193
{ /* make sure there is enough space */
194
if(s_key < (k = key*r->datalen) )
195
{ if(k < RS_RESERVE &&
196
rs->meth->type != RS_MTVERIFY)
197
k = RS_RESERVE;
198
199
if(m_key) /* try to extend key space in place */
200
{ int n = (c_key-m_key)+s_key+k;
201
if(vmresize(rs->vm,m_key,n,0) )
202
s_key += k;
203
else /* fix current segment */
204
{ vmresize(rs->vm,m_key,
205
(c_key-m_key),0);
206
m_key = NIL(uchar*);
207
}
208
}
209
if(!m_key)
210
{ if(!(m_key = (uchar*)vmalloc(rs->vm,k)) )
211
return -1;
212
c_key = m_key;
213
s_key = k;
214
}
215
}
216
217
k = (*defkeyf)(rs,r->data,r->datalen,c_key,s_key,rs->disc);
218
if(k < 0)
219
return -1;
220
r->key = c_key;
221
r->keylen = k;
222
223
if(rs->meth->type == RS_MTVERIFY)
224
{ /* each key is allocated separately */
225
s_key = 0;
226
m_key = c_key = NIL(uchar*);
227
}
228
else
229
{ c_key += k;
230
s_key -= k;
231
}
232
}
233
if(r->data != data || !(rs->events & RS_READ))
234
break;
235
if((n = rsnotify(rs,RS_READ,r,(Void_t*)0,rs->disc))<0)
236
return -1;
237
if(n == RS_DELETE)
238
{ if(defkeyf && c_key)
239
{ c_key -= k;
240
s_key += k;
241
}
242
RSFREE(rs, r);
243
goto delete_raw;
244
}
245
if (!(endd = (uchar*)vmalloc(rs->vm,r->datalen)) || !(r->data = (uchar*)memcpy(endd, r->data, r->datalen)))
246
return -1;
247
}
248
249
if((*insertf)(rs,r) < 0)
250
return -1;
251
rs->count += 1;
252
253
delete_raw:
254
p_loop += datalen;
255
data += datalen;
256
} while ((s_loop -= datalen) > 0);
257
next_loop:
258
s_process += p_loop;
259
rs->c_size -= s_loop;
260
if((s_data -= p_loop) <= 0 || p_loop == 0)
261
break;
262
}
263
264
if(rs->meth->type == RS_MTVERIFY)
265
{ (*rs->meth->listf)(rs);
266
rs->c_size = 0;
267
}
268
269
if(m_key) /* fix memory segment */
270
vmresize(rs->vm,m_key,c_key-m_key,0);
271
272
return s_process;
273
}
274
275