Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/libhtp/htp/bstr.c
Line
Count
Source
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
6.74M
bstr *bstr_alloc(size_t len) {
44
6.74M
    bstr *b = malloc(sizeof (bstr) + len);
45
6.74M
    if (b == NULL) return NULL;
46
47
6.74M
    b->len = 0;
48
6.74M
    b->size = len;
49
6.74M
    b->realptr = NULL;
50
51
6.74M
    return b;
52
6.74M
}
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
17.4k
bstr *bstr_add_c_noex(bstr *destination, const char *source) {
63
17.4k
    return bstr_add_mem_noex(destination, source, strlen(source));
64
17.4k
}
65
66
298k
bstr *bstr_add_mem(bstr *destination, const void *data, size_t len) {
67
    // Expand the destination if necessary
68
298k
    if (bstr_size(destination) < bstr_len(destination) + len) {
69
288k
        destination = bstr_expand(destination, bstr_len(destination) + len);
70
288k
        if (destination == NULL) return NULL;
71
288k
    }
72
73
    // Add source to destination
74
298k
    bstr *b = (bstr *) destination;
75
298k
    memcpy(bstr_ptr(destination) + bstr_len(b), data, len);
76
298k
    bstr_adjust_len(b, bstr_len(b) + len);
77
78
298k
    return destination;
79
298k
}
80
81
1.06M
bstr *bstr_add_mem_noex(bstr *destination, const void *data, size_t len) {
82
1.06M
    size_t copylen = len;
83
84
    // Is there enough room in the destination?
85
1.06M
    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
1.06M
    bstr *b = (bstr *) destination;
92
1.06M
    memcpy(bstr_ptr(destination) + bstr_len(b), data, copylen);
93
1.06M
    bstr_adjust_len(b, bstr_len(b) + copylen);
94
95
1.06M
    return destination;
96
1.06M
}
97
98
609k
bstr *bstr_add_noex(bstr *destination, const bstr *source) {
99
609k
    return bstr_add_mem_noex(destination, bstr_ptr(source), bstr_len(source));
100
609k
}
101
102
8.26M
void bstr_adjust_len(bstr *b, size_t newlen) {
103
8.26M
    b->len = newlen;
104
8.26M
}
105
106
0
void bstr_adjust_realptr(bstr *b, void *newrealptr) {
107
0
    b->realptr = newrealptr;
108
0
}
109
110
730k
void bstr_adjust_size(bstr *b, size_t newsize) {
111
730k
    b->size = newsize;
112
730k
}
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
4.07k
int bstr_begins_with_c_nocase(const bstr *haystack, const char *needle) {
123
4.07k
    return bstr_begins_with_mem_nocase(haystack, needle, strlen(needle));
124
4.07k
}
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
4.07k
int bstr_begins_with_mem_nocase(const bstr *haystack, const void *_data, size_t len) {
152
4.07k
    const unsigned char *data = (const unsigned char *) _data;
153
4.07k
    const unsigned char *hdata = bstr_ptr(haystack);
154
4.07k
    size_t hlen = bstr_len(haystack);
155
4.07k
    size_t pos = 0;
156
157
19.1k
    while ((pos < len) && (pos < hlen)) {
158
16.4k
        if (tolower((int) hdata[pos]) != tolower((int) data[pos])) {
159
1.32k
            return 0;
160
1.32k
        }
161
162
15.0k
        pos++;
163
15.0k
    }
164
165
2.75k
    if (pos == len) {
166
2.75k
        return 1;
167
2.75k
    } else {
168
0
        return 0;
169
0
    }
170
2.75k
}
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
31.7k
int bstr_char_at_end(const bstr *b, size_t pos) {
181
31.7k
    unsigned char *data = bstr_ptr(b);
182
31.7k
    size_t len = bstr_len(b);
183
184
31.7k
    if (pos >= len) return -1;
185
27.9k
    return data[len - 1 - pos];
186
31.7k
}
187
188
2.58k
void bstr_chop(bstr *b) {
189
2.58k
    if (bstr_len(b) > 0) {
190
2.58k
        bstr_adjust_len(b, bstr_len(b) - 1);
191
2.58k
    }
192
2.58k
}
193
194
16.8k
int bstr_chr(const bstr *b, int c) {
195
16.8k
    unsigned char *data = bstr_ptr(b);
196
16.8k
    size_t len = bstr_len(b);
197
198
16.8k
    size_t i = 0;
199
2.04M
    while (i < len) {
200
2.03M
        if (data[i] == c) {
201
8.06k
            return (int) i;
202
8.06k
        }
203
204
2.03M
        i++;
205
2.03M
    }
206
207
8.77k
    return -1;
208
16.8k
}
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
31.4M
int bstr_cmp_c(const bstr *b, const char *c) {
215
31.4M
    return bstr_util_cmp_mem(bstr_ptr(b), bstr_len(b), c, strlen(c));
216
31.4M
}
217
218
483k
int bstr_cmp_c_nocase(const bstr *b, const char *c) {
219
483k
    return bstr_util_cmp_mem_nocase(bstr_ptr(b), bstr_len(b), c, strlen(c));
220
483k
}
221
222
9.32M
int bstr_cmp_c_nocasenorzero(const bstr *b, const char *c) {
223
9.32M
    return bstr_util_cmp_mem_nocasenorzero(bstr_ptr(b), bstr_len(b), c, strlen(c));
224
9.32M
}
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
3.66M
int bstr_cmp_nocase(const bstr *b1, const bstr *b2) {
235
3.66M
    return bstr_util_cmp_mem_nocase(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2));
236
3.66M
}
237
238
990k
bstr *bstr_dup(const bstr *b) {
239
990k
    return bstr_dup_ex(b, 0, bstr_len(b));
240
990k
}
241
242
560k
bstr *bstr_dup_c(const char *cstr) {
243
560k
    return bstr_dup_mem(cstr, strlen(cstr));
244
560k
}
245
246
1.00M
bstr *bstr_dup_ex(const bstr *b, size_t offset, size_t len) {
247
1.00M
    bstr *bnew = bstr_alloc(len);
248
1.00M
    if (bnew == NULL) return NULL;
249
1.00M
    memcpy(bstr_ptr(bnew), bstr_ptr(b) + offset, len);
250
1.00M
    bstr_adjust_len(bnew, len);
251
1.00M
    return bnew;
252
1.00M
}
253
254
52.9k
bstr *bstr_dup_lower(const bstr *b) {
255
52.9k
    return bstr_to_lowercase(bstr_dup(b));
256
52.9k
}
257
258
5.52M
bstr *bstr_dup_mem(const void *data, size_t len) {
259
5.52M
    bstr *bnew = bstr_alloc(len);
260
5.52M
    if (bnew == NULL) return NULL;
261
5.52M
    memcpy(bstr_ptr(bnew), data, len);
262
5.52M
    bstr_adjust_len(bnew, len);
263
5.52M
    return bnew;
264
5.52M
}
265
266
730k
bstr *bstr_expand(bstr *b, size_t newsize) {
267
730k
    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
730k
    if (bstr_size(b) > newsize) return NULL;
276
277
730k
    bstr *bnew = realloc(b, sizeof (bstr) + newsize);
278
730k
    if (bnew == NULL) return NULL;
279
280
730k
    bstr_adjust_size(bnew, newsize);
281
282
730k
    return bnew;
283
730k
}
284
285
13.7M
void bstr_free(bstr *b) {
286
13.7M
    if (b == NULL) return;
287
6.74M
    free(b);
288
6.74M
}
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
2.49k
int bstr_index_of_c(const bstr *haystack, const char *needle) {
295
2.49k
    return bstr_index_of_mem(haystack, needle, strlen(needle));
296
2.49k
}
297
298
532
int bstr_index_of_c_nocase(const bstr *haystack, const char *needle) {
299
532
    return bstr_index_of_mem_nocase(haystack, needle, strlen(needle));
300
532
}
301
302
12.0k
int bstr_index_of_c_nocasenorzero(const bstr *haystack, const char *needle) {
303
12.0k
    return bstr_util_mem_index_of_mem_nocasenorzero(bstr_ptr(haystack), bstr_len(haystack), needle, strlen(needle));
304
12.0k
}
305
306
2.49k
int bstr_index_of_mem(const bstr *haystack, const void *_data2, size_t len2) {
307
2.49k
    return bstr_util_mem_index_of_mem(bstr_ptr(haystack), bstr_len(haystack), _data2, len2);
308
2.49k
}
309
310
532
int bstr_index_of_mem_nocase(const bstr *haystack, const void *_data2, size_t len2) {
311
532
    return bstr_util_mem_index_of_mem_nocase(bstr_ptr(haystack), bstr_len(haystack), _data2, len2);
312
532
}
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
117k
bstr *bstr_to_lowercase(bstr *b) {
335
117k
    if (b == NULL) return NULL;
336
337
117k
    unsigned char *data = bstr_ptr(b);
338
117k
    size_t len = bstr_len(b);
339
340
117k
    size_t i = 0;
341
3.70M
    while (i < len) {
342
3.58M
        data[i] = (uint8_t)tolower(data[i]);
343
3.58M
        i++;
344
3.58M
    }
345
346
117k
    return b;
347
117k
}
348
349
31.5M
int bstr_util_cmp_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) {
350
31.5M
    const unsigned char *data1 = (const unsigned char *) _data1;
351
31.5M
    const unsigned char *data2 = (const unsigned char *) _data2;
352
31.5M
    size_t p1 = 0, p2 = 0;
353
354
32.2M
    while ((p1 < len1) && (p2 < len2)) {
355
31.8M
        if (data1[p1] != data2[p2]) {
356
            // Difference.
357
31.1M
            return (data1[p1] < data2[p2]) ? -1 : 1;
358
31.1M
        }
359
360
736k
        p1++;
361
736k
        p2++;
362
736k
    }
363
364
352k
    if ((p1 == len2) && (p2 == len1)) {
365
        // They're identical.
366
83.9k
        return 0;
367
268k
    } else {
368
        // One string is shorter.
369
268k
        if (p1 == len1) return -1;
370
2.87k
        else return 1;
371
268k
    }
372
352k
}
373
374
4.14M
int bstr_util_cmp_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) {
375
4.14M
    const unsigned char *data1 = (const unsigned char *) _data1;
376
4.14M
    const unsigned char *data2 = (const unsigned char *) _data2;
377
4.14M
    size_t p1 = 0, p2 = 0;
378
379
9.91M
    while ((p1 < len1) && (p2 < len2)) {
380
7.82M
        if (tolower(data1[p1]) != tolower(data2[p2])) {
381
            // Difference.
382
2.04M
            return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1;
383
2.04M
        }
384
385
5.77M
        p1++;
386
5.77M
        p2++;
387
5.77M
    }
388
389
2.09M
    if ((p1 == len2) && (p2 == len1)) {
390
        // They're identical.
391
799k
        return 0;
392
1.29M
    } else {
393
        // One string is shorter.
394
1.29M
        if (p1 == len1) return -1;
395
575k
        else return 1;
396
1.29M
    }
397
2.09M
}
398
399
9.32M
int bstr_util_cmp_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) {
400
9.32M
    const unsigned char *data1 = (const unsigned char *) _data1;
401
9.32M
    const unsigned char *data2 = (const unsigned char *) _data2;
402
9.32M
    size_t p1 = 0, p2 = 0;
403
404
19.0M
    while ((p1 < len1) && (p2 < len2)) {
405
16.5M
        if (data1[p1] == 0) {
406
333k
            p1++;
407
333k
            continue;
408
333k
        }
409
16.2M
        if (tolower(data1[p1]) != tolower(data2[p2])) {
410
            // Difference.
411
6.90M
            return (tolower(data1[p1]) < tolower(data2[p2])) ? -1 : 1;
412
6.90M
        }
413
414
9.34M
        p1++;
415
9.34M
        p2++;
416
9.34M
    }
417
418
2.43M
    while((p1 < len1) && (data1[p1] == 0)) {
419
16.9k
        p1++;
420
16.9k
    }
421
2.41M
    if ((p1 == len1) && (p2 == len2)) {
422
        // They're identical.
423
340k
        return 0;
424
2.07M
    } else {
425
        // One string is shorter.
426
2.07M
        if (p1 == len1) return -1;
427
6.26k
        else return 1;
428
2.07M
    }
429
2.41M
}
430
431
248k
int64_t bstr_util_mem_to_pint(const void *_data, size_t len, int base, size_t *lastlen) {
432
248k
    const unsigned char *data = (unsigned char *) _data;
433
248k
    int64_t rval = 0, tflag = 0;
434
248k
    size_t i = 0;
435
436
248k
    *lastlen = i;
437
438
715k
    for (i = 0; i < len; i++) {
439
508k
        int d = data[i];
440
441
508k
        *lastlen = i;
442
443
        // Convert character to digit.
444
508k
        if ((d >= '0') && (d <= '9')) {
445
447k
            d -= '0';
446
447k
        } else if ((d >= 'a') && (d <= 'z')) {
447
13.8k
            d -= 'a' - 10;
448
47.2k
        } else if ((d >= 'A') && (d <= 'Z')) {
449
26.0k
            d -= 'A' - 10;
450
26.0k
        } else {
451
21.1k
            d = -1;
452
21.1k
        }
453
454
        // Check that the digit makes sense with the base we are using.
455
508k
        if ((d == -1) || (d >= base)) {
456
40.5k
            if (tflag) {
457
                // Return what we have so far; lastlen points
458
                // to the first non-digit position.
459
15.7k
                return rval;
460
24.7k
            } else {
461
                // We didn't see a single digit.
462
24.7k
                return -1;
463
24.7k
            }
464
40.5k
        }
465
466
468k
        if (tflag) {
467
244k
            if (((INT64_MAX - d) / base) < rval) {
468
                // Overflow
469
418
                return -2;
470
418
            }
471
472
244k
            rval *= base;
473
244k
            rval += d;
474
244k
        } else {
475
223k
            rval = d;
476
223k
            tflag = 1;
477
223k
        }
478
468k
    }
479
480
207k
    *lastlen = i + 1;
481
482
207k
    return rval;
483
248k
}
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
37.0k
int bstr_util_mem_index_of_c_nocase(const void *_data1, size_t len1, const char *cstr) {
490
37.0k
    return bstr_util_mem_index_of_mem_nocase(_data1, len1, cstr, strlen(cstr));
491
37.0k
}
492
493
2.49k
int bstr_util_mem_index_of_mem(const void *_data1, size_t len1, const void *_data2, size_t len2) {
494
2.49k
    const unsigned char *data1 = (unsigned char *) _data1;
495
2.49k
    const unsigned char *data2 = (unsigned char *) _data2;
496
2.49k
    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
307k
    for (i = 0; i < len1; i++) {
502
306k
        size_t k = i;
503
504
313k
        for (j = 0; ((j < len2) && (k < len1)); j++, k++) {
505
312k
            if (data1[k] != data2[j]) break;
506
312k
        }
507
508
306k
        if (j == len2) {
509
1.29k
            return (int) i;
510
1.29k
        }
511
306k
    }
512
513
1.19k
    return -1;
514
2.49k
}
515
516
37.5k
int bstr_util_mem_index_of_mem_nocase(const void *_data1, size_t len1, const void *_data2, size_t len2) {
517
37.5k
    const unsigned char *data1 = (unsigned char *) _data1;
518
37.5k
    const unsigned char *data2 = (unsigned char *) _data2;
519
37.5k
    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
891k
    for (i = 0; i < len1; i++) {
525
868k
        size_t k = i;
526
527
954k
        for (j = 0; ((j < len2) && (k < len1)); j++, k++) {
528
939k
            if (toupper(data1[k]) != toupper(data2[j])) break;
529
939k
        }
530
531
868k
        if (j == len2) {
532
14.7k
            return (int) i;
533
14.7k
        }
534
868k
    }
535
536
22.7k
    return -1;
537
37.5k
}
538
539
12.0k
int bstr_util_mem_index_of_mem_nocasenorzero(const void *_data1, size_t len1, const void *_data2, size_t len2) {
540
12.0k
    const unsigned char *data1 = (unsigned char *) _data1;
541
12.0k
    const unsigned char *data2 = (unsigned char *) _data2;
542
12.0k
    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
992k
    for (i = 0; i < len1; i++) {
548
991k
        size_t k = i;
549
991k
        if (data1[i] == 0) {
550
            // skip leading zeroes to avoid quadratic complexity
551
105k
            continue;
552
105k
        }
553
554
996k
        for (j = 0; ((j < len2) && (k < len1)); j++, k++) {
555
984k
            if (data1[k] == 0) {
556
21.6k
                j--;
557
21.6k
                continue;
558
21.6k
            }
559
963k
            if (toupper(data1[k]) != toupper(data2[j])) break;
560
963k
        }
561
562
885k
        if (j == len2) {
563
11.7k
            return (int) i;
564
11.7k
        }
565
885k
    }
566
567
289
    return -1;
568
12.0k
}
569
570
51.8k
void bstr_util_mem_trim(unsigned char **data, size_t *len) {
571
51.8k
    if ((data == NULL)||(len == NULL)) return;
572
573
51.8k
    unsigned char *d = *data;
574
51.8k
    size_t l = *len;
575
576
    // Ignore whitespace at the beginning.
577
51.8k
    size_t pos = 0;
578
52.9k
    while ((pos < l) && isspace(d[pos])) pos++;
579
51.8k
    d += pos;
580
51.8k
    l -= pos;
581
582
    // Ignore whitespace at the end.
583
53.6k
    while ((l > 0)&&(isspace(d[l - 1]))) l--;
584
585
51.8k
    *data = d;
586
51.8k
    *len = l;
587
51.8k
}
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
}