1 : #define VSTR_SPN_C
2 : /*
3 : * Copyright (C) 1999, 2000, 2001, 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 : /* functionss for counting a "spanning" of chars within a vstr */
22 : #include "main.h"
23 :
24 : static size_t vstr__spn_chr_fwd(const Vstr_base *base, size_t pos, size_t len,
25 : char spn_chr)
26 74710 : {
27 74710 : Vstr_iter iter[1];
28 74710 : size_t ret = 0;
29 :
30 74710 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
31 163 : return (0);
32 :
33 85645 : do
34 : {
35 85645 : size_t count = 0;
36 :
37 85645 : if (iter->node->type == VSTR_TYPE_NODE_NON)
38 20 : return (ret);
39 :
40 104115 : while (count < iter->len)
41 : {
42 90726 : if (spn_chr != iter->ptr[count])
43 72236 : return (ret + count);
44 18490 : ++count;
45 : }
46 13389 : assert(count == iter->len);
47 :
48 13389 : ret += iter->len;
49 13389 : } while (vstr_iter_fwd_nxt(iter));
50 :
51 2291 : return (ret);
52 : }
53 :
54 : size_t vstr_spn_chrs_fwd(const Vstr_base *base, size_t pos, size_t len,
55 : const char *spn_chrs, size_t spn_len)
56 347396 : {
57 347396 : Vstr_iter iter[1];
58 347396 : size_t ret = 0;
59 :
60 347396 : ASSERT_RET(base, 0);
61 :
62 347396 : if (!spn_chrs && !base->node_non_used)
63 112228 : return (0);
64 :
65 235168 : if (spn_chrs && (spn_len == 1))
66 74710 : return (vstr__spn_chr_fwd(base, pos, len, *spn_chrs));
67 :
68 160458 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
69 18062 : return (0);
70 :
71 143125 : do
72 : {
73 143125 : size_t count = 0;
74 :
75 143125 : if ((iter->node->type == VSTR_TYPE_NODE_NON) && spn_chrs)
76 40 : return (ret);
77 :
78 143085 : if (iter->node->type == VSTR_TYPE_NODE_NON)
79 : {
80 150 : assert(!spn_chrs);
81 28242 : goto next_loop;
82 : }
83 :
84 142935 : if (!spn_chrs)
85 210 : return (ret);
86 :
87 257244 : while (count < iter->len)
88 : {
89 255224 : if (!vstr_wrap_memchr(spn_chrs, iter->ptr[count], spn_len))
90 140705 : return (ret + count);
91 114519 : ++count;
92 : }
93 2139 : assert(count == iter->len);
94 :
95 : next_loop:
96 2170 : ret += iter->len;
97 2170 : } while (vstr_iter_fwd_nxt(iter));
98 :
99 1441 : return (ret);
100 : }
101 :
102 : #if 0
103 : static size_t VSTR__ATTR_I() vstr__spn_chrs_rev_slow(const Vstr_base *base,
104 : size_t pos, size_t len,
105 : const char *spn_chrs, size_t spn_len);
106 : #endif
107 : /* go through fwd, reset everytime it fails then start doing it again */
108 : static size_t vstr__spn_chrs_rev_slow(const Vstr_base *base,
109 : size_t pos, size_t len,
110 : const char *spn_chrs, size_t spn_len)
111 220 : {
112 220 : Vstr_iter iter[1];
113 220 : size_t ret = 0;
114 :
115 220 : if (!spn_chrs && !base->node_non_used)
116 12 : return (0);
117 :
118 208 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
119 12 : return (0);
120 :
121 454 : do
122 : {
123 454 : size_t count = 0;
124 :
125 454 : if ((iter->node->type == VSTR_TYPE_NODE_NON) && spn_chrs)
126 : {
127 12 : ret = 0;
128 12 : continue;
129 : }
130 :
131 442 : if (iter->node->type == VSTR_TYPE_NODE_NON)
132 : {
133 12 : assert(!spn_chrs);
134 111 : goto next_loop_all_good;
135 : }
136 :
137 430 : if (!spn_chrs)
138 : {
139 12 : ret = 0;
140 12 : continue;
141 : }
142 :
143 418 : count = iter->len;
144 2037 : while (count-- > 0)
145 1834 : if (!vstr_wrap_memchr(spn_chrs, iter->ptr[count], spn_len))
146 : {
147 215 : ret = ((iter->len - count) - 1);
148 215 : goto next_loop_memchr_fail;
149 : }
150 :
151 : next_loop_all_good:
152 215 : ret += iter->len;
153 :
154 : next_loop_memchr_fail:
155 454 : continue;
156 454 : } while (vstr_iter_fwd_nxt(iter));
157 :
158 196 : return (ret);
159 : }
160 :
161 : static size_t vstr__spn_chrs_rev_fast(const Vstr_base *base,
162 : size_t pos, size_t len,
163 : const char *spn_chrs, size_t spn_len)
164 28279 : {
165 28279 : unsigned int num = 0;
166 28279 : unsigned int type = 0;
167 28279 : size_t ret = 0;
168 28279 : char *scan_str = NULL;
169 28279 : size_t scan_len = 0;
170 :
171 28279 : if (!spn_chrs && !base->node_non_used)
172 8 : return (0);
173 :
174 28271 : if (!vstr__base_scan_rev_beg(base, pos, &len, &num, &type,
175 : &scan_str, &scan_len))
176 167 : return (0);
177 :
178 28208 : do
179 : {
180 28208 : size_t count = 0;
181 :
182 28208 : if ((type == VSTR_TYPE_NODE_NON) && spn_chrs)
183 8 : return (ret);
184 :
185 28200 : if (type == VSTR_TYPE_NODE_NON)
186 : {
187 8 : assert(!spn_chrs);
188 6173 : goto next_loop;
189 : }
190 :
191 28192 : if (!spn_chrs)
192 8 : return (ret);
193 :
194 47162 : while (count < scan_len)
195 : {
196 46994 : ++count;
197 46994 : if (!vstr_wrap_memchr(spn_chrs, scan_str[scan_len - count], spn_len))
198 28016 : return (ret + (count - 1));
199 : }
200 174 : assert(count == scan_len);
201 :
202 : next_loop:
203 176 : ret += scan_len;
204 176 : } while (vstr__base_scan_rev_nxt(base, &len, &num, &type,
205 : &scan_str, &scan_len));
206 :
207 72 : return (ret);
208 : }
209 :
210 : size_t vstr_spn_chrs_rev(const Vstr_base *base, size_t pos, size_t len,
211 : const char *spn_chrs, size_t spn_len)
212 28499 : {
213 28499 : ASSERT_RET(base, 0);
214 :
215 28499 : if (base->iovec_upto_date)
216 28279 : return (vstr__spn_chrs_rev_fast(base, pos, len, spn_chrs, spn_len));
217 :
218 220 : return (vstr__spn_chrs_rev_slow(base, pos, len, spn_chrs, spn_len));
219 : }
220 :
221 : size_t vstr_cspn_chrs_fwd(const Vstr_base *base, size_t pos, size_t len,
222 : const char *cspn_chrs, size_t cspn_len)
223 660544 : {
224 660544 : Vstr_iter iter[1];
225 660544 : size_t ret = 0;
226 :
227 660544 : ASSERT_RET(base, 0);
228 660544 : if (!cspn_chrs && !base->node_non_used)
229 20 : return (len);
230 :
231 660524 : if (cspn_chrs && (cspn_len == 1))
232 : {
233 16683 : size_t f_pos = vstr_srch_chr_fwd(base, pos, len, cspn_chrs[0]);
234 :
235 16683 : if (!f_pos)
236 14076 : return (len);
237 :
238 2607 : return (f_pos - pos);
239 : }
240 :
241 643841 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
242 12 : return (0);
243 :
244 656936 : do
245 : {
246 656936 : size_t count = 0;
247 :
248 656936 : if ((iter->node->type == VSTR_TYPE_NODE_NON) && cspn_chrs)
249 20 : goto next_loop;
250 :
251 656916 : if (iter->node->type == VSTR_TYPE_NODE_NON)
252 : {
253 20 : assert(!cspn_chrs);
254 20 : return (ret);
255 : }
256 :
257 656896 : if (!cspn_chrs)
258 20 : goto next_loop;
259 :
260 2465882 : while (count < iter->len)
261 : {
262 2426320 : if (vstr_wrap_memchr(cspn_chrs, iter->ptr[count], cspn_len))
263 617314 : return (ret + count);
264 1809006 : ++count;
265 : }
266 39592 : assert(count == iter->len);
267 :
268 : next_loop:
269 39602 : ret += iter->len;
270 39602 : } while (vstr_iter_fwd_nxt(iter));
271 :
272 26495 : return (ret);
273 : }
274 :
275 : /* go through fwd, reset everytime it fails then start doing it again */
276 : static size_t vstr__cspn_chrs_rev_slow(const Vstr_base *base,
277 : size_t pos, size_t len,
278 : const char *cspn_chrs, size_t cspn_len)
279 140 : {
280 140 : Vstr_iter iter[1];
281 140 : size_t ret = 0;
282 :
283 140 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
284 8 : return (0);
285 :
286 528 : do
287 : {
288 528 : size_t count = 0;
289 :
290 528 : if ((iter->node->type == VSTR_TYPE_NODE_NON) && cspn_chrs)
291 12 : goto next_loop_all_good;
292 :
293 516 : if (iter->node->type == VSTR_TYPE_NODE_NON)
294 : {
295 12 : assert(!cspn_chrs);
296 12 : ret = 0;
297 12 : continue;
298 : }
299 :
300 504 : if (!cspn_chrs)
301 24 : goto next_loop_all_good;
302 :
303 480 : count = iter->len;
304 3164 : while (count-- > 0)
305 2844 : if (vstr_wrap_memchr(cspn_chrs, iter->ptr[count], cspn_len))
306 : {
307 160 : ret = ((iter->len - count) - 1);
308 160 : goto next_loop_memchr_fail;
309 : }
310 :
311 : next_loop_all_good:
312 356 : ret += iter->len;
313 :
314 : next_loop_memchr_fail:
315 528 : continue;
316 528 : } while (vstr_iter_fwd_nxt(iter));
317 :
318 132 : return (ret);
319 : }
320 :
321 : static size_t vstr__cspn_chrs_rev_fast(const Vstr_base *base,
322 : size_t pos, size_t len,
323 : const char *cspn_chrs, size_t cspn_len)
324 96 : {
325 96 : unsigned int num = 0;
326 96 : unsigned int type = 0;
327 96 : size_t ret = 0;
328 96 : char *scan_str = NULL;
329 96 : size_t scan_len = 0;
330 :
331 96 : if (!vstr__base_scan_rev_beg(base, pos, &len, &num, &type,
332 : &scan_str, &scan_len))
333 8 : return (0);
334 :
335 264 : do
336 : {
337 264 : size_t count = 0;
338 :
339 264 : if ((type == VSTR_TYPE_NODE_NON) && cspn_chrs)
340 8 : goto next_loop;
341 :
342 256 : if (type == VSTR_TYPE_NODE_NON)
343 : {
344 8 : assert(!cspn_chrs);
345 8 : return (ret);
346 : }
347 :
348 248 : if (!cspn_chrs)
349 8 : goto next_loop;
350 :
351 1648 : while (count < scan_len)
352 : {
353 1472 : ++count;
354 1472 : if (vstr_wrap_memchr(cspn_chrs, scan_str[scan_len - count], cspn_len))
355 64 : return (ret + (count - 1));
356 : }
357 188 : assert(count == scan_len);
358 :
359 : next_loop:
360 192 : ret += scan_len;
361 192 : } while (vstr__base_scan_rev_nxt(base, &len, &num, &type,
362 : &scan_str, &scan_len));
363 :
364 16 : return (ret);
365 : }
366 :
367 : size_t vstr_cspn_chrs_rev(const Vstr_base *base, size_t pos, size_t len,
368 : const char *cspn_chrs, size_t cspn_len)
369 381 : {
370 381 : ASSERT_RET(base, 0);
371 :
372 381 : if (!cspn_chrs && !base->node_non_used)
373 20 : return (len);
374 :
375 361 : if (cspn_chrs && (cspn_len == 1))
376 : {
377 125 : size_t f_pos = vstr_srch_chr_rev(base, pos, len, cspn_chrs[0]);
378 :
379 125 : if (!f_pos)
380 65 : return (len);
381 :
382 60 : return ((pos + (len - 1)) - f_pos);
383 : }
384 :
385 236 : if (base->iovec_upto_date)
386 96 : return (vstr__cspn_chrs_rev_fast(base, pos, len, cspn_chrs, cspn_len));
387 :
388 140 : return (vstr__cspn_chrs_rev_slow(base, pos, len, cspn_chrs, cspn_len));
389 : }
|