Coverage Report

Created: 2026-01-10 06:29

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
0
{
35
0
    pj_ssize_t i, j, count = 0;
36
0
    for (i = 0; i < str->slen; i++) {
37
0
        if (count != i)
38
0
            break;
39
40
0
        for (j = 0; j < set_char->slen; j++) {
41
0
            if (str->ptr[i] == set_char->ptr[j])
42
0
                count++;
43
0
        }
44
0
    }
45
0
    return count;
46
0
}
47
48
49
PJ_DEF(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char)
50
0
{
51
0
    pj_ssize_t i, j, count = 0;
52
0
    for (i = 0; i < str->slen; i++) {
53
0
        if (count != i)
54
0
            break;
55
56
0
        for (j = 0; set_char[j] != 0; j++) {
57
0
            if (str->ptr[i] == set_char[j])
58
0
                count++;
59
0
        }
60
0
    }
61
0
    return count;
62
0
}
63
64
65
PJ_DEF(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char)
66
0
{
67
0
    pj_ssize_t i, j;
68
0
    for (i = 0; i < str->slen; i++) {
69
0
        for (j = 0; j < set_char->slen; j++) {
70
0
            if (str->ptr[i] == set_char->ptr[j])
71
0
                return i;
72
0
        }
73
0
    }
74
0
    return i;
75
0
}
76
77
78
PJ_DEF(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char)
79
0
{
80
0
    pj_ssize_t i, j;
81
0
    for (i = 0; i < str->slen; i++) {
82
0
        for (j = 0; set_char[j] != 0; j++) {
83
0
            if (str->ptr[i] == set_char[j])
84
0
                return i;
85
0
        }
86
0
    }
87
0
    return i;
88
0
}
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
0
{
94
0
    pj_ssize_t str_idx;
95
96
0
    pj_assert(str->slen >= 0);
97
0
    pj_assert(delim->slen >= 0);
98
99
0
    tok->slen = 0;
100
0
    if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
101
0
        return str->slen;
102
0
    }
103
104
0
    tok->ptr = str->ptr + start_idx;
105
0
    tok->slen = str->slen - start_idx;
106
107
0
    str_idx = pj_strspn(tok, delim);
108
0
    if (start_idx+str_idx == (pj_size_t)str->slen) {
109
0
        return str->slen;
110
0
    }
111
0
    tok->ptr += str_idx;
112
0
    tok->slen -= str_idx;
113
114
0
    tok->slen = pj_strcspn(tok, delim);
115
0
    return start_idx + str_idx;
116
0
}
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
0
{
122
0
    pj_ssize_t str_idx;
123
124
0
    pj_assert(str->slen >= 0);
125
126
0
    tok->slen = 0;
127
0
    if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
128
0
        return str->slen;
129
0
    }
130
131
0
    tok->ptr = str->ptr + start_idx;
132
0
    tok->slen = str->slen - start_idx;
133
134
0
    str_idx = pj_strspn2(tok, delim);
135
0
    if (start_idx + str_idx == (pj_size_t)str->slen) {
136
0
        return str->slen;
137
0
    }
138
0
    tok->ptr += str_idx;
139
0
    tok->slen -= str_idx;
140
141
0
    tok->slen = pj_strcspn2(tok, delim);
142
0
    return start_idx + str_idx;
143
0
}
144
145
146
PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr)
147
0
{
148
0
    const char *s, *ends;
149
0
    int first;
150
151
0
    PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
152
153
    /* Check if the string is empty */
154
0
    if (str->slen <= 0)
155
0
        return NULL;
156
157
    /* Special case when substr is empty */
158
0
    if (substr->slen <= 0) {
159
0
        return (char*)str->ptr;
160
0
    }
161
162
0
    s = str->ptr;
163
0
    ends = str->ptr + str->slen - substr->slen;
164
0
    first = substr->ptr[0];
165
0
    for (; s<=ends; ++s) {
166
0
        if (s[0] == first && pj_memcmp(s, substr->ptr, substr->slen) == 0)
167
0
            return (char*)s;
168
0
    }
169
0
    return NULL;
170
0
}
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
0
{
202
0
    char *end = str->ptr + str->slen;
203
0
    register char *p = str->ptr;
204
205
0
    pj_assert(str->slen >= 0);
206
207
0
    while (p < end && pj_isspace(*p))
208
0
        ++p;
209
0
    str->slen -= (p - str->ptr);
210
0
    str->ptr = p;
211
0
    return str;
212
0
}
213
214
PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
215
0
{
216
0
    char *end = str->ptr + str->slen;
217
0
    register char *p = end - 1;
218
219
0
    pj_assert(str->slen >= 0);
220
221
0
    while (p >= str->ptr && pj_isspace(*p))
222
0
        --p;
223
0
    str->slen -= ((end - p) - 1);
224
0
    return str;
225
0
}
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.49k
{
250
3.49k
    pj_bool_t is_negative = PJ_FALSE;
251
3.49k
    unsigned long uval;
252
3.49k
    long val;
253
254
3.49k
    PJ_CHECK_STACK();
255
256
3.49k
    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.49k
        uval = pj_strtoul(str);
264
265
3.49k
    if (is_negative)
266
0
        val = uval > PJ_MAXLONG ? PJ_MINLONG : -(long)uval;
267
3.49k
    else
268
3.49k
        val = uval > PJ_MAXLONG ? PJ_MAXLONG : uval;
269
270
3.49k
    return val;
271
3.49k
}
272
273
PJ_DEF(pj_status_t) pj_strtol2(const pj_str_t *str, long *value)
274
0
{
275
0
    pj_str_t s;
276
0
    unsigned long retval = 0;
277
0
    pj_bool_t is_negative = PJ_FALSE;
278
0
    int rc = 0;
279
280
0
    PJ_CHECK_STACK();
281
282
0
    if (!str || !value) {
283
0
        return PJ_EINVAL;
284
0
    }
285
0
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
286
287
0
    s = *str;
288
0
    pj_strltrim(&s);
289
290
0
    if (s.slen == 0)
291
0
        return PJ_EINVAL;
292
293
0
    if (s.ptr[0] == '+' || s.ptr[0] == '-') {
294
0
        is_negative = (s.ptr[0] == '-');
295
0
        s.ptr += 1;
296
0
        s.slen -= 1;
297
0
    }
298
299
0
    rc = pj_strtoul3(&s, &retval, 10);
300
0
    if (rc == PJ_EINVAL) {
301
0
        return rc;
302
0
    } else if (rc != PJ_SUCCESS) {
303
0
        *value = is_negative ? PJ_MINLONG : PJ_MAXLONG;
304
0
        return is_negative ? PJ_ETOOSMALL : PJ_ETOOBIG;
305
0
    }
306
307
0
    if (retval > PJ_MAXLONG && !is_negative) {
308
0
        *value = PJ_MAXLONG;
309
0
        return PJ_ETOOBIG;
310
0
    }
311
312
0
    if (retval > (PJ_MAXLONG + 1UL) && is_negative) {
313
0
        *value = PJ_MINLONG;
314
0
        return PJ_ETOOSMALL;
315
0
    }
316
317
0
    if (is_negative && retval == PJ_MAXLONG + 1UL) {
318
0
        *value = PJ_MINLONG;
319
0
        return PJ_SUCCESS;
320
0
    }
321
322
0
    *value = is_negative ? -(long)retval : retval;
323
324
0
    return PJ_SUCCESS;
325
0
}
326
327
PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
328
3.49k
{
329
3.49k
    unsigned long value;
330
3.49k
    unsigned i;
331
332
3.49k
    PJ_CHECK_STACK();
333
334
3.49k
    pj_assert(str->slen >= 0);
335
336
3.49k
    value = 0;
337
22.4k
    for (i=0; i<(unsigned)str->slen; ++i) {
338
18.9k
        if (!pj_isdigit(str->ptr[i]))
339
0
            break;
340
18.9k
        value = value * 10 + (str->ptr[i] - '0');
341
18.9k
    }
342
3.49k
    return value;
343
3.49k
}
344
345
PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
346
                                  unsigned base)
347
646
{
348
646
    unsigned long value;
349
646
    unsigned i;
350
351
646
    PJ_CHECK_STACK();
352
353
646
    pj_assert(str->slen >= 0);
354
355
646
    value = 0;
356
646
    if (base <= 10) {
357
9.90k
        for (i=0; i<(unsigned)str->slen; ++i) {
358
9.47k
            unsigned c = (str->ptr[i] - '0');
359
9.47k
            if (c >= base)
360
215
                break;
361
9.25k
            value = value * base + c;
362
9.25k
        }
363
646
    } 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
646
    if (endptr) {
376
646
        endptr->ptr = str->ptr + i;
377
646
        endptr->slen = (str->slen < 0)? 0: (str->slen - i);
378
646
    }
379
380
646
    return value;
381
646
}
382
383
PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
384
                                unsigned base)
385
0
{
386
0
    pj_str_t s;
387
0
    unsigned i;
388
389
0
    PJ_CHECK_STACK();
390
391
0
    if (!str || !value) {
392
0
        return PJ_EINVAL;
393
0
    }
394
0
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
395
    
396
0
    s = *str;
397
0
    pj_strltrim(&s);
398
399
0
    if (s.slen == 0 || s.ptr[0] < '0' ||
400
0
        (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
401
0
        (base == 16 && !pj_isxdigit(s.ptr[0])))
402
0
    {
403
0
        return PJ_EINVAL;
404
0
    }
405
406
0
    *value = 0;
407
0
    if (base <= 10) {
408
0
        for (i=0; i<(unsigned)s.slen; ++i) {
409
0
            unsigned c = s.ptr[i] - '0';
410
0
            if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
411
0
                break;
412
0
            }
413
0
            if (*value > PJ_MAXULONG / base) {
414
0
                *value = PJ_MAXULONG;
415
0
                return PJ_ETOOBIG;
416
0
            }
417
418
0
            *value *= base;
419
0
            if ((PJ_MAXULONG - *value) < c) {
420
0
                *value = PJ_MAXULONG;
421
0
                return PJ_ETOOBIG;
422
0
            }
423
0
            *value += c;
424
0
        }
425
0
    } 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
0
    return PJ_SUCCESS;
447
0
}
448
449
PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
450
                                unsigned base)
451
0
{
452
0
    pj_str_t s;
453
0
    unsigned i;
454
455
0
    PJ_CHECK_STACK();
456
457
0
    if (!str || !value) {
458
0
        return PJ_EINVAL;
459
0
    }
460
0
    PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
461
462
0
    s = *str;
463
0
    pj_strltrim(&s);
464
465
0
    if (s.slen == 0 || s.ptr[0] < '0' ||
466
0
        (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
467
0
        (base == 16 && !pj_isxdigit(s.ptr[0])))
468
0
    {
469
0
        return PJ_EINVAL;
470
0
    }
471
472
0
    *value = 0;
473
0
    if (base <= 10) {
474
0
        for (i=0; i<(unsigned)s.slen; ++i) {
475
0
            unsigned c = s.ptr[i] - '0';
476
0
            if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
477
0
                break;
478
0
            }
479
0
            if (*value > PJ_MAXUINT / base) {
480
0
                *value = PJ_MAXUINT;
481
0
                return PJ_ETOOBIG;
482
0
            }
483
484
0
            *value *= base;
485
0
            if ((PJ_MAXUINT - *value) < c) {
486
0
                *value = PJ_MAXUINT;
487
0
                return PJ_ETOOBIG;
488
0
            }
489
0
            *value += c;
490
0
        }
491
0
    } 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
0
    return PJ_SUCCESS;
513
0
}
514
515
PJ_DEF(float) pj_strtof(const pj_str_t *str)
516
6.17k
{
517
6.17k
    pj_str_t part;
518
6.17k
    char *pdot;
519
6.17k
    float val;
520
521
6.17k
    pj_assert(str->slen >= 0);
522
523
6.17k
    if (str->slen <= 0)
524
0
        return 0;
525
526
6.17k
    pdot = (char*)pj_memchr(str->ptr, '.', str->slen);
527
6.17k
    part.ptr = str->ptr;
528
6.17k
    part.slen = pdot ? pdot - str->ptr : str->slen;
529
530
6.17k
    if (part.slen)
531
3.49k
        val = (float)pj_strtol(&part);
532
2.67k
    else
533
2.67k
        val = 0;
534
535
6.17k
    if (pdot) {
536
2.70k
        part.ptr = pdot + 1;
537
2.70k
        part.slen = (str->ptr + str->slen - pdot - 1);
538
2.70k
        if (part.slen) {
539
646
            pj_str_t endptr;
540
646
            float fpart, fdiv;
541
646
            int i;
542
646
            fpart = (float)pj_strtoul2(&part, &endptr, 10);
543
646
            fdiv = 1.0;
544
9.90k
            for (i=0; i<(part.slen - endptr.slen); ++i)
545
9.25k
                    fdiv = fdiv * 10;
546
646
            if (val >= 0)
547
646
                val += (fpart / fdiv);
548
0
            else
549
0
                val -= (fpart / fdiv);
550
646
        }
551
2.70k
    }
552
6.17k
    return val;
553
6.17k
}
554
555
PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
556
0
{
557
0
    return pj_utoa_pad(val, buf, 0, 0);
558
0
}
559
560
PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
561
4
{
562
4
    char *p;
563
4
    int len;
564
565
4
    PJ_CHECK_STACK();
566
567
4
    p = buf;
568
8
    do {
569
8
        unsigned long digval = (unsigned long) (val % 10);
570
8
        val /= 10;
571
8
        *p++ = (char) (digval + '0');
572
8
    } while (val > 0);
573
574
4
    len = (int)(p-buf);
575
5
    while (len < min_dig) {
576
1
        *p++ = (char)pad;
577
1
        ++len;
578
1
    }
579
4
    *p-- = '\0';
580
581
4
    do {
582
4
        char temp = *p;
583
4
        *p = *buf;
584
4
        *buf = temp;
585
4
        --p;
586
4
        ++buf;
587
4
    } while (buf < p);
588
589
4
    return len;
590
4
}
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
6.83k
{
632
6.83k
    char *odst = dst;
633
634
6.83k
    PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
635
636
6.83k
    if (dst_size==0)
637
0
        return -PJ_ETOOBIG;
638
639
88.8k
    while (--dst_size && (*dst=*src) != 0) {
640
82.0k
        ++dst;
641
82.0k
        ++src;
642
82.0k
    }
643
644
6.83k
    if (!*dst && !*src) {
645
6.83k
        return (int)(dst-odst);
646
6.83k
    } else {
647
0
        *dst = '\0';
648
0
        return *src? -PJ_ETOOBIG : (int)(dst-odst);
649
0
    }
650
6.83k
}
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
}