1 : #define VSTR_SPLIT_C
2 : /*
3 : * Copyright (C) 2002, 2003, 2004 James Antill
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 : *
19 : * email: james@and.org
20 : */
21 : /* functions to split a Vstr into sections (ala. perl split()) */
22 : #include "main.h"
23 :
24 :
25 : #define VSTR__SPLIT_LIM(x) (!limit || (limit > (x)))
26 :
27 : /* do the null fields go to the end ? */
28 : static int vstr__split_buf_null_end(const Vstr_base *base,
29 : size_t pos, size_t len,
30 : const void *buf, size_t buf_len,
31 : unsigned int *ret_num)
32 435 : {
33 435 : assert(vstr_cmp_buf_eq(base, pos, buf_len, buf, buf_len));
34 435 : assert(len >= buf_len);
35 :
36 435 : *ret_num = 1;
37 :
38 435 : if (len == buf_len)
39 5 : return (TRUE);
40 :
41 430 : pos += buf_len;
42 430 : len -= buf_len;
43 :
44 611 : while (len >= buf_len)
45 : {
46 577 : if (!vstr_cmp_buf_eq(base, pos, buf_len, buf, buf_len))
47 396 : return (FALSE);
48 :
49 181 : ++*ret_num;
50 181 : pos += buf_len;
51 181 : len -= buf_len;
52 : }
53 :
54 34 : return (!len);
55 : }
56 :
57 : static unsigned int vstr__split_hdl_err(Vstr_sects *sects,
58 : unsigned int flags, unsigned int added,
59 : int *bad_ret)
60 190 : {
61 190 : ASSERT(bad_ret);
62 190 : ASSERT(!*bad_ret);
63 :
64 190 : if (sects->malloc_bad)
65 : {
66 10 : ASSERT(sects->num >= added);
67 10 : sects->num -= added;
68 10 : *bad_ret = TRUE;
69 10 : return (0);
70 : }
71 :
72 180 : ASSERT(!sects->can_add_sz);
73 180 : ASSERT(sects->num == sects->sz);
74 :
75 180 : if (flags & VSTR_FLAG_SPLIT_NO_RET)
76 10 : *bad_ret = TRUE;
77 :
78 180 : return (1);
79 : }
80 :
81 : #define VSTR__SPLIT_HDL_ERR(bad_ret) do { \
82 : unsigned int err_ret = vstr__split_hdl_err(sects, flags, added, \
83 : bad_ret); \
84 : \
85 : if (*bad_ret) \
86 : return (err_ret); \
87 : } while (FALSE)
88 :
89 : static unsigned int vstr__split_hdl_null_beg(size_t *pos, size_t *len,
90 : size_t buf_len,
91 : Vstr_sects *sects,
92 : unsigned int flags,
93 : unsigned int count,
94 : unsigned int limit,
95 : unsigned int added,
96 : int *bad_ret)
97 227 : {
98 227 : const int is_remain = !!(flags & VSTR_FLAG_SPLIT_REMAIN);
99 :
100 227 : ASSERT(count);
101 :
102 227 : if (limit && (count >= (limit - added)))
103 5 : count = (limit - is_remain) - added;
104 :
105 609 : while (count)
106 : {
107 384 : if (flags & VSTR_FLAG_SPLIT_BEG_NULL)
108 : {
109 144 : if (!vstr_sects_add(sects, *pos, 0))
110 42 : VSTR__SPLIT_HDL_ERR(bad_ret);
111 :
112 142 : ++added;
113 : }
114 :
115 382 : *pos += buf_len;
116 382 : *len -= buf_len;
117 382 : --count;
118 : }
119 :
120 225 : return (added);
121 : }
122 :
123 : static unsigned int vstr__split_hdl_null_mid(size_t *pos, size_t *len,
124 : size_t buf_len,
125 : Vstr_sects *sects,
126 : unsigned int flags,
127 : unsigned int count,
128 : unsigned int limit,
129 : unsigned int added,
130 : int *bad_ret)
131 2157 : {
132 2157 : const int is_remain = !!(flags & VSTR_FLAG_SPLIT_REMAIN);
133 :
134 2157 : ASSERT(count);
135 :
136 2157 : if (limit && (count >= (limit - added)))
137 26 : count = (limit - is_remain) - added;
138 :
139 5744 : while (count)
140 : {
141 3589 : if (flags & VSTR_FLAG_SPLIT_MID_NULL)
142 : {
143 202 : if (!vstr_sects_add(sects, *pos, 0))
144 27 : VSTR__SPLIT_HDL_ERR(bad_ret);
145 :
146 200 : ++added;
147 : }
148 :
149 3587 : *pos += buf_len;
150 3587 : *len -= buf_len;
151 3587 : --count;
152 : }
153 :
154 2155 : return (added);
155 : }
156 :
157 : static unsigned int vstr__split_hdl_null_end(size_t pos, size_t len,
158 : size_t buf_len,
159 : Vstr_sects *sects,
160 : unsigned int flags,
161 : unsigned int count,
162 : unsigned int limit,
163 : unsigned int added)
164 49 : {
165 49 : const int is_remain = !!(flags & VSTR_FLAG_SPLIT_REMAIN);
166 49 : int bad_ret = FALSE;
167 :
168 49 : assert(len);
169 :
170 49 : if (!(flags & VSTR_FLAG_SPLIT_END_NULL))
171 11 : goto no_end_null;
172 :
173 38 : if (limit && (count >= (limit - added)))
174 6 : count = (limit - is_remain) - added;
175 :
176 125 : while (count)
177 : {
178 90 : if (!vstr_sects_add(sects, pos, 0))
179 28 : VSTR__SPLIT_HDL_ERR(&bad_ret);
180 :
181 87 : ++added;
182 :
183 87 : pos += buf_len;
184 87 : len -= buf_len;
185 87 : --count;
186 : }
187 :
188 : no_end_null:
189 46 : if (((len && (flags & VSTR_FLAG_SPLIT_REMAIN)) ||
190 : (!len && (flags & VSTR_FLAG_SPLIT_POST_NULL))))
191 : {
192 31 : if (!vstr_sects_add(sects, pos, len))
193 6 : VSTR__SPLIT_HDL_ERR(&bad_ret);
194 30 : ++added;
195 : }
196 :
197 45 : return (added);
198 : }
199 :
200 : static unsigned int vstr__split_hdl_end(size_t pos, size_t len,
201 : size_t split_pos,
202 : Vstr_sects *sects,
203 : unsigned int limit, unsigned int flags,
204 : unsigned int added)
205 9696 : {
206 9696 : int bad_ret = FALSE;
207 :
208 9696 : if (len)
209 : {
210 9612 : if (flags & VSTR_FLAG_SPLIT_REMAIN)
211 : {
212 46 : ASSERT(!limit || (added <= (limit - 1)));
213 :
214 46 : if (!vstr_sects_add(sects, pos, len))
215 1 : VSTR__SPLIT_HDL_ERR(&bad_ret);
216 :
217 45 : ++added;
218 : }
219 9566 : else if (!split_pos)
220 : {
221 9551 : if (!vstr_sects_add(sects, pos, len))
222 25 : VSTR__SPLIT_HDL_ERR(&bad_ret);
223 :
224 9551 : ++added;
225 : }
226 : }
227 84 : else if ((flags & VSTR_FLAG_SPLIT_POST_NULL) && (!limit || (added < limit)))
228 : {
229 16 : if (!vstr_sects_add(sects, pos, 0))
230 6 : VSTR__SPLIT_HDL_ERR(&bad_ret);
231 :
232 15 : ++added;
233 : }
234 :
235 9694 : return (added);
236 : }
237 :
238 : static unsigned int vstr__split_hdl_def(size_t *pos, size_t *len,
239 : size_t split_pos, size_t buf_len,
240 : Vstr_sects *sects,
241 : unsigned int flags,
242 : unsigned int added,
243 : int *bad_ret)
244 14284 : {
245 14284 : size_t split_len = (split_pos - *pos);
246 :
247 14284 : ASSERT(split_pos > *pos);
248 :
249 14284 : if (!vstr_sects_add(sects, *pos, split_len))
250 55 : VSTR__SPLIT_HDL_ERR(bad_ret);
251 :
252 14274 : ++added;
253 :
254 14274 : split_len += buf_len;
255 :
256 14274 : *pos += split_len;
257 14274 : *len -= split_len;
258 :
259 14274 : return (added);
260 : }
261 :
262 : unsigned int vstr_split_buf(const Vstr_base *base, size_t pos, size_t len,
263 : const void *buf, size_t buf_len,
264 : Vstr_sects *sects,
265 : unsigned int limit, unsigned int flags)
266 465 : {
267 465 : size_t orig_pos = pos;
268 465 : size_t split_pos = 0;
269 465 : unsigned int added = 0;
270 465 : const int is_remain = !!(flags & VSTR_FLAG_SPLIT_REMAIN);
271 465 : int bad_ret = FALSE;
272 :
273 11403 : while (len && (!limit || (added < (limit - is_remain))) &&
274 : (split_pos = vstr_srch_buf_fwd(base, pos, len, buf, buf_len)))
275 : {
276 10979 : if (split_pos == orig_pos)
277 : {
278 167 : unsigned int count = 0;
279 :
280 167 : assert(orig_pos == pos);
281 :
282 167 : if (vstr__split_buf_null_end(base, pos, len, buf, buf_len, &count))
283 : {
284 16 : if (!(flags & VSTR_FLAG_SPLIT_BEG_NULL))
285 5 : return (0);
286 :
287 11 : return (vstr__split_hdl_null_end(pos, len, buf_len, sects, flags,
288 : count, limit, added));
289 : }
290 151 : added = vstr__split_hdl_null_beg(&pos, &len, buf_len, sects, flags,
291 : count, limit, added, &bad_ret);
292 151 : if (bad_ret)
293 1 : return (added);
294 : }
295 10812 : else if (split_pos == pos)
296 : {
297 268 : unsigned int count = 0;
298 :
299 268 : if (vstr__split_buf_null_end(base, pos, len, buf, buf_len, &count))
300 18 : return (vstr__split_hdl_null_end(pos, len, buf_len, sects, flags,
301 : count, limit, added));
302 250 : added = vstr__split_hdl_null_mid(&pos, &len, buf_len, sects, flags,
303 : count, limit, added, &bad_ret);
304 250 : if (bad_ret)
305 1 : return (added);
306 : }
307 : else
308 : {
309 10544 : added = vstr__split_hdl_def(&pos, &len, split_pos, buf_len, sects,
310 : flags, added, &bad_ret);
311 10544 : if (bad_ret)
312 5 : return (added);
313 : }
314 : }
315 :
316 424 : return (vstr__split_hdl_end(pos, len, split_pos, sects, limit, flags, added));
317 : }
318 :
319 : unsigned int vstr_split_chrs(const Vstr_base *base, size_t pos, size_t len,
320 : const char *chrs, size_t chrs_len,
321 : Vstr_sects *sects,
322 : unsigned int limit, unsigned int flags)
323 9304 : {
324 9304 : size_t orig_pos = pos;
325 9304 : size_t split_pos = 0;
326 9304 : unsigned int added = 0;
327 9304 : const int is_remain = !!(flags & VSTR_FLAG_SPLIT_REMAIN);
328 9304 : int bad_ret = FALSE;
329 :
330 15020 : while (len && (!limit || (added < (limit - is_remain))) &&
331 : (split_pos = vstr_srch_chrs_fwd(base, pos, len, chrs, chrs_len)))
332 : {
333 5748 : if (split_pos == orig_pos)
334 : {
335 91 : unsigned int count = 0;
336 :
337 91 : assert(orig_pos == pos);
338 :
339 91 : if ((count = vstr_spn_chrs_fwd(base, pos, len, chrs, chrs_len)) == len)
340 : {
341 15 : if (!(flags & VSTR_FLAG_SPLIT_BEG_NULL))
342 5 : return (0);
343 :
344 10 : return (vstr__split_hdl_null_end(pos, len, 1, sects, flags,
345 : count, limit, added));
346 : }
347 76 : added = vstr__split_hdl_null_beg(&pos, &len, 1, sects, flags,
348 : count, limit, added, &bad_ret);
349 76 : if (bad_ret)
350 1 : return (added);
351 : }
352 5657 : else if (split_pos == pos)
353 : {
354 1917 : unsigned int count = 0;
355 :
356 1917 : if ((count = vstr_spn_chrs_fwd(base, pos, len, chrs, chrs_len)) == len)
357 10 : return (vstr__split_hdl_null_end(pos, len, 1, sects, flags,
358 : count, limit, added));
359 :
360 1907 : added = vstr__split_hdl_null_mid(&pos, &len, 1, sects, flags,
361 : count, limit, added, &bad_ret);
362 1907 : if (bad_ret)
363 1 : return (added);
364 : }
365 : else
366 : {
367 3740 : added = vstr__split_hdl_def(&pos, &len, split_pos, 1, sects,
368 : flags, added, &bad_ret);
369 3740 : if (bad_ret)
370 5 : return (added);
371 : }
372 : }
373 :
374 9272 : return (vstr__split_hdl_end(pos, len, split_pos, sects, limit, flags, added));
375 : }
376 : #undef VSTR__SPLIT_HDL_ERR
|