Coverage Report

Created: 2026-06-15 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pjsip/pjlib/src/pj/string.c
Line
Count
Source
1
/* 
2
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
3
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program 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
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
 */
19
#include <pj/string.h>
20
#include <pj/assert.h>
21
#include <pj/pool.h>
22
#include <pj/ctype.h>
23
#include <pj/rand.h>
24
#include <pj/os.h>
25
#include <pj/errno.h>
26
#include <pj/limits.h>
27
28
#if PJ_FUNCTIONS_ARE_INLINED==0
29
#  include <pj/string_i.h>
30
#endif
31
32
33
PJ_DEF(pj_ssize_t) pj_strspn(const pj_str_t *str, const pj_str_t *set_char)
34
17.8k
{
35
17.8k
    pj_ssize_t i, j, count = 0;
36
70.8k
    for (i = 0; i < str->slen; i++) {
37
70.5k
        if (count != i)
38
17.6k
            break;
39
40
136k
        for (j = 0; j < set_char->slen; j++) {
41
83.8k
            if (str->ptr[i] == set_char->ptr[j])
42
35.1k
                count++;
43
83.8k
        }
44
52.9k
    }
45
17.8k
    return count;
46
17.8k
}
47
48
49
PJ_DEF(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char)
50
20.0k
{
51
20.0k
    pj_ssize_t i, j, count = 0;
52
73.6k
    for (i = 0; i < str->slen; i++) {
53
71.8k
        if (count != i)
54
18.2k
            break;
55
56
107k
        for (j = 0; set_char[j] != 0; j++) {
57
53.6k
            if (str->ptr[i] == set_char[j])
58
33.7k
                count++;
59
53.6k
        }
60
53.6k
    }
61
20.0k
    return count;
62
20.0k
}
63
64
65
PJ_DEF(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char)
66
17.7k
{
67
17.7k
    pj_ssize_t i, j;
68
519k
    for (i = 0; i < str->slen; i++) {
69
1.24M
        for (j = 0; j < set_char->slen; j++) {
70
746k
            if (str->ptr[i] == set_char->ptr[j])
71
13.6k
                return i;
72
746k
        }
73
515k
    }
74
4.11k
    return i;
75
17.7k
}
76
77
78
PJ_DEF(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char)
79
19.8k
{
80
19.8k
    pj_ssize_t i, j;
81
160k
    for (i = 0; i < str->slen; i++) {
82
297k
        for (j = 0; set_char[j] != 0; j++) {
83
157k
            if (str->ptr[i] == set_char[j])
84
17.4k
                return i;
85
157k
        }
86
157k
    }
87
2.44k
    return i;
88
19.8k
}
89
90
91
PJ_DEF(pj_ssize_t) pj_strtok(const pj_str_t *str, const pj_str_t *delim,
92
                             pj_str_t *tok, pj_size_t start_idx)
93
17.9k
{
94
17.9k
    pj_ssize_t str_idx;
95
96
17.9k
    pj_assert(str->slen >= 0);
97
17.9k
    pj_assert(delim->slen >= 0);
98
99
17.9k
    tok->slen = 0;
100
17.9k
    if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
101
5
        return str->slen;
102
5
    }
103
104
17.8k
    tok->ptr = str->ptr + start_idx;
105
17.8k
    tok->slen = str->slen - start_idx;
106
107
17.8k
    str_idx = pj_strspn(tok, delim);
108
17.8k
    if (start_idx+str_idx == (pj_size_t)str->slen) {
109
103
        return str->slen;
110
103
    }
111
17.7k
    tok->ptr += str_idx;
112
17.7k
    tok->slen -= str_idx;
113
114
17.7k
    tok->slen = pj_strcspn(tok, delim);
115
17.7k
    return start_idx + str_idx;
116
17.8k
}
117
118
119
PJ_DEF(pj_ssize_t) pj_strtok2(const pj_str_t *str, const char *delim,
120
                              pj_str_t *tok, pj_size_t start_idx)
121
20.0k
{
122
20.0k
    pj_ssize_t str_idx;
123
124
20.0k
    pj_assert(str->slen >= 0);
125
126
20.0k
    tok->slen = 0;
127
20.0k
    if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
128
2
        return str->slen;
129
2
    }
130
131
20.0k
    tok->ptr = str->ptr + start_idx;
132
20.0k
    tok->slen = str->slen - start_idx;
133
134
20.0k
    str_idx = pj_strspn2(tok, delim);
135
20.0k
    if (start_idx + str_idx == (pj_size_t)str->slen) {
136
152
        return str->slen;
137
152
    }
138
19.8k
    tok->ptr += str_idx;
139
19.8k
    tok->slen -= str_idx;
140
141
19.8k
    tok->slen = pj_strcspn2(tok, delim);
142
19.8k
    return start_idx + str_idx;
143
20.0k
}
144
145
146
PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr)
147
39.7k
{
148
39.7k
    const char *s, *ends;
149
39.7k
    int first;
150
151
39.7k
    PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
152
153
    /* Check if the string is empty */
154
39.7k
    if (str->slen <= 0)
155
79
        return NULL;
156
157
    /* Special case when substr is empty */
158
39.6k
    if (substr->slen <= 0) {
159
0
        return (char*)str->ptr;
160
0
    }
161
162
39.6k
    s = str->ptr;
163
39.6k
    ends = str->ptr + str->slen - substr->slen;
164
39.6k
    first = substr->ptr[0];
165
703k
    for (; s<=ends; ++s) {
166
703k
        if (s[0] == first && pj_memcmp(s, substr->ptr, substr->slen) == 0)
167
38.9k
            return (char*)s;
168
703k
    }
169
717
    return NULL;
170
39.6k
}
171
172
173
PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr)
174
0
{
175
0
    const char *s, *ends;
176
0
    int first;
177
178
0
    PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
179
180
    /* Check if the string is empty */
181
0
    if (str->slen <= 0)
182
0
        return NULL;
183
184
    /* Special case when substr is empty */
185
0
    if (substr->slen == 0) {
186
0
        return (char*)str->ptr;
187
0
    }
188
189
0
    s = str->ptr;
190
0
    ends = str->ptr + str->slen - substr->slen;
191
0
    first = pj_tolower(substr->ptr[0]);
192
0
    for (; s<=ends; ++s) {
193
0
        if (pj_tolower(s[0]) == first && pj_ansi_strnicmp(s, substr->ptr, substr->slen) == 0)
194
0
            return (char*)s;
195
0
    }
196
0
    return NULL;
197
0
}
198
199
200
PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
201
407k
{
202
407k
    char *end = str->ptr + str->slen;
203
407k
    register char *p = str->ptr;
204
205
407k
    pj_assert(str->slen >= 0);
206
207
415k
    while (p < end && pj_isspace(*p))
208
8.04k
        ++p;
209
407k
    str->slen -= (p - str->ptr);
210
407k
    str->ptr = p;
211
407k
    return str;
212
407k
}
213
214
PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
215
14.2k
{
216
14.2k
    char *end = str->ptr + str->slen;
217
14.2k
    register char *p = end - 1;
218
219
14.2k
    pj_assert(str->slen >= 0);
220
221
18.8k
    while (p >= str->ptr && pj_isspace(*p))
222
4.66k
        --p;
223
14.2k
    str->slen -= ((end - p) - 1);
224
14.2k
    return str;
225
14.2k
}
226
227
PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len)
228
0
{
229
0
    unsigned i;
230
0
    char *p = str;
231
232
0
    PJ_CHECK_STACK();
233
234
0
    for (i=0; i<len/8; ++i) {
235
0
        pj_uint32_t val = pj_rand();
236
0
        pj_val_to_hex_digit( (val & 0xFF000000) >> 24, p+0 );
237
0
        pj_val_to_hex_digit( (val & 0x00FF0000) >> 16, p+2 );
238
0
        pj_val_to_hex_digit( (val & 0x0000FF00) >>  8, p+4 );
239
0
        pj_val_to_hex_digit( (val & 0x000000FF) >>  0, p+6 );
240
0
        p += 8;
241
0
    }
242
0
    for (i=i * 8; i<len; ++i) {
243
0
        *p++ = pj_hex_digits[ pj_rand() & 0x0F ];
244
0
    }
245
0
    return str;
246
0
}
247
248
PJ_DEF(long) pj_strtol(const pj_str_t *str)
249
3.44k
{
250
3.44k
    pj_bool_t is_negative = PJ_FALSE;
251
3.44k
    unsigned long uval;
252
3.44k
    long val;
253
254
3.44k
    PJ_CHECK_STACK();
255
256
3.44k
    if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) {
257
0
        pj_str_t s;
258
0
        s.ptr = str->ptr + 1;
259
0
        s.slen = str->slen - 1;
260
0
        uval = pj_strtoul(&s);
261
0
        is_negative = (str->ptr[0] == '-');
262
0
    } else
263
3.44k
        uval = pj_strtoul(str);
264
265
3.44k
    if (is_negative)
266
0
        val = uval > PJ_MAXLONG ? PJ_MINLONG : -(long)uval;
267
3.44k
    else
268
3.44k
        val = uval > PJ_MAXLONG ? PJ_MAXLONG : uval;
269
270
3.44k
    return val;
271
3.44k
}
272
273
PJ_DEF(pj_status_t) pj_strtol2(const pj_str_t *str, long *value)
274
53.7k
{
275
53.7k
    pj_str_t s;
276
53.7k
    unsigned long retval = 0;
277
53.7k
    pj_bool_t is_negative = PJ_FALSE;
278
53.7k
    int rc = 0;
279
280
53.7k
    PJ_CHECK_STACK();
281
282
53.7k
    if (!str || !value) {
283
0
        return PJ_EINVAL;
284
0
    }
285
53.7k
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
286
287
53.7k
    s = *str;
288
53.7k
    pj_strltrim(&s);
289
290
53.7k
    if (s.slen == 0)
291
614
        return PJ_EINVAL;
292
293
53.1k
    if (s.ptr[0] == '+' || s.ptr[0] == '-') {
294
6.67k
        is_negative = (s.ptr[0] == '-');
295
6.67k
        s.ptr += 1;
296
6.67k
        s.slen -= 1;
297
6.67k
    }
298
299
53.1k
    rc = pj_strtoul3(&s, &retval, 10);
300
53.1k
    if (rc == PJ_EINVAL) {
301
2.70k
        return rc;
302
50.4k
    } else if (rc != PJ_SUCCESS) {
303
1.31k
        *value = is_negative ? PJ_MINLONG : PJ_MAXLONG;
304
1.31k
        return is_negative ? PJ_ETOOSMALL : PJ_ETOOBIG;
305
1.31k
    }
306
307
49.1k
    if (retval > PJ_MAXLONG && !is_negative) {
308
1.07k
        *value = PJ_MAXLONG;
309
1.07k
        return PJ_ETOOBIG;
310
1.07k
    }
311
312
48.0k
    if (retval > (PJ_MAXLONG + 1UL) && is_negative) {
313
705
        *value = PJ_MINLONG;
314
705
        return PJ_ETOOSMALL;
315
705
    }
316
317
47.3k
    if (is_negative && retval == PJ_MAXLONG + 1UL) {
318
669
        *value = PJ_MINLONG;
319
669
        return PJ_SUCCESS;
320
669
    }
321
322
46.7k
    *value = is_negative ? -(long)retval : retval;
323
324
46.7k
    return PJ_SUCCESS;
325
47.3k
}
326
327
PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
328
66.8k
{
329
66.8k
    unsigned long value;
330
66.8k
    unsigned i;
331
332
66.8k
    PJ_CHECK_STACK();
333
334
66.8k
    pj_assert(str->slen >= 0);
335
336
66.8k
    value = 0;
337
283k
    for (i=0; i<(unsigned)str->slen; ++i) {
338
220k
        if (!pj_isdigit(str->ptr[i]))
339
3.70k
            break;
340
216k
        value = value * 10 + (str->ptr[i] - '0');
341
216k
    }
342
66.8k
    return value;
343
66.8k
}
344
345
PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
346
                                  unsigned base)
347
118k
{
348
118k
    unsigned long value;
349
118k
    unsigned i;
350
351
118k
    PJ_CHECK_STACK();
352
353
118k
    pj_assert(str->slen >= 0);
354
355
118k
    value = 0;
356
118k
    if (base <= 10) {
357
341k
        for (i=0; i<(unsigned)str->slen; ++i) {
358
330k
            unsigned c = (str->ptr[i] - '0');
359
330k
            if (c >= base)
360
107k
                break;
361
222k
            value = value * base + c;
362
222k
        }
363
118k
    } else if (base == 16) {
364
0
        for (i=0; i<(unsigned)str->slen; ++i) {
365
0
            if (!pj_isxdigit(str->ptr[i]))
366
0
                break;
367
0
            value = value * 16 + pj_hex_digit_to_val(str->ptr[i]);
368
0
        }
369
0
    } else {
370
0
        pj_assert(!"Unsupported base");
371
0
        i = 0;
372
0
        value = 0xFFFFFFFFUL;
373
0
    }
374
375
118k
    if (endptr) {
376
118k
        endptr->ptr = str->ptr + i;
377
118k
        endptr->slen = (str->slen < 0)? 0: (str->slen - i);
378
118k
    }
379
380
118k
    return value;
381
118k
}
382
383
PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
384
                                unsigned base)
385
280k
{
386
280k
    pj_str_t s;
387
280k
    unsigned i;
388
389
280k
    PJ_CHECK_STACK();
390
391
280k
    if (!str || !value) {
392
0
        return PJ_EINVAL;
393
0
    }
394
280k
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
395
    
396
280k
    s = *str;
397
280k
    pj_strltrim(&s);
398
399
280k
    if (s.slen == 0 || s.ptr[0] < '0' ||
400
277k
        (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
401
274k
        (base == 16 && !pj_isxdigit(s.ptr[0])))
402
5.52k
    {
403
5.52k
        return PJ_EINVAL;
404
5.52k
    }
405
406
274k
    *value = 0;
407
274k
    if (base <= 10) {
408
924k
        for (i=0; i<(unsigned)s.slen; ++i) {
409
668k
            unsigned c = s.ptr[i] - '0';
410
668k
            if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
411
16.8k
                break;
412
16.8k
            }
413
651k
            if (*value > PJ_MAXULONG / base) {
414
831
                *value = PJ_MAXULONG;
415
831
                return PJ_ETOOBIG;
416
831
            }
417
418
650k
            *value *= base;
419
650k
            if ((PJ_MAXULONG - *value) < c) {
420
709
                *value = PJ_MAXULONG;
421
709
                return PJ_ETOOBIG;
422
709
            }
423
649k
            *value += c;
424
649k
        }
425
274k
    } else if (base == 16) {
426
0
        for (i=0; i<(unsigned)s.slen; ++i) {
427
0
            unsigned c = pj_hex_digit_to_val(s.ptr[i]);
428
0
            if (!pj_isxdigit(s.ptr[i]))
429
0
                break;
430
431
0
            if (*value > PJ_MAXULONG / base) {
432
0
                *value = PJ_MAXULONG;
433
0
                return PJ_ETOOBIG;
434
0
            }
435
0
            *value *= base;
436
0
            if ((PJ_MAXULONG - *value) < c) {
437
0
                *value = PJ_MAXULONG;
438
0
                return PJ_ETOOBIG;
439
0
            }
440
0
            *value += c;
441
0
        }
442
0
    } else {
443
0
        pj_assert(!"Unsupported base");
444
0
        return PJ_EINVAL;
445
0
    }
446
273k
    return PJ_SUCCESS;
447
274k
}
448
449
PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
450
                                unsigned base)
451
59.0k
{
452
59.0k
    pj_str_t s;
453
59.0k
    unsigned i;
454
455
59.0k
    PJ_CHECK_STACK();
456
457
59.0k
    if (!str || !value) {
458
0
        return PJ_EINVAL;
459
0
    }
460
59.0k
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
461
462
59.0k
    s = *str;
463
59.0k
    pj_strltrim(&s);
464
465
59.0k
    if (s.slen == 0 || s.ptr[0] < '0' ||
466
58.9k
        (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
467
58.9k
        (base == 16 && !pj_isxdigit(s.ptr[0])))
468
114
    {
469
114
        return PJ_EINVAL;
470
114
    }
471
472
58.9k
    *value = 0;
473
58.9k
    if (base <= 10) {
474
158k
        for (i=0; i<(unsigned)s.slen; ++i) {
475
101k
            unsigned c = s.ptr[i] - '0';
476
101k
            if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
477
2.49k
                break;
478
2.49k
            }
479
99.4k
            if (*value > PJ_MAXUINT / base) {
480
66
                *value = PJ_MAXUINT;
481
66
                return PJ_ETOOBIG;
482
66
            }
483
484
99.3k
            *value *= base;
485
99.3k
            if ((PJ_MAXUINT - *value) < c) {
486
9
                *value = PJ_MAXUINT;
487
9
                return PJ_ETOOBIG;
488
9
            }
489
99.3k
            *value += c;
490
99.3k
        }
491
58.9k
    } else if (base == 16) {
492
0
        for (i=0; i<(unsigned)s.slen; ++i) {
493
0
            unsigned c = pj_hex_digit_to_val(s.ptr[i]);
494
0
            if (!pj_isxdigit(s.ptr[i]))
495
0
                break;
496
497
0
            if (*value > PJ_MAXUINT / base) {
498
0
                *value = PJ_MAXUINT;
499
0
                return PJ_ETOOBIG;
500
0
            }
501
0
            *value *= base;
502
0
            if ((PJ_MAXUINT - *value) < c) {
503
0
                *value = PJ_MAXUINT;
504
0
                return PJ_ETOOBIG;
505
0
            }
506
0
            *value += c;
507
0
        }
508
0
    } else {
509
0
        pj_assert(!"Unsupported base");
510
0
        return PJ_EINVAL;
511
0
    }
512
58.8k
    return PJ_SUCCESS;
513
58.9k
}
514
515
PJ_DEF(float) pj_strtof(const pj_str_t *str)
516
5.94k
{
517
5.94k
    pj_str_t part;
518
5.94k
    char *pdot;
519
5.94k
    float val;
520
521
5.94k
    pj_assert(str->slen >= 0);
522
523
5.94k
    if (str->slen <= 0)
524
0
        return 0;
525
526
5.94k
    pdot = (char*)pj_memchr(str->ptr, '.', str->slen);
527
5.94k
    part.ptr = str->ptr;
528
5.94k
    part.slen = pdot ? pdot - str->ptr : str->slen;
529
530
5.94k
    if (part.slen)
531
3.25k
        val = (float)pj_strtol(&part);
532
2.69k
    else
533
2.69k
        val = 0;
534
535
5.94k
    if (pdot) {
536
2.69k
        part.ptr = pdot + 1;
537
2.69k
        part.slen = (str->ptr + str->slen - pdot - 1);
538
2.69k
        if (part.slen) {
539
619
            pj_str_t endptr;
540
619
            float fpart, fdiv;
541
619
            int i;
542
619
            fpart = (float)pj_strtoul2(&part, &endptr, 10);
543
619
            fdiv = 1.0;
544
13.6k
            for (i=0; i<(part.slen - endptr.slen); ++i)
545
13.0k
                    fdiv = fdiv * 10;
546
619
            if (val >= 0)
547
619
                val += (fpart / fdiv);
548
0
            else
549
0
                val -= (fpart / fdiv);
550
619
        }
551
2.69k
    }
552
5.94k
    return val;
553
5.94k
}
554
555
PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
556
9.18k
{
557
9.18k
    return pj_utoa_pad(val, buf, 0, 0);
558
9.18k
}
559
560
PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
561
9.33k
{
562
9.33k
    char *p;
563
9.33k
    int len;
564
565
9.33k
    PJ_CHECK_STACK();
566
567
9.33k
    p = buf;
568
14.7k
    do {
569
14.7k
        unsigned long digval = (unsigned long) (val % 10);
570
14.7k
        val /= 10;
571
14.7k
        *p++ = (char) (digval + '0');
572
14.7k
    } while (val > 0);
573
574
9.33k
    len = (int)(p-buf);
575
9.37k
    while (len < min_dig) {
576
38
        *p++ = (char)pad;
577
38
        ++len;
578
38
    }
579
9.33k
    *p-- = '\0';
580
581
9.94k
    do {
582
9.94k
        char temp = *p;
583
9.94k
        *p = *buf;
584
9.94k
        *buf = temp;
585
9.94k
        --p;
586
9.94k
        ++buf;
587
9.94k
    } while (buf < p);
588
589
9.33k
    return len;
590
9.33k
}
591
592
PJ_DEF(int) pj_utoa2(pj_uint_t val, char *buf)
593
0
{
594
0
    return pj_utoa_pad2(val, buf, 0, 0);
595
0
}
596
597
PJ_DEF(int) pj_utoa_pad2(pj_uint_t val, char *buf, int min_dig, int pad)
598
0
{
599
0
    char *p;
600
0
    int len;
601
602
0
    PJ_CHECK_STACK();
603
604
0
    p = buf;
605
0
    do {
606
0
        pj_uint_t digval = (pj_uint_t) (val % 10);
607
0
        val /= 10;
608
0
        *p++ = (char) (digval + '0');
609
0
    } while (val > 0);
610
611
0
    len = (int)(p-buf);
612
0
    while (len < min_dig) {
613
0
        *p++ = (char)pad;
614
0
        ++len;
615
0
    }
616
0
    *p-- = '\0';
617
618
0
    do {
619
0
        char temp = *p;
620
0
        *p = *buf;
621
0
        *buf = temp;
622
0
        --p;
623
0
        ++buf;
624
0
    } while (buf < p);
625
626
0
    return len;
627
0
}
628
629
PJ_DEF(int) pj_ansi_strxcpy(char *dst, const char *src,
630
                            pj_size_t dst_size)
631
644k
{
632
644k
    char *odst = dst;
633
634
644k
    PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
635
636
644k
    if (dst_size==0)
637
0
        return -PJ_ETOOBIG;
638
639
10.1M
    while (--dst_size && (*dst=*src) != 0) {
640
9.50M
        ++dst;
641
9.50M
        ++src;
642
9.50M
    }
643
644
644k
    if (!*dst && !*src) {
645
644k
        return (int)(dst-odst);
646
644k
    } else {
647
2
        *dst = '\0';
648
2
        return *src? -PJ_ETOOBIG : (int)(dst-odst);
649
2
    }
650
644k
}
651
652
PJ_DEF(int) pj_ansi_strxcpy2(char *dst, const pj_str_t *src,
653
                             pj_size_t dst_size)
654
0
{
655
0
    char *odst = dst;
656
0
    const char *ssrc, *esrc;
657
658
0
    PJ_ASSERT_RETURN(dst && src && src->slen >= 0, -PJ_EINVAL);
659
0
    if (dst_size==0)
660
0
        return -PJ_ETOOBIG;
661
662
0
    ssrc = src->ptr;
663
0
    esrc = ssrc + src->slen;
664
665
0
    while (ssrc < esrc && --dst_size && (*dst = *ssrc)!= 0) {
666
0
        dst++;
667
0
        ssrc++;
668
0
    }
669
670
0
    *dst = '\0';
671
0
    if (ssrc==esrc || !*ssrc) {
672
0
         return (int)(dst-odst);
673
0
    } else {
674
0
        return -PJ_ETOOBIG;
675
0
    }
676
0
}
677
678
PJ_DEF(int) pj_ansi_strxcat(char *dst, const char *src, pj_size_t dst_size)
679
0
{
680
0
    pj_size_t dst_len;
681
682
0
    PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
683
684
0
    if (dst_size==0)
685
0
        return -PJ_ETOOBIG;
686
687
0
    dst_len = pj_ansi_strlen(dst);
688
0
    if (dst_len < dst_size) {
689
0
        int rc = pj_ansi_strxcpy(dst+dst_len, src, dst_size-dst_len);
690
0
        if (rc < 0)
691
0
            return rc;
692
0
        return (int)dst_len + rc;
693
0
    } else
694
0
        return -PJ_ETOOBIG;
695
0
}