Line | Count | Source (jump to first uncovered line) |
1 | | /*************************************************************************** |
2 | | * Copyright (c) 2009-2010 Open Information Security Foundation |
3 | | * Copyright (c) 2010-2013 Qualys, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions are |
8 | | * met: |
9 | | * |
10 | | * - Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | |
13 | | * - Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | |
17 | | * - Neither the name of the Qualys, Inc. nor the names of its |
18 | | * contributors may be used to endorse or promote products derived from |
19 | | * this software without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
23 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
24 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
25 | | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
31 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | | ***************************************************************************/ |
33 | | |
34 | | /** |
35 | | * @file |
36 | | * @author Ivan Ristic <ivanr@webkreator.com> |
37 | | */ |
38 | | |
39 | | #include <ctype.h> |
40 | | |
41 | | #include "bstr.h" |
42 | | |
43 | 941k | bstr *bstr_alloc(size_t len) { |
44 | 941k | bstr *b = malloc(sizeof (bstr) + len); |
45 | 941k | if (b == NULL) return NULL; |
46 | | |
47 | 941k | b->len = 0; |
48 | 941k | b->size = len; |
49 | 941k | b->realptr = NULL; |
50 | | |
51 | 941k | return b; |
52 | 941k | } |
53 | | |
54 | 0 | bstr *bstr_add(bstr *destination, const bstr *source) { |
55 | 0 | return bstr_add_mem(destination, bstr_ptr(source), bstr_len(source)); |
56 | 0 | } |
57 | | |
58 | 0 | bstr *bstr_add_c(bstr *bdestination, const char *csource) { |
59 | 0 | return bstr_add_mem(bdestination, csource, strlen(csource)); |
60 | 0 | } |
61 | | |
62 | 0 | bstr *bstr_add_c_noex(bstr *destination, const char *source) { |
63 | 0 | return bstr_add_mem_noex(destination, source, strlen(source)); |
64 | 0 | } |
65 | | |
66 | 37.6k | bstr *bstr_add_mem(bstr *destination, const void *data, size_t len) { |
67 | | // Expand the destination if necessary |
68 | 37.6k | if (bstr_size(destination) < bstr_len(destination) + len) { |
69 | 13.6k | destination = bstr_expand(destination, bstr_len(destination) + len); |
70 | 13.6k | if (destination == NULL) return NULL; |
71 | 13.6k | } |
72 | | |
73 | | // Add source to destination |
74 | 37.6k | bstr *b = (bstr *) destination; |
75 | 37.6k | memcpy(bstr_ptr(destination) + bstr_len(b), data, len); |
76 | 37.6k | bstr_adjust_len(b, bstr_len(b) + len); |
77 | | |
78 | 37.6k | return destination; |
79 | 37.6k | } |
80 | | |
81 | 82.0k | bstr *bstr_add_mem_noex(bstr *destination, const void *data, size_t len) { |
82 | 82.0k | size_t copylen = len; |
83 | | |
84 | | // Is there enough room in the destination? |
85 | 82.0k | if (bstr_size(destination) < bstr_len(destination) + copylen) { |
86 | 0 | copylen = bstr_size(destination) - bstr_len(destination); |
87 | 0 | if (copylen <= 0) return destination; |
88 | 0 | } |
89 | | |
90 | | // Copy over the bytes |
91 | 82.0k | bstr *b = (bstr *) destination; |
92 | 82.0k | memcpy(bstr_ptr(destination) + bstr_len(b), data, copylen); |
93 | 82.0k | bstr_adjust_len(b, bstr_len(b) + copylen); |
94 | | |
95 | 82.0k | return destination; |
96 | 82.0k | } |
97 | | |
98 | 41.0k | bstr *bstr_add_noex(bstr *destination, const bstr *source) { |
99 | 41.0k | return bstr_add_mem_noex(destination, bstr_ptr(source), bstr_len(source)); |
100 | 41.0k | } |
101 | | |
102 | 1.15M | void bstr_adjust_len(bstr *b, size_t newlen) { |
103 | 1.15M | b->len = newlen; |
104 | 1.15M | } |
105 | | |
106 | 0 | void bstr_adjust_realptr(bstr *b, void *newrealptr) { |
107 | 0 | b->realptr = newrealptr; |
108 | 0 | } |
109 | | |
110 | 54.6k | void bstr_adjust_size(bstr *b, size_t newsize) { |
111 | 54.6k | b->size = newsize; |
112 | 54.6k | } |
113 | | |
114 | 0 | int bstr_begins_with(const bstr *haystack, const bstr *needle) { |
115 | 0 | return bstr_begins_with_mem(haystack, bstr_ptr(needle), bstr_len(needle)); |
116 | 0 | } |
117 | | |
118 | 0 | int bstr_begins_with_c(const bstr *haystack, const char *needle) { |
119 | 0 | return bstr_begins_with_mem(haystack, needle, strlen(needle)); |
120 | 0 | } |
121 | | |
122 | 0 | int bstr_begins_with_c_nocase(const bstr *haystack, const char *needle) { |
123 | 0 | return bstr_begins_with_mem_nocase(haystack, needle, strlen(needle)); |
124 | 0 | } |
125 | | |
126 | 0 | int bstr_begins_with_nocase(const bstr *haystack, const bstr *needle) { |
127 | 0 | return bstr_begins_with_mem_nocase(haystack, bstr_ptr(needle), bstr_len(needle)); |
128 | 0 | } |
129 | | |
130 | 0 | int bstr_begins_with_mem(const bstr *haystack, const void *_data, size_t len) { |
131 | 0 | const unsigned char *data = (unsigned char *) _data; |
132 | 0 | const unsigned char *hdata = bstr_ptr(haystack); |
133 | 0 | size_t hlen = bstr_len(haystack); |
134 | 0 | size_t pos = 0; |
135 | |
|
136 | 0 | while ((pos < len) && (pos < hlen)) { |
137 | 0 | if (hdata[pos] != data[pos]) { |
138 | 0 | return 0; |
139 | 0 | } |
140 | | |
141 | 0 | pos++; |
142 | 0 | } |
143 | | |
144 | 0 | if (pos == len) { |
145 | 0 | return 1; |
146 | 0 | } else { |
147 | 0 | return 0; |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | int bstr_begins_with_mem_nocase(const bstr *haystack, const void *_data, size_t len) { |
152 | 0 | const unsigned char *data = (const unsigned char *) _data; |
153 | 0 | const unsigned char *hdata = bstr_ptr(haystack); |
154 | 0 | size_t hlen = bstr_len(haystack); |
155 | 0 | size_t pos = 0; |
156 | |
|
157 | 0 | while ((pos < len) && (pos < hlen)) { |
158 | 0 | if (tolower((int) hdata[pos]) != tolower((int) data[pos])) { |
159 | 0 | return 0; |
160 | 0 | } |
161 | | |
162 | 0 | pos++; |
163 | 0 | } |
164 | | |
165 | 0 | if (pos == len) { |
166 | 0 | return 1; |
167 | 0 | } else { |
168 | 0 | return 0; |
169 | 0 | } |
170 | 0 | } |
171 | | |
172 | 0 | int bstr_char_at(const bstr *b, size_t pos) { |
173 | 0 | unsigned char *data = bstr_ptr(b); |
174 | 0 | size_t len = bstr_len(b); |
175 | |
|
176 | 0 | if (pos >= len) return -1; |
177 | 0 | return data[pos]; |
178 | 0 | } |
179 | | |
180 | 16.3k | int bstr_char_at_end(const bstr *b, size_t pos) { |
181 | 16.3k | unsigned char *data = bstr_ptr(b); |
182 | 16.3k | size_t len = bstr_len(b); |
183 | | |
184 | 16.3k | if (pos >= len) return -1; |
185 | 8.79k | return data[len - 1 - pos]; |
186 | 16.3k | } |
187 | | |
188 | 983 | void bstr_chop(bstr *b) { |
189 | 983 | if (bstr_len(b) > 0) { |
190 | 983 | bstr_adjust_len(b, bstr_len(b) - 1); |
191 | 983 | } |
192 | 983 | } |
193 | | |
194 | 1.87k | int bstr_chr(const bstr *b, int c) { |
195 | 1.87k | unsigned char *data = bstr_ptr(b); |
196 | 1.87k | size_t len = bstr_len(b); |
197 | | |
198 | 1.87k | size_t i = 0; |
199 | 18.0M | while (i < len) { |
200 | 18.0M | if (data[i] == c) { |
201 | 1.33k | return (int) i; |
202 | 1.33k | } |
203 | | |
204 | 18.0M | i++; |
205 | 18.0M | } |
206 | | |
207 | 535 | return -1; |
208 | 1.87k | } |
209 | | |
210 | 0 | int bstr_cmp(const bstr *b1, const bstr *b2) { |
211 | 0 | return bstr_util_cmp_mem(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2)); |
212 | 0 | } |
213 | | |
214 | 2.34M | int bstr_cmp_c(const bstr *b, const char *c) { |
215 | 2.34M | return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
216 | 2.34M | } |
217 | | |
218 | 41.0k | int bstr_cmp_c_nocase(const bstr *b, const char *c) { |
219 | 41.0k | return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
220 | 41.0k | } |
221 | | |
222 | 342k | int bstr_cmp_c_nocasenorzero(const bstr *b, const char *c) { |
223 | 342k | return bstr_util_cmp_mem_nocasenorzero(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
224 | 342k | } |
225 | | |
226 | 0 | int bstr_cmp_mem(const bstr *b, const void *data, size_t len) { |
227 | 0 | return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), data, len); |
228 | 0 | } |
229 | | |
230 | 0 | int bstr_cmp_mem_nocase(const bstr *b, const void *data, size_t len) { |
231 | 0 | return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), data, len); |
232 | 0 | } |
233 | | |
234 | 399k | int bstr_cmp_nocase(const bstr *b1, const bstr *b2) { |
235 | 399k | return bstr_util_cmp_mem_nocase(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2)); |
236 | 399k | } |
237 | | |
238 | 128k | bstr *bstr_dup(const bstr *b) { |
239 | 128k | return bstr_dup_ex(b, 0, bstr_len(b)); |
240 | 128k | } |
241 | | |
242 | 92.1k | bstr *bstr_dup_c(const char *cstr) { |
243 | 92.1k | return bstr_dup_mem(cstr, strlen(cstr)); |
244 | 92.1k | } |
245 | | |
246 | 128k | bstr *bstr_dup_ex(const bstr *b, size_t offset, size_t len) { |
247 | 128k | bstr *bnew = bstr_alloc(len); |
248 | 128k | if (bnew == NULL) return NULL; |
249 | 128k | memcpy(bstr_ptr(bnew), bstr_ptr(b) + offset, len); |
250 | 128k | bstr_adjust_len(bnew, len); |
251 | 128k | return bnew; |
252 | 128k | } |
253 | | |
254 | 12.9k | bstr *bstr_dup_lower(const bstr *b) { |
255 | 12.9k | return bstr_to_lowercase(bstr_dup(b)); |
256 | 12.9k | } |
257 | | |
258 | 812k | bstr *bstr_dup_mem(const void *data, size_t len) { |
259 | 812k | bstr *bnew = bstr_alloc(len); |
260 | 812k | if (bnew == NULL) return NULL; |
261 | 812k | memcpy(bstr_ptr(bnew), data, len); |
262 | 812k | bstr_adjust_len(bnew, len); |
263 | 812k | return bnew; |
264 | 812k | } |
265 | | |
266 | 54.6k | bstr *bstr_expand(bstr *b, size_t newsize) { |
267 | 54.6k | if (bstr_realptr(b) != NULL) { |
268 | | // Refuse to expand a wrapped bstring. In the future, |
269 | | // we can change this to make a copy of the data, thus |
270 | | // leaving the original memory area intact. |
271 | 0 | return NULL; |
272 | 0 | } |
273 | | |
274 | | // Catch attempts to "expand" to a smaller size |
275 | 54.6k | if (bstr_size(b) > newsize) return NULL; |
276 | | |
277 | 54.6k | bstr *bnew = realloc(b, sizeof (bstr) + newsize); |
278 | 54.6k | if (bnew == NULL) return NULL; |
279 | | |
280 | 54.6k | bstr_adjust_size(bnew, newsize); |
281 | | |
282 | 54.6k | return bnew; |
283 | 54.6k | } |
284 | | |
285 | 2.95M | void bstr_free(bstr *b) { |
286 | 2.95M | if (b == NULL) return; |
287 | 941k | free(b); |
288 | 941k | } |
289 | | |
290 | 0 | int bstr_index_of(const bstr *haystack, const bstr *needle) { |
291 | 0 | return bstr_index_of_mem(haystack, bstr_ptr(needle), bstr_len(needle)); |
292 | 0 | } |
293 | | |
294 | 0 | int bstr_index_of_c(const bstr *haystack, const char *needle) { |
295 | 0 | return bstr_index_of_mem(haystack, needle, strlen(needle)); |
296 | 0 | } |
297 | | |
298 | 91 | int bstr_index_of_c_nocase(const bstr *haystack, const char *needle) { |
299 | 91 | return bstr_index_of_mem_nocase(haystack, needle, strlen(needle)); |
300 | 91 | } |
301 | | |
302 | 0 | int bstr_index_of_c_nocasenorzero(const bstr *haystack, const char *needle) { |
303 | 0 | return bstr_util_mem_index_of_mem_nocasenorzero(bstr_ptr(haystack), bstr_len(haystack), needle, strlen(needle)); |
304 | 0 | } |
305 | | |
306 | 0 | int bstr_index_of_mem(const bstr *haystack, const void *_data2, size_t len2) { |
307 | 0 | return bstr_util_mem_index_of_mem(bstr_ptr(haystack), bstr_len(haystack), _data2, len2); |
308 | 0 | } |
309 | | |
310 | 91 | int bstr_index_of_mem_nocase(const bstr *haystack, const void *_data2, size_t len2) { |
311 | 91 | return bstr_util_mem_index_of_mem_nocase(bstr_ptr(haystack), bstr_len(haystack), _data2, len2); |
312 | 91 | } |
313 | | |
314 | 0 | int bstr_index_of_nocase(const bstr *haystack, const bstr *needle) { |
315 | 0 | return bstr_index_of_mem_nocase(haystack, bstr_ptr(needle), bstr_len(needle)); |
316 | 0 | } |
317 | | |
318 | 0 | int bstr_rchr(const bstr *b, int c) { |
319 | 0 | const unsigned char *data = bstr_ptr(b); |
320 | 0 | size_t len = bstr_len(b); |
321 | |
|
322 | 0 | size_t i = len; |
323 | 0 | while (i > 0) { |
324 | 0 | if (data[i - 1] == c) { |
325 | 0 | return (int) (i - 1); |
326 | 0 | } |
327 | | |
328 | 0 | i--; |
329 | 0 | } |
330 | | |
331 | 0 | return -1; |
332 | 0 | } |
333 | | |
334 | 34.4k | bstr *bstr_to_lowercase(bstr *b) { |
335 | 34.4k | if (b == NULL) return NULL; |
336 | | |
337 | 34.4k | unsigned char *data = bstr_ptr(b); |
338 | 34.4k | size_t len = bstr_len(b); |
339 | | |
340 | 34.4k | size_t i = 0; |
341 | 13.5M | while (i < len) { |
342 | 13.5M | data[i] = (uint8_t)tolower(data[i]); |
343 | 13.5M | i++; |
344 | 13.5M | } |
345 | | |
346 | 34.4k | return b; |
347 | 34.4k | } |
348 | | |
349 | 2.36M | int bstr_util_cmp_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
350 | 2.36M | const unsigned char *data1 = (const unsigned char *) _data1; |
351 | 2.36M | const unsigned char *data2 = (const unsigned char *) _data2; |
352 | 2.36M | size_t p1 = 0, p2 = 0; |
353 | | |
354 | 2.50M | while ((p1 < len1) && (p2 < len2)) { |
355 | 2.23M | if (data1[p1] != data2[p2]) { |
356 | | // Difference. |
357 | 2.09M | return (data1[p1] < data2[p2]) ? -1 : 1; |
358 | 2.09M | } |
359 | | |
360 | 133k | p1++; |
361 | 133k | p2++; |
362 | 133k | } |
363 | | |
364 | 270k | if ((p1 == len2) && (p2 == len1)) { |
365 | | // They're identical. |
366 | 20.7k | return 0; |
367 | 250k | } else { |
368 | | // One string is shorter. |
369 | 250k | if (p1 == len1) return -1; |
370 | 642 | else return 1; |
371 | 250k | } |
372 | 270k | } |
373 | | |
374 | 440k | int bstr_util_cmp_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
375 | 440k | const unsigned char *data1 = (const unsigned char *) _data1; |
376 | 440k | const unsigned char *data2 = (const unsigned char *) _data2; |
377 | 440k | size_t p1 = 0, p2 = 0; |
378 | | |
379 | 990k | while ((p1 < len1) && (p2 < len2)) { |
380 | 786k | if (tolower(data1[p1]) != tolower(data2[p2])) { |
381 | | // Difference. |
382 | 236k | return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; |
383 | 236k | } |
384 | | |
385 | 549k | p1++; |
386 | 549k | p2++; |
387 | 549k | } |
388 | | |
389 | 203k | if ((p1 == len2) && (p2 == len1)) { |
390 | | // They're identical. |
391 | 127k | return 0; |
392 | 127k | } else { |
393 | | // One string is shorter. |
394 | 76.6k | if (p1 == len1) return -1; |
395 | 21.4k | else return 1; |
396 | 76.6k | } |
397 | 203k | } |
398 | | |
399 | 342k | int bstr_util_cmp_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
400 | 342k | const unsigned char *data1 = (const unsigned char *) _data1; |
401 | 342k | const unsigned char *data2 = (const unsigned char *) _data2; |
402 | 342k | size_t p1 = 0, p2 = 0; |
403 | | |
404 | 1.03M | while ((p1 < len1) && (p2 < len2)) { |
405 | 934k | if (data1[p1] == 0) { |
406 | 6.79k | p1++; |
407 | 6.79k | continue; |
408 | 6.79k | } |
409 | 927k | if (tolower(data1[p1]) != tolower(data2[p2])) { |
410 | | // Difference. |
411 | 244k | return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; |
412 | 244k | } |
413 | | |
414 | 683k | p1++; |
415 | 683k | p2++; |
416 | 683k | } |
417 | | |
418 | 100k | while((p1 < len1) && (data1[p1] == 0)) { |
419 | 2.43k | p1++; |
420 | 2.43k | } |
421 | 97.9k | if ((p1 == len1) && (p2 == len2)) { |
422 | | // They're identical. |
423 | 43.2k | return 0; |
424 | 54.7k | } else { |
425 | | // One string is shorter. |
426 | 54.7k | if (p1 == len1) return -1; |
427 | 3.34k | else return 1; |
428 | 54.7k | } |
429 | 97.9k | } |
430 | | |
431 | 35.3k | int64_t bstr_util_mem_to_pint(const void *_data, size_t len, int base, size_t *lastlen) { |
432 | 35.3k | const unsigned char *data = (unsigned char *) _data; |
433 | 35.3k | int64_t rval = 0, tflag = 0; |
434 | 35.3k | size_t i = 0; |
435 | | |
436 | 35.3k | *lastlen = i; |
437 | | |
438 | 134k | for (i = 0; i < len; i++) { |
439 | 104k | int d = data[i]; |
440 | | |
441 | 104k | *lastlen = i; |
442 | | |
443 | | // Convert character to digit. |
444 | 104k | if ((d >= '0') && (d <= '9')) { |
445 | 99.3k | d -= '0'; |
446 | 99.3k | } else if ((d >= 'a') && (d <= 'z')) { |
447 | 763 | d -= 'a' - 10; |
448 | 3.92k | } else if ((d >= 'A') && (d <= 'Z')) { |
449 | 610 | d -= 'A' - 10; |
450 | 3.31k | } else { |
451 | 3.31k | d = -1; |
452 | 3.31k | } |
453 | | |
454 | | // Check that the digit makes sense with the base we are using. |
455 | 104k | if ((d == -1) || (d >= base)) { |
456 | 4.69k | if (tflag) { |
457 | | // Return what we have so far; lastlen points |
458 | | // to the first non-digit position. |
459 | 2.17k | return rval; |
460 | 2.51k | } else { |
461 | | // We didn't see a single digit. |
462 | 2.51k | return -1; |
463 | 2.51k | } |
464 | 4.69k | } |
465 | | |
466 | 99.3k | if (tflag) { |
467 | 66.5k | if (((INT64_MAX - d) / base) < rval) { |
468 | | // Overflow |
469 | 247 | return -2; |
470 | 247 | } |
471 | | |
472 | 66.2k | rval *= base; |
473 | 66.2k | rval += d; |
474 | 66.2k | } else { |
475 | 32.8k | rval = d; |
476 | 32.8k | tflag = 1; |
477 | 32.8k | } |
478 | 99.3k | } |
479 | | |
480 | 30.3k | *lastlen = i + 1; |
481 | | |
482 | 30.3k | return rval; |
483 | 35.3k | } |
484 | | |
485 | 0 | int bstr_util_mem_index_of_c(const void *_data1, size_t len1, const char *cstr) { |
486 | 0 | return bstr_util_mem_index_of_mem(_data1, len1, cstr, strlen(cstr)); |
487 | 0 | } |
488 | | |
489 | 15.9k | int bstr_util_mem_index_of_c_nocase(const void *_data1, size_t len1, const char *cstr) { |
490 | 15.9k | return bstr_util_mem_index_of_mem_nocase(_data1, len1, cstr, strlen(cstr)); |
491 | 15.9k | } |
492 | | |
493 | 0 | int bstr_util_mem_index_of_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
494 | 0 | const unsigned char *data1 = (unsigned char *) _data1; |
495 | 0 | const unsigned char *data2 = (unsigned char *) _data2; |
496 | 0 | size_t i, j; |
497 | | |
498 | | // If we ever want to optimize this function, the following link |
499 | | // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm |
500 | |
|
501 | 0 | for (i = 0; i < len1; i++) { |
502 | 0 | size_t k = i; |
503 | |
|
504 | 0 | for (j = 0; ((j < len2) && (k < len1)); j++, k++) { |
505 | 0 | if (data1[k] != data2[j]) break; |
506 | 0 | } |
507 | |
|
508 | 0 | if (j == len2) { |
509 | 0 | return (int) i; |
510 | 0 | } |
511 | 0 | } |
512 | | |
513 | 0 | return -1; |
514 | 0 | } |
515 | | |
516 | 16.0k | int bstr_util_mem_index_of_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
517 | 16.0k | const unsigned char *data1 = (unsigned char *) _data1; |
518 | 16.0k | const unsigned char *data2 = (unsigned char *) _data2; |
519 | 16.0k | size_t i, j; |
520 | | |
521 | | // If we ever want to optimize this function, the following link |
522 | | // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm |
523 | | |
524 | 12.4M | for (i = 0; i < len1; i++) { |
525 | 12.4M | size_t k = i; |
526 | | |
527 | 12.4M | for (j = 0; ((j < len2) && (k < len1)); j++, k++) { |
528 | 12.4M | if (toupper(data1[k]) != toupper(data2[j])) break; |
529 | 12.4M | } |
530 | | |
531 | 12.4M | if (j == len2) { |
532 | 5.05k | return (int) i; |
533 | 5.05k | } |
534 | 12.4M | } |
535 | | |
536 | 10.9k | return -1; |
537 | 16.0k | } |
538 | | |
539 | 0 | int bstr_util_mem_index_of_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
540 | 0 | const unsigned char *data1 = (unsigned char *) _data1; |
541 | 0 | const unsigned char *data2 = (unsigned char *) _data2; |
542 | 0 | size_t i, j; |
543 | | |
544 | | // If we ever want to optimize this function, the following link |
545 | | // might be useful: http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm |
546 | |
|
547 | 0 | for (i = 0; i < len1; i++) { |
548 | 0 | size_t k = i; |
549 | 0 | if (data1[i] == 0) { |
550 | | // skip leading zeroes to avoid quadratic complexity |
551 | 0 | continue; |
552 | 0 | } |
553 | | |
554 | 0 | for (j = 0; ((j < len2) && (k < len1)); j++, k++) { |
555 | 0 | if (data1[k] == 0) { |
556 | 0 | j--; |
557 | 0 | continue; |
558 | 0 | } |
559 | 0 | if (toupper(data1[k]) != toupper(data2[j])) break; |
560 | 0 | } |
561 | |
|
562 | 0 | if (j == len2) { |
563 | 0 | return (int) i; |
564 | 0 | } |
565 | 0 | } |
566 | | |
567 | 0 | return -1; |
568 | 0 | } |
569 | | |
570 | 10.9k | void bstr_util_mem_trim(unsigned char **data, size_t *len) { |
571 | 10.9k | if ((data == NULL)||(len == NULL)) return; |
572 | | |
573 | 10.9k | unsigned char *d = *data; |
574 | 10.9k | size_t l = *len; |
575 | | |
576 | | // Ignore whitespace at the beginning. |
577 | 10.9k | size_t pos = 0; |
578 | 11.3k | while ((pos < l) && isspace(d[pos])) pos++; |
579 | 10.9k | d += pos; |
580 | 10.9k | l -= pos; |
581 | | |
582 | | // Ignore whitespace at the end. |
583 | 11.1k | while ((l > 0)&&(isspace(d[l - 1]))) l--; |
584 | | |
585 | 10.9k | *data = d; |
586 | 10.9k | *len = l; |
587 | 10.9k | } |
588 | | |
589 | 8.52k | char *bstr_util_memdup_to_c(const void *_data, size_t len) { |
590 | 8.52k | const unsigned char *data = (unsigned char *) _data; |
591 | | |
592 | | // Count how many NUL bytes we have in the string. |
593 | 8.52k | size_t i, nulls = 0; |
594 | 5.21M | for (i = 0; i < len; i++) { |
595 | 5.20M | if (data[i] == '\0') { |
596 | 216k | nulls++; |
597 | 216k | } |
598 | 5.20M | } |
599 | | |
600 | | // Now copy the string into a NUL-terminated buffer. |
601 | | |
602 | 8.52k | char *r, *d; |
603 | 8.52k | r = d = malloc(len + nulls + 1); |
604 | 8.52k | if (d == NULL) return NULL; |
605 | | |
606 | 5.21M | while (len--) { |
607 | 5.20M | if (*data == '\0') { |
608 | 216k | data++; |
609 | 216k | *d++ = '\\'; |
610 | 216k | *d++ = '0'; |
611 | 4.99M | } else { |
612 | 4.99M | *d++ = *data++; |
613 | 4.99M | } |
614 | 5.20M | } |
615 | | |
616 | 8.52k | *d = '\0'; |
617 | | |
618 | 8.52k | return r; |
619 | 8.52k | } |
620 | | |
621 | 39.8k | char *bstr_util_strdup_to_c(const bstr *b) { |
622 | 39.8k | if (b == NULL) return NULL; |
623 | 8.52k | return bstr_util_memdup_to_c(bstr_ptr(b), bstr_len(b)); |
624 | 39.8k | } |
625 | | |
626 | 0 | bstr *bstr_wrap_c(const char *cstr) { |
627 | 0 | return bstr_wrap_mem((unsigned char *) cstr, strlen(cstr)); |
628 | 0 | } |
629 | | |
630 | 0 | bstr *bstr_wrap_mem(const void *data, size_t len) { |
631 | 0 | bstr *b = (bstr *) malloc(sizeof (bstr)); |
632 | 0 | if (b == NULL) return NULL; |
633 | | |
634 | 0 | b->size = b->len = len; |
635 | 0 | b->realptr = (unsigned char *) data; |
636 | |
|
637 | 0 | return b; |
638 | 0 | } |