1 : /*
2 : * Copyright (C) 2002, 2003, 2004 James Antill
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, write to the Free Software
16 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 : *
18 : * email: james@and.org
19 : */
20 : /* not external inline functions */
21 : #ifdef VSTR_AUTOCONF_USE_WRAP_MEMRCHR
22 : extern inline void *vstr_wrap_memrchr(const void *passed_s1, int c, size_t n)
23 1644 : {
24 1644 : const unsigned char *s1 = passed_s1;
25 1644 : const void *ret = 0;
26 1644 : int tmp = 0;
27 :
28 1644 : switch (n)
29 : {
30 16 : case 7: tmp = s1[6] == c; if (tmp) { ret = s1 + 6; break; }
31 28 : case 6: tmp = s1[5] == c; if (tmp) { ret = s1 + 5; break; }
32 48 : case 5: tmp = s1[4] == c; if (tmp) { ret = s1 + 4; break; }
33 276 : case 4: tmp = s1[3] == c; if (tmp) { ret = s1 + 3; break; }
34 588 : case 3: tmp = s1[2] == c; if (tmp) { ret = s1 + 2; break; }
35 860 : case 2: tmp = s1[1] == c; if (tmp) { ret = s1 + 1; break; }
36 1204 : case 1: tmp = s1[0] == c; if (tmp) { ret = s1 + 0; break; }
37 : case 0:
38 356 : break;
39 356 : default: ret = memrchr(s1, c, n);
40 1644 : break;
41 : }
42 :
43 1644 : return ((void *)ret);
44 : }
45 : #else
46 : # define vstr_wrap_memrchr(x, y, z) memrchr(x, y, z)
47 : #endif
48 :
49 : #if USE_MALLOC_CHECK /* this is all non threadsafe ... */
50 : static inline void vstr__debug_alloc(void)
51 393228 : {
52 393228 : size_t sz = vstr__options.mem_sz;
53 :
54 393228 : ++vstr__options.mem_num;
55 :
56 393228 : if (!vstr__options.mem_sz)
57 : {
58 625 : sz = 8;
59 625 : vstr__options.mem_vals = malloc(sizeof(Vstr__debug_malloc) * sz);
60 : }
61 392603 : else if (vstr__options.mem_num > vstr__options.mem_sz)
62 : {
63 2767 : sz *= 2;
64 2767 : vstr__options.mem_vals = realloc(vstr__options.mem_vals,
65 : sizeof(Vstr__debug_malloc) * sz);
66 : }
67 393228 : ASSERT(vstr__options.mem_num <= sz);
68 393228 : ASSERT(vstr__options.mem_vals);
69 :
70 393228 : vstr__options.mem_sz = sz;
71 : }
72 :
73 : extern inline void *vstr__debug_malloc(size_t sz,
74 : const char *file, unsigned int line)
75 426758 : {
76 426758 : void *ret = NULL;
77 :
78 426758 : if (VSTR__DEBUG_MALLOC_DEC())
79 33530 : return (NULL);
80 :
81 393228 : vstr__debug_alloc();
82 :
83 393228 : ASSERT(sz);
84 :
85 393228 : ret = malloc(sz);
86 393228 : ASSERT_RET(ret, NULL);
87 :
88 393228 : memset(ret, 0xef, sz); /* poison */
89 :
90 393228 : vstr__options.mem_vals[vstr__options.mem_num - 1].ptr = ret;
91 393228 : vstr__options.mem_vals[vstr__options.mem_num - 1].file = file;
92 393228 : vstr__options.mem_vals[vstr__options.mem_num - 1].line = line;
93 :
94 393228 : return (ret);
95 : }
96 :
97 : extern inline unsigned int vstr__debug_malloc_check_mem(const void *ptr)
98 12208512 : {
99 12208512 : unsigned int scan = 0;
100 :
101 12208512 : ASSERT(vstr__options.mem_num);
102 :
103 -1504913274 : while (vstr__options.mem_vals[scan].ptr &&
104 : (vstr__options.mem_vals[scan].ptr != ptr))
105 -1517121786 : ++scan;
106 :
107 12208512 : ASSERT(vstr__options.mem_vals[scan].ptr);
108 :
109 12208512 : return (scan);
110 : }
111 :
112 : extern inline void vstr__debug_free(void *ptr)
113 380041 : {
114 380041 : if (ptr)
115 : {
116 380040 : unsigned int scan = vstr__debug_malloc_check_mem(ptr);
117 :
118 380040 : ASSERT(vstr__options.mem_num > 0);
119 380040 : --vstr__options.mem_num;
120 :
121 380040 : if (scan != vstr__options.mem_num)
122 : {
123 243464 : SWAP_TYPE(vstr__options.mem_vals[scan].ptr,
124 : vstr__options.mem_vals[vstr__options.mem_num].ptr,
125 : void *);
126 243464 : SWAP_TYPE(vstr__options.mem_vals[scan].file,
127 : vstr__options.mem_vals[vstr__options.mem_num].file,
128 : const char *);
129 243464 : SWAP_TYPE(vstr__options.mem_vals[scan].line,
130 : vstr__options.mem_vals[vstr__options.mem_num].line,
131 : unsigned int);
132 : }
133 380040 : vstr__options.mem_vals[vstr__options.mem_num].ptr = NULL;
134 380040 : free(ptr);
135 : }
136 : }
137 :
138 : extern inline void *vstr__debug_realloc(void *ptr, size_t sz,
139 : const char *file, unsigned int line)
140 113161 : {
141 113161 : void *ret = NULL;
142 :
143 113161 : ASSERT(ptr && sz);
144 :
145 113161 : if (VSTR__DEBUG_MALLOC_DEC())
146 378 : return (NULL);
147 :
148 112783 : ret = realloc(ptr, sz);
149 112783 : ASSERT_RET(ret, NULL);
150 :
151 112783 : if (ptr != ret) /* not ISO C compliant */
152 : {
153 22181 : unsigned int scan = vstr__debug_malloc_check_mem(ptr);
154 :
155 22181 : vstr__options.mem_vals[scan].ptr = ret;
156 22181 : vstr__options.mem_vals[scan].file = file;
157 22181 : vstr__options.mem_vals[scan].line = line;
158 : }
159 :
160 112783 : return (ret);
161 : }
162 : extern inline void vstr__debug_malloc_check_empty(void)
163 607 : {
164 607 : if (0 && vstr__options.mem_num) /* needs to be zero'd for coverage testing */
165 : {
166 607 : unsigned int scan = 0;
167 :
168 607 : while (vstr__options.mem_vals[scan].ptr)
169 : {
170 607 : fprintf(stderr, " FAILED MEM CHECK EMPTY: ptr %p from %u:%s\n",
171 : vstr__options.mem_vals[scan].ptr,
172 : vstr__options.mem_vals[scan].line,
173 : vstr__options.mem_vals[scan].file);
174 607 : ++scan;
175 : }
176 : }
177 607 : ASSERT(!vstr__options.mem_num);
178 : }
179 : #endif
180 :
181 : /* zero ->used and normalise first node */
182 : extern inline void vstr__base_zero_used(Vstr_base *base)
183 119128 : {
184 119128 : if (base->used)
185 : {
186 18 : ASSERT(base->beg->type == VSTR_TYPE_NODE_BUF);
187 18 : base->beg->len -= base->used;
188 18 : vstr_wrap_memmove(((Vstr_node_buf *)base->beg)->buf,
189 : ((Vstr_node_buf *)base->beg)->buf + base->used,
190 : base->beg->len);
191 18 : base->used = 0;
192 : }
193 : }
194 :
195 : extern inline void vstr__cache_iovec_reset_node(const Vstr_base *base,
196 : Vstr_node *node,
197 : unsigned int num)
198 29516 : {
199 29516 : struct iovec *iovs = NULL;
200 29516 : unsigned char *types = NULL;
201 :
202 29516 : if (!base->iovec_upto_date)
203 17064 : return;
204 :
205 12452 : iovs = VSTR__CACHE(base)->vec->v + VSTR__CACHE(base)->vec->off;
206 12452 : iovs[num - 1].iov_len = node->len;
207 12452 : iovs[num - 1].iov_base = vstr_export__node_ptr(node);
208 :
209 12452 : types = VSTR__CACHE(base)->vec->t + VSTR__CACHE(base)->vec->off;
210 12452 : types[num - 1] = node->type;
211 :
212 12452 : if (num == 1)
213 : {
214 8489 : char *tmp = NULL;
215 :
216 8489 : iovs[num - 1].iov_len -= base->used;
217 8489 : tmp = iovs[num - 1].iov_base;
218 8489 : tmp += base->used;
219 8489 : iovs[num - 1].iov_base = tmp;
220 : }
221 : }
222 :
223 : extern inline void vstr__relink_nodes(Vstr_conf *conf,
224 : Vstr_node *beg, Vstr_node **end_next,
225 : unsigned int num)
226 760746 : {
227 760746 : Vstr_node *tmp = NULL;
228 :
229 760746 : ASSERT(beg->type == VSTR__CONV_PTR_NEXT_PREV(end_next)->type);
230 :
231 760746 : switch (beg->type)
232 : {
233 : case VSTR_TYPE_NODE_BUF:
234 324061 : tmp = (Vstr_node *)conf->spare_buf_beg;
235 :
236 324061 : conf->spare_buf_num += num;
237 :
238 324061 : conf->spare_buf_beg = (Vstr_node_buf *)beg;
239 324061 : break;
240 :
241 : case VSTR_TYPE_NODE_NON:
242 1547 : tmp = (Vstr_node *)conf->spare_non_beg;
243 :
244 1547 : conf->spare_non_num += num;
245 :
246 1547 : conf->spare_non_beg = (Vstr_node_non *)beg;
247 1547 : break;
248 :
249 : case VSTR_TYPE_NODE_PTR:
250 266067 : tmp = (Vstr_node *)conf->spare_ptr_beg;
251 :
252 266067 : conf->spare_ptr_num += num;
253 :
254 266067 : conf->spare_ptr_beg = (Vstr_node_ptr *)beg;
255 266067 : break;
256 :
257 : case VSTR_TYPE_NODE_REF:
258 169071 : tmp = (Vstr_node *)conf->spare_ref_beg;
259 :
260 169071 : conf->spare_ref_num += num;
261 :
262 169071 : conf->spare_ref_beg = (Vstr_node_ref *)beg;
263 :
264 43579 : ASSERT_NO_SWITCH_DEF();
265 : }
266 :
267 760746 : *end_next = tmp;
268 : }
269 :
270 : /* sequence could get annoying ... too many special cases */
271 : extern inline int vstr__base_scan_rev_beg(const Vstr_base *base,
272 : size_t pos, size_t *len,
273 : unsigned int *num, unsigned int *type,
274 : char **scan_str, size_t *scan_len)
275 28607 : {
276 28607 : Vstr_node *scan_beg = NULL;
277 28607 : Vstr_node *scan_end = NULL;
278 28607 : unsigned int dummy_num = 0;
279 28607 : size_t end_pos = 0;
280 :
281 28607 : ASSERT(base && num && len && type && scan_str && scan_len);
282 :
283 28607 : if (!*len)
284 183 : return (FALSE);
285 :
286 28424 : ASSERT_RET(((pos + *len - 1) <= base->len), FALSE);
287 :
288 28408 : assert(base->iovec_upto_date);
289 :
290 28408 : end_pos = pos;
291 28408 : end_pos += *len - 1;
292 28408 : scan_beg = vstr_base__pos(base, &pos, &dummy_num, TRUE);
293 28408 : --pos;
294 :
295 28408 : scan_end = vstr_base__pos(base, &end_pos, num, FALSE);
296 :
297 28408 : *type = scan_end->type;
298 :
299 28408 : if (scan_beg != scan_end)
300 : {
301 2999 : assert(*num != dummy_num);
302 2999 : assert(scan_end != base->beg);
303 :
304 2999 : pos = 0;
305 2999 : *scan_len = end_pos;
306 :
307 2999 : assert(*scan_len < *len);
308 2999 : *len -= *scan_len;
309 : }
310 : else
311 : {
312 25409 : assert(scan_end->len >= *len);
313 25409 : *scan_len = *len;
314 25409 : *len = 0;
315 : }
316 :
317 28408 : *scan_str = NULL;
318 28408 : if (scan_end->type != VSTR_TYPE_NODE_NON)
319 28392 : *scan_str = vstr_export__node_ptr(scan_end) + pos;
320 :
321 28408 : return (TRUE);
322 : }
323 :
324 : extern inline int vstr__base_scan_rev_nxt(const Vstr_base *base, size_t *len,
325 : unsigned int *num, unsigned int *type,
326 : char **scan_str, size_t *scan_len)
327 1288 : {
328 1288 : struct iovec *iovs = NULL;
329 1288 : unsigned char *types = NULL;
330 1288 : size_t pos = 0;
331 :
332 1288 : ASSERT(base && num && len && type && scan_str && scan_len);
333 :
334 1288 : assert(base->iovec_upto_date);
335 :
336 1288 : assert(num);
337 :
338 1288 : if (!*len || !--*num)
339 176 : return (FALSE);
340 :
341 1112 : iovs = VSTR__CACHE(base)->vec->v + VSTR__CACHE(base)->vec->off;
342 1112 : types = VSTR__CACHE(base)->vec->t + VSTR__CACHE(base)->vec->off;
343 :
344 1112 : *type = types[*num - 1];
345 1112 : *scan_len = iovs[*num - 1].iov_len;
346 :
347 1112 : if (*scan_len > *len)
348 : {
349 12 : pos = *scan_len - *len;
350 12 : *scan_len = *len;
351 : }
352 1112 : *len -= *scan_len;
353 :
354 1112 : *scan_str = NULL;
355 1112 : if (*type != VSTR_TYPE_NODE_NON)
356 1004 : *scan_str = ((char *) (iovs[*num - 1].iov_base)) + pos;
357 :
358 1112 : return (TRUE);
359 : }
360 :
361 : extern inline const char *
362 : vstr__loc_num_grouping(Vstr_locale *loc, unsigned int num_base)
363 317226 : {
364 317226 : Vstr_locale_num_base *srch = vstr__loc_num_srch(loc, num_base, FALSE);
365 :
366 317226 : return (srch->grouping->ptr);
367 : }
368 :
369 : extern inline const char *
370 : vstr__loc_num_sep_ptr(Vstr_locale *loc, unsigned int num_base)
371 312741 : {
372 312741 : Vstr_locale_num_base *srch = vstr__loc_num_srch(loc, num_base, FALSE);
373 :
374 312741 : return (srch->thousands_sep_ref->ptr);
375 : }
376 :
377 : extern inline size_t
378 : vstr__loc_num_sep_len(Vstr_locale *loc, unsigned int num_base)
379 317226 : {
380 317226 : Vstr_locale_num_base *srch = vstr__loc_num_srch(loc, num_base, FALSE);
381 :
382 317226 : return (srch->thousands_sep_len);
383 : }
384 :
385 : extern inline const char *
386 : vstr__loc_num_pnt_ptr(Vstr_locale *loc, unsigned int num_base)
387 145086 : {
388 145086 : Vstr_locale_num_base *srch = vstr__loc_num_srch(loc, num_base, FALSE);
389 :
390 145086 : return (srch->decimal_point_ref->ptr);
391 : }
392 :
393 : extern inline size_t
394 : vstr__loc_num_pnt_len(Vstr_locale *loc, unsigned int num_base)
395 145086 : {
396 145086 : Vstr_locale_num_base *srch = vstr__loc_num_srch(loc, num_base, FALSE);
397 :
398 145086 : return (srch->decimal_point_len);
399 : }
400 :
|