/src/suricata7/libhtp/htp/bstr.c
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 | 4.71M | bstr *bstr_alloc(size_t len) { |
44 | 4.71M | bstr *b = malloc(sizeof (bstr) + len); |
45 | 4.71M | if (b == NULL) return NULL; |
46 | | |
47 | 4.71M | b->len = 0; |
48 | 4.71M | b->size = len; |
49 | 4.71M | b->realptr = NULL; |
50 | | |
51 | 4.71M | return b; |
52 | 4.71M | } |
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 | 12.7k | bstr *bstr_add_c_noex(bstr *destination, const char *source) { |
63 | 12.7k | return bstr_add_mem_noex(destination, source, strlen(source)); |
64 | 12.7k | } |
65 | | |
66 | 314k | bstr *bstr_add_mem(bstr *destination, const void *data, size_t len) { |
67 | | // Expand the destination if necessary |
68 | 314k | if (bstr_size(destination) < bstr_len(destination) + len) { |
69 | 305k | destination = bstr_expand(destination, bstr_len(destination) + len); |
70 | 305k | if (destination == NULL) return NULL; |
71 | 305k | } |
72 | | |
73 | | // Add source to destination |
74 | 314k | bstr *b = (bstr *) destination; |
75 | 314k | memcpy(bstr_ptr(destination) + bstr_len(b), data, len); |
76 | 314k | bstr_adjust_len(b, bstr_len(b) + len); |
77 | | |
78 | 314k | return destination; |
79 | 314k | } |
80 | | |
81 | 757k | bstr *bstr_add_mem_noex(bstr *destination, const void *data, size_t len) { |
82 | 757k | size_t copylen = len; |
83 | | |
84 | | // Is there enough room in the destination? |
85 | 757k | 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 | 757k | bstr *b = (bstr *) destination; |
92 | 757k | memcpy(bstr_ptr(destination) + bstr_len(b), data, copylen); |
93 | 757k | bstr_adjust_len(b, bstr_len(b) + copylen); |
94 | | |
95 | 757k | return destination; |
96 | 757k | } |
97 | | |
98 | 436k | bstr *bstr_add_noex(bstr *destination, const bstr *source) { |
99 | 436k | return bstr_add_mem_noex(destination, bstr_ptr(source), bstr_len(source)); |
100 | 436k | } |
101 | | |
102 | 5.88M | void bstr_adjust_len(bstr *b, size_t newlen) { |
103 | 5.88M | b->len = newlen; |
104 | 5.88M | } |
105 | | |
106 | 0 | void bstr_adjust_realptr(bstr *b, void *newrealptr) { |
107 | 0 | b->realptr = newrealptr; |
108 | 0 | } |
109 | | |
110 | 614k | void bstr_adjust_size(bstr *b, size_t newsize) { |
111 | 614k | b->size = newsize; |
112 | 614k | } |
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 | 3 | int bstr_begins_with_c_nocase(const bstr *haystack, const char *needle) { |
123 | 3 | return bstr_begins_with_mem_nocase(haystack, needle, strlen(needle)); |
124 | 3 | } |
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 | 3 | int bstr_begins_with_mem_nocase(const bstr *haystack, const void *_data, size_t len) { |
152 | 3 | const unsigned char *data = (const unsigned char *) _data; |
153 | 3 | const unsigned char *hdata = bstr_ptr(haystack); |
154 | 3 | size_t hlen = bstr_len(haystack); |
155 | 3 | size_t pos = 0; |
156 | | |
157 | 10 | while ((pos < len) && (pos < hlen)) { |
158 | 9 | if (tolower((int) hdata[pos]) != tolower((int) data[pos])) { |
159 | 2 | return 0; |
160 | 2 | } |
161 | | |
162 | 7 | pos++; |
163 | 7 | } |
164 | | |
165 | 1 | if (pos == len) { |
166 | 1 | return 1; |
167 | 1 | } else { |
168 | 0 | return 0; |
169 | 0 | } |
170 | 1 | } |
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 | 33.5k | int bstr_char_at_end(const bstr *b, size_t pos) { |
181 | 33.5k | unsigned char *data = bstr_ptr(b); |
182 | 33.5k | size_t len = bstr_len(b); |
183 | | |
184 | 33.5k | if (pos >= len) return -1; |
185 | 30.8k | return data[len - 1 - pos]; |
186 | 33.5k | } |
187 | | |
188 | 6.14k | void bstr_chop(bstr *b) { |
189 | 6.14k | if (bstr_len(b) > 0) { |
190 | 6.14k | bstr_adjust_len(b, bstr_len(b) - 1); |
191 | 6.14k | } |
192 | 6.14k | } |
193 | | |
194 | 13.1k | int bstr_chr(const bstr *b, int c) { |
195 | 13.1k | unsigned char *data = bstr_ptr(b); |
196 | 13.1k | size_t len = bstr_len(b); |
197 | | |
198 | 13.1k | size_t i = 0; |
199 | 3.88M | while (i < len) { |
200 | 3.88M | if (data[i] == c) { |
201 | 7.39k | return (int) i; |
202 | 7.39k | } |
203 | | |
204 | 3.87M | i++; |
205 | 3.87M | } |
206 | | |
207 | 5.74k | return -1; |
208 | 13.1k | } |
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 | 21.4M | int bstr_cmp_c(const bstr *b, const char *c) { |
215 | 21.4M | return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
216 | 21.4M | } |
217 | | |
218 | 362k | int bstr_cmp_c_nocase(const bstr *b, const char *c) { |
219 | 362k | return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
220 | 362k | } |
221 | | |
222 | 3.89M | int bstr_cmp_c_nocasenorzero(const bstr *b, const char *c) { |
223 | 3.89M | return bstr_util_cmp_mem_nocasenorzero(bstr_ptr(b), bstr_len(b), c, strlen(c)); |
224 | 3.89M | } |
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 | 1.88M | int bstr_cmp_nocase(const bstr *b1, const bstr *b2) { |
235 | 1.88M | return bstr_util_cmp_mem_nocase(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2)); |
236 | 1.88M | } |
237 | | |
238 | 598k | bstr *bstr_dup(const bstr *b) { |
239 | 598k | return bstr_dup_ex(b, 0, bstr_len(b)); |
240 | 598k | } |
241 | | |
242 | 421k | bstr *bstr_dup_c(const char *cstr) { |
243 | 421k | return bstr_dup_mem(cstr, strlen(cstr)); |
244 | 421k | } |
245 | | |
246 | 607k | bstr *bstr_dup_ex(const bstr *b, size_t offset, size_t len) { |
247 | 607k | bstr *bnew = bstr_alloc(len); |
248 | 607k | if (bnew == NULL) return NULL; |
249 | 607k | memcpy(bstr_ptr(bnew), bstr_ptr(b) + offset, len); |
250 | 607k | bstr_adjust_len(bnew, len); |
251 | 607k | return bnew; |
252 | 607k | } |
253 | | |
254 | 44.7k | bstr *bstr_dup_lower(const bstr *b) { |
255 | 44.7k | return bstr_to_lowercase(bstr_dup(b)); |
256 | 44.7k | } |
257 | | |
258 | 3.91M | bstr *bstr_dup_mem(const void *data, size_t len) { |
259 | 3.91M | bstr *bnew = bstr_alloc(len); |
260 | 3.91M | if (bnew == NULL) return NULL; |
261 | 3.91M | memcpy(bstr_ptr(bnew), data, len); |
262 | 3.91M | bstr_adjust_len(bnew, len); |
263 | 3.91M | return bnew; |
264 | 3.91M | } |
265 | | |
266 | 614k | bstr *bstr_expand(bstr *b, size_t newsize) { |
267 | 614k | 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 | 614k | if (bstr_size(b) > newsize) return NULL; |
276 | | |
277 | 614k | bstr *bnew = realloc(b, sizeof (bstr) + newsize); |
278 | 614k | if (bnew == NULL) return NULL; |
279 | | |
280 | 614k | bstr_adjust_size(bnew, newsize); |
281 | | |
282 | 614k | return bnew; |
283 | 614k | } |
284 | | |
285 | 10.5M | void bstr_free(bstr *b) { |
286 | 10.5M | if (b == NULL) return; |
287 | 4.71M | free(b); |
288 | 4.71M | } |
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 | 261 | int bstr_index_of_c_nocase(const bstr *haystack, const char *needle) { |
299 | 261 | return bstr_index_of_mem_nocase(haystack, needle, strlen(needle)); |
300 | 261 | } |
301 | | |
302 | 10.1k | int bstr_index_of_c_nocasenorzero(const bstr *haystack, const char *needle) { |
303 | 10.1k | return bstr_util_mem_index_of_mem_nocasenorzero(bstr_ptr(haystack), bstr_len(haystack), needle, strlen(needle)); |
304 | 10.1k | } |
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 | 261 | int bstr_index_of_mem_nocase(const bstr *haystack, const void *_data2, size_t len2) { |
311 | 261 | return bstr_util_mem_index_of_mem_nocase(bstr_ptr(haystack), bstr_len(haystack), _data2, len2); |
312 | 261 | } |
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 | 88.5k | bstr *bstr_to_lowercase(bstr *b) { |
335 | 88.5k | if (b == NULL) return NULL; |
336 | | |
337 | 88.5k | unsigned char *data = bstr_ptr(b); |
338 | 88.5k | size_t len = bstr_len(b); |
339 | | |
340 | 88.5k | size_t i = 0; |
341 | 4.32M | while (i < len) { |
342 | 4.23M | data[i] = (uint8_t)tolower(data[i]); |
343 | 4.23M | i++; |
344 | 4.23M | } |
345 | | |
346 | 88.5k | return b; |
347 | 88.5k | } |
348 | | |
349 | 21.5M | int bstr_util_cmp_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
350 | 21.5M | const unsigned char *data1 = (const unsigned char *) _data1; |
351 | 21.5M | const unsigned char *data2 = (const unsigned char *) _data2; |
352 | 21.5M | size_t p1 = 0, p2 = 0; |
353 | | |
354 | 22.0M | while ((p1 < len1) && (p2 < len2)) { |
355 | 21.6M | if (data1[p1] != data2[p2]) { |
356 | | // Difference. |
357 | 21.1M | return (data1[p1] < data2[p2]) ? -1 : 1; |
358 | 21.1M | } |
359 | | |
360 | 517k | p1++; |
361 | 517k | p2++; |
362 | 517k | } |
363 | | |
364 | 410k | if ((p1 == len2) && (p2 == len1)) { |
365 | | // They're identical. |
366 | 55.1k | return 0; |
367 | 355k | } else { |
368 | | // One string is shorter. |
369 | 355k | if (p1 == len1) return -1; |
370 | 2.16k | else return 1; |
371 | 355k | } |
372 | 410k | } |
373 | | |
374 | 2.25M | int bstr_util_cmp_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
375 | 2.25M | const unsigned char *data1 = (const unsigned char *) _data1; |
376 | 2.25M | const unsigned char *data2 = (const unsigned char *) _data2; |
377 | 2.25M | size_t p1 = 0, p2 = 0; |
378 | | |
379 | 6.87M | while ((p1 < len1) && (p2 < len2)) { |
380 | 5.44M | if (tolower(data1[p1]) != tolower(data2[p2])) { |
381 | | // Difference. |
382 | 822k | return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; |
383 | 822k | } |
384 | | |
385 | 4.62M | p1++; |
386 | 4.62M | p2++; |
387 | 4.62M | } |
388 | | |
389 | 1.42M | if ((p1 == len2) && (p2 == len1)) { |
390 | | // They're identical. |
391 | 677k | return 0; |
392 | 750k | } else { |
393 | | // One string is shorter. |
394 | 750k | if (p1 == len1) return -1; |
395 | 258k | else return 1; |
396 | 750k | } |
397 | 1.42M | } |
398 | | |
399 | 3.89M | int bstr_util_cmp_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
400 | 3.89M | const unsigned char *data1 = (const unsigned char *) _data1; |
401 | 3.89M | const unsigned char *data2 = (const unsigned char *) _data2; |
402 | 3.89M | size_t p1 = 0, p2 = 0; |
403 | | |
404 | 9.09M | while ((p1 < len1) && (p2 < len2)) { |
405 | 7.84M | if (data1[p1] == 0) { |
406 | 365k | p1++; |
407 | 365k | continue; |
408 | 365k | } |
409 | 7.48M | if (tolower(data1[p1]) != tolower(data2[p2])) { |
410 | | // Difference. |
411 | 2.64M | return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1; |
412 | 2.64M | } |
413 | | |
414 | 4.83M | p1++; |
415 | 4.83M | p2++; |
416 | 4.83M | } |
417 | | |
418 | 1.26M | while((p1 < len1) && (data1[p1] == 0)) { |
419 | 23.5k | p1++; |
420 | 23.5k | } |
421 | 1.24M | if ((p1 == len1) && (p2 == len2)) { |
422 | | // They're identical. |
423 | 133k | return 0; |
424 | 1.11M | } else { |
425 | | // One string is shorter. |
426 | 1.11M | if (p1 == len1) return -1; |
427 | 4.41k | else return 1; |
428 | 1.11M | } |
429 | 1.24M | } |
430 | | |
431 | 228k | int64_t bstr_util_mem_to_pint(const void *_data, size_t len, int base, size_t *lastlen) { |
432 | 228k | const unsigned char *data = (unsigned char *) _data; |
433 | 228k | int64_t rval = 0, tflag = 0; |
434 | 228k | size_t i = 0; |
435 | | |
436 | 228k | *lastlen = i; |
437 | | |
438 | 614k | for (i = 0; i < len; i++) { |
439 | 421k | int d = data[i]; |
440 | | |
441 | 421k | *lastlen = i; |
442 | | |
443 | | // Convert character to digit. |
444 | 421k | if ((d >= '0') && (d <= '9')) { |
445 | 369k | d -= '0'; |
446 | 369k | } else if ((d >= 'a') && (d <= 'z')) { |
447 | 13.6k | d -= 'a' - 10; |
448 | 37.8k | } else if ((d >= 'A') && (d <= 'Z')) { |
449 | 14.2k | d -= 'A' - 10; |
450 | 23.6k | } else { |
451 | 23.6k | d = -1; |
452 | 23.6k | } |
453 | | |
454 | | // Check that the digit makes sense with the base we are using. |
455 | 421k | if ((d == -1) || (d >= base)) { |
456 | 34.2k | if (tflag) { |
457 | | // Return what we have so far; lastlen points |
458 | | // to the first non-digit position. |
459 | 17.0k | return rval; |
460 | 17.2k | } else { |
461 | | // We didn't see a single digit. |
462 | 17.2k | return -1; |
463 | 17.2k | } |
464 | 34.2k | } |
465 | | |
466 | 387k | if (tflag) { |
467 | 176k | if (((INT64_MAX - d) / base) < rval) { |
468 | | // Overflow |
469 | 585 | return -2; |
470 | 585 | } |
471 | | |
472 | 175k | rval *= base; |
473 | 175k | rval += d; |
474 | 211k | } else { |
475 | 211k | rval = d; |
476 | 211k | tflag = 1; |
477 | 211k | } |
478 | 387k | } |
479 | | |
480 | 193k | *lastlen = i + 1; |
481 | | |
482 | 193k | return rval; |
483 | 228k | } |
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 | 44.1k | int bstr_util_mem_index_of_c_nocase(const void *_data1, size_t len1, const char *cstr) { |
490 | 44.1k | return bstr_util_mem_index_of_mem_nocase(_data1, len1, cstr, strlen(cstr)); |
491 | 44.1k | } |
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 | 44.4k | int bstr_util_mem_index_of_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
517 | 44.4k | const unsigned char *data1 = (unsigned char *) _data1; |
518 | 44.4k | const unsigned char *data2 = (unsigned char *) _data2; |
519 | 44.4k | 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 | 1.57M | for (i = 0; i < len1; i++) { |
525 | 1.54M | size_t k = i; |
526 | | |
527 | 1.64M | for (j = 0; ((j < len2) && (k < len1)); j++, k++) { |
528 | 1.63M | if (toupper(data1[k]) != toupper(data2[j])) break; |
529 | 1.63M | } |
530 | | |
531 | 1.54M | if (j == len2) { |
532 | 14.8k | return (int) i; |
533 | 14.8k | } |
534 | 1.54M | } |
535 | | |
536 | 29.5k | return -1; |
537 | 44.4k | } |
538 | | |
539 | 10.1k | int bstr_util_mem_index_of_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) { |
540 | 10.1k | const unsigned char *data1 = (unsigned char *) _data1; |
541 | 10.1k | const unsigned char *data2 = (unsigned char *) _data2; |
542 | 10.1k | 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 | 192k | for (i = 0; i < len1; i++) { |
548 | 192k | size_t k = i; |
549 | 192k | if (data1[i] == 0) { |
550 | | // skip leading zeroes to avoid quadratic complexity |
551 | 19.8k | continue; |
552 | 19.8k | } |
553 | | |
554 | 265k | for (j = 0; ((j < len2) && (k < len1)); j++, k++) { |
555 | 255k | if (data1[k] == 0) { |
556 | 20.9k | j--; |
557 | 20.9k | continue; |
558 | 20.9k | } |
559 | 234k | if (toupper(data1[k]) != toupper(data2[j])) break; |
560 | 234k | } |
561 | | |
562 | 172k | if (j == len2) { |
563 | 9.85k | return (int) i; |
564 | 9.85k | } |
565 | 172k | } |
566 | | |
567 | 302 | return -1; |
568 | 10.1k | } |
569 | | |
570 | 20.7k | void bstr_util_mem_trim(unsigned char **data, size_t *len) { |
571 | 20.7k | if ((data == NULL)||(len == NULL)) return; |
572 | | |
573 | 20.7k | unsigned char *d = *data; |
574 | 20.7k | size_t l = *len; |
575 | | |
576 | | // Ignore whitespace at the beginning. |
577 | 20.7k | size_t pos = 0; |
578 | 22.0k | while ((pos < l) && isspace(d[pos])) pos++; |
579 | 20.7k | d += pos; |
580 | 20.7k | l -= pos; |
581 | | |
582 | | // Ignore whitespace at the end. |
583 | 21.5k | while ((l > 0)&&(isspace(d[l - 1]))) l--; |
584 | | |
585 | 20.7k | *data = d; |
586 | 20.7k | *len = l; |
587 | 20.7k | } |
588 | | |
589 | 0 | char *bstr_util_memdup_to_c(const void *_data, size_t len) { |
590 | 0 | const unsigned char *data = (unsigned char *) _data; |
591 | | |
592 | | // Count how many NUL bytes we have in the string. |
593 | 0 | size_t i, nulls = 0; |
594 | 0 | for (i = 0; i < len; i++) { |
595 | 0 | if (data[i] == '\0') { |
596 | 0 | nulls++; |
597 | 0 | } |
598 | 0 | } |
599 | | |
600 | | // Now copy the string into a NUL-terminated buffer. |
601 | |
|
602 | 0 | char *r, *d; |
603 | 0 | r = d = malloc(len + nulls + 1); |
604 | 0 | if (d == NULL) return NULL; |
605 | | |
606 | 0 | while (len--) { |
607 | 0 | if (*data == '\0') { |
608 | 0 | data++; |
609 | 0 | *d++ = '\\'; |
610 | 0 | *d++ = '0'; |
611 | 0 | } else { |
612 | 0 | *d++ = *data++; |
613 | 0 | } |
614 | 0 | } |
615 | |
|
616 | 0 | *d = '\0'; |
617 | |
|
618 | 0 | return r; |
619 | 0 | } |
620 | | |
621 | 0 | char *bstr_util_strdup_to_c(const bstr *b) { |
622 | 0 | if (b == NULL) return NULL; |
623 | 0 | return bstr_util_memdup_to_c(bstr_ptr(b), bstr_len(b)); |
624 | 0 | } |
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 | } |