~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/common/ustring.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
******************************************************************************
3
 
*
4
 
*   Copyright (C) 1998-2001, International Business Machines
5
 
*   Corporation and others.  All Rights Reserved.
6
 
*
7
 
******************************************************************************
8
 
*
9
 
* File ustring.h
10
 
*
11
 
* Modification History:
12
 
*
13
 
*   Date        Name        Description
14
 
*   12/07/98    bertrand    Creation.
15
 
******************************************************************************
16
 
*/
17
 
 
18
 
#include "unicode/utypes.h"
19
 
#include "unicode/ustring.h"
20
 
#include "unicode/putil.h"
21
 
#include "unicode/ucnv.h"
22
 
#include "cstring.h"
23
 
#include "cwchar.h"
24
 
#include "cmemory.h"
25
 
#include "umutex.h"
26
 
#include "ustr_imp.h"
27
 
#include "ucln_cmn.h"
28
 
 
29
 
/* forward declaractions of definitions for the shared default converter */
30
 
 
31
 
static UConverter *gDefaultConverter = NULL;
32
 
 
33
 
/* ANSI string.h - style functions ------------------------------------------ */
34
 
 
35
 
#define MAX_STRLEN 0x0FFFFFFF
36
 
 
37
 
/* ---- String searching functions ---- */
38
 
 
39
 
U_CAPI UChar* U_EXPORT2
40
 
u_strchr(const UChar *s, UChar c) 
41
 
{
42
 
  while (*s && *s != c) {
43
 
    ++s;
44
 
  }
45
 
  if (*s == c)
46
 
    return (UChar *)s;
47
 
  return NULL;
48
 
}
49
 
 
50
 
/* A Boyer-Moore algorithm would be better, but that would require a hashtable
51
 
   because UChar is so big. This algorithm doesn't use a lot of extra memory.
52
 
 */
53
 
U_CAPI UChar * U_EXPORT2
54
 
u_strstr(const UChar *s, const UChar *substring) {
55
 
 
56
 
  UChar *strItr, *subItr;
57
 
 
58
 
  if (*substring == 0) {
59
 
    return (UChar *)s;
60
 
  }
61
 
 
62
 
  do {
63
 
    strItr = (UChar *)s;
64
 
    subItr = (UChar *)substring;
65
 
 
66
 
    /* Only one string iterator needs checking for null terminator */
67
 
    while ((*strItr != 0) && (*strItr == *subItr)) {
68
 
      strItr++;
69
 
      subItr++;
70
 
    }
71
 
 
72
 
    if (*subItr == 0) {             /* Was the end of the substring reached? */
73
 
      return (UChar *)s;
74
 
    }
75
 
 
76
 
    s++;
77
 
  } while (*strItr != 0);           /* Was the end of the string reached? */
78
 
 
79
 
  return NULL;                      /* No match */
80
 
}
81
 
 
82
 
/**
83
 
 * Check if there is an unmatched surrogate c in a string [start..limit[ at s.
84
 
 * start<=s<limit or limit==NULL
85
 
 * @return TRUE if *s is unmatched
86
 
 */
87
 
static U_INLINE UBool
88
 
uprv_isSingleSurrogate(const UChar *start, const UChar *s, UChar c, const UChar *limit) {
89
 
    if(UTF_IS_SURROGATE_FIRST(c)) {
90
 
        ++s;
91
 
        return (UBool)(s==limit || !UTF_IS_TRAIL(*s));
92
 
    } else {
93
 
        return (UBool)(s==start || !UTF_IS_LEAD(*(s-1)));
94
 
    }
95
 
}
96
 
 
97
 
U_CFUNC const UChar *
98
 
uprv_strFindSurrogate(const UChar *s, int32_t length, UChar surrogate) {
99
 
    const UChar *limit, *t;
100
 
    UChar c;
101
 
 
102
 
    if(length>=0) {
103
 
        limit=s+length;
104
 
    } else {
105
 
        limit=NULL;
106
 
    }
107
 
 
108
 
    for(t=s; t!=limit && ((c=*t)!=0 || limit!=NULL); ++t) {
109
 
        if(c==surrogate && uprv_isSingleSurrogate(s, t, c, limit)) {
110
 
            return t;
111
 
        }
112
 
    }
113
 
 
114
 
    return NULL;
115
 
}
116
 
 
117
 
U_CFUNC const UChar *
118
 
uprv_strFindLastSurrogate(const UChar *s, int32_t length, UChar surrogate) {
119
 
    const UChar *limit, *t;
120
 
    UChar c;
121
 
 
122
 
    if(length>=0) {
123
 
        limit=s+length;
124
 
    } else {
125
 
        limit=s+u_strlen(s);
126
 
    }
127
 
 
128
 
    for(t=limit; t!=s;) {
129
 
        c=*--t;
130
 
        if(c==surrogate && uprv_isSingleSurrogate(s, t, c, limit)) {
131
 
            return t;
132
 
        }
133
 
    }
134
 
 
135
 
    return NULL;
136
 
}
137
 
 
138
 
U_CAPI UChar * U_EXPORT2
139
 
u_strchr32(const UChar *s, UChar32 c) {
140
 
  if(c < 0xd800) {
141
 
    /* non-surrogate BMP code point */
142
 
    return u_strchr(s, (UChar)c);
143
 
  } else if(c <= 0xdfff) {
144
 
    /* surrogate code point */
145
 
    return (UChar *)uprv_strFindSurrogate(s, -1, (UChar)c);
146
 
  } else if(c <= 0xffff) {
147
 
    /* non-surrogate BMP code point */
148
 
    return u_strchr(s, (UChar)c);
149
 
  } else {
150
 
    /* supplementary code point, search for string */
151
 
    UChar buffer[3];
152
 
 
153
 
    buffer[0] = UTF16_LEAD(c);
154
 
    buffer[1] = UTF16_TRAIL(c);
155
 
    buffer[2] = 0;
156
 
    return u_strstr(s, buffer);
157
 
  }
158
 
}
159
 
 
160
 
/* Search for a codepoint in a string that matches one of the matchSet codepoints. */
161
 
U_CAPI UChar * U_EXPORT2
162
 
u_strpbrk(const UChar *string, const UChar *matchSet)
163
 
{
164
 
    int32_t matchLen;
165
 
    UBool single = TRUE;
166
 
 
167
 
    for (matchLen = 0; matchSet[matchLen]; matchLen++)
168
 
    {
169
 
        if (!UTF_IS_SINGLE(matchSet[matchLen]))
170
 
        {
171
 
            single = FALSE;
172
 
        }
173
 
    }
174
 
 
175
 
    if (single)
176
 
    {
177
 
        const UChar *matchItr;
178
 
        const UChar *strItr;
179
 
 
180
 
        for (strItr = string; *strItr; strItr++)
181
 
        {
182
 
            for (matchItr = matchSet; *matchItr; matchItr++)
183
 
            {
184
 
                if (*matchItr == *strItr)
185
 
                {
186
 
                    return (UChar *)strItr;
187
 
                }
188
 
            }
189
 
        }
190
 
    }
191
 
    else
192
 
    {
193
 
        int32_t matchItr;
194
 
        int32_t strItr;
195
 
        UChar32 stringCh, matchSetCh;
196
 
        int32_t stringLen = u_strlen(string);
197
 
 
198
 
        for (strItr = 0; strItr < stringLen; strItr++)
199
 
        {
200
 
            UTF_GET_CHAR_SAFE(string, 0, strItr, stringLen, stringCh, TRUE);
201
 
            for (matchItr = 0; matchItr < matchLen; matchItr++)
202
 
            {
203
 
                UTF_GET_CHAR_SAFE(matchSet, 0, matchItr, matchLen, matchSetCh, TRUE);
204
 
                if (stringCh == matchSetCh && (stringCh != UTF_ERROR_VALUE
205
 
                    || string[strItr] == UTF_ERROR_VALUE
206
 
                    || (matchSetCh == UTF_ERROR_VALUE && !UTF_IS_SINGLE(matchSet[matchItr]))))
207
 
                {
208
 
                    return (UChar *)string + strItr;
209
 
                }
210
 
            }
211
 
        }
212
 
    }
213
 
 
214
 
    /* Didn't find it. */
215
 
    return NULL;
216
 
}
217
 
 
218
 
/* Search for a codepoint in a string that matches one of the matchSet codepoints. */
219
 
U_CAPI int32_t U_EXPORT2
220
 
u_strcspn(const UChar *string, const UChar *matchSet)
221
 
{
222
 
    const UChar *foundStr = u_strpbrk(string, matchSet);
223
 
    if (foundStr == NULL)
224
 
    {
225
 
        return u_strlen(string);
226
 
    }
227
 
    return foundStr - string;
228
 
}
229
 
 
230
 
/* Search for a codepoint in a string that does not match one of the matchSet codepoints. */
231
 
U_CAPI int32_t U_EXPORT2
232
 
u_strspn(const UChar *string, const UChar *matchSet)
233
 
{
234
 
    UBool single = TRUE;
235
 
    UBool match = TRUE;
236
 
    int32_t matchLen;
237
 
    int32_t retValue;
238
 
 
239
 
    for (matchLen = 0; matchSet[matchLen]; matchLen++)
240
 
    {
241
 
        if (!UTF_IS_SINGLE(matchSet[matchLen]))
242
 
        {
243
 
            single = FALSE;
244
 
        }
245
 
    }
246
 
 
247
 
    if (single)
248
 
    {
249
 
        const UChar *matchItr;
250
 
        const UChar *strItr;
251
 
 
252
 
        for (strItr = string; *strItr && match; strItr++)
253
 
        {
254
 
            match = FALSE;
255
 
            for (matchItr = matchSet; *matchItr; matchItr++)
256
 
            {
257
 
                if (*matchItr == *strItr)
258
 
                {
259
 
                    match = TRUE;
260
 
                    break;
261
 
                }
262
 
            }
263
 
        }
264
 
        retValue = strItr - string - (match == FALSE);
265
 
    }
266
 
    else
267
 
    {
268
 
        int32_t matchItr;
269
 
        int32_t strItr;
270
 
        UChar32 stringCh, matchSetCh;
271
 
        int32_t stringLen = u_strlen(string);
272
 
 
273
 
        for (strItr = 0; strItr < stringLen && match; strItr++)
274
 
        {
275
 
            match = FALSE;
276
 
            UTF_GET_CHAR_SAFE(string, 0, strItr, stringLen, stringCh, TRUE);
277
 
            for (matchItr = 0; matchItr < matchLen; matchItr++)
278
 
            {
279
 
                UTF_GET_CHAR_SAFE(matchSet, 0, matchItr, matchLen, matchSetCh, TRUE);
280
 
                if (stringCh == matchSetCh && (stringCh != UTF_ERROR_VALUE
281
 
                    || string[strItr] == UTF_ERROR_VALUE
282
 
                    || (matchSetCh == UTF_ERROR_VALUE && !UTF_IS_SINGLE(matchSet[matchItr]))))
283
 
                {
284
 
                    match = TRUE;
285
 
                    break;
286
 
                }
287
 
            }
288
 
        }
289
 
        retValue = strItr - (match == FALSE);
290
 
    }
291
 
 
292
 
    /* Found a mismatch or didn't find it. */
293
 
    return retValue;
294
 
}
295
 
 
296
 
/* ----- Text manipulation functions --- */
297
 
 
298
 
U_CAPI UChar* U_EXPORT2
299
 
u_strtok_r(UChar    *src, 
300
 
     const UChar    *delim,
301
 
           UChar   **saveState)
302
 
{
303
 
    UChar *tokSource;
304
 
    UChar *nextToken;
305
 
    uint32_t nonDelimIdx;
306
 
 
307
 
    /* If saveState is NULL, the user messed up. */
308
 
    if (src != NULL) {
309
 
        tokSource = src;
310
 
        *saveState = src; /* Set to "src" in case there are no delimiters */
311
 
    }
312
 
    else if (*saveState) {
313
 
        tokSource = *saveState;
314
 
    }
315
 
    else {
316
 
        /* src == NULL && *saveState == NULL */
317
 
        /* This shouldn't happen. We already finished tokenizing. */
318
 
        return NULL;
319
 
    }
320
 
 
321
 
    /* Skip initial delimiters */
322
 
    nonDelimIdx = u_strspn(tokSource, delim);
323
 
    tokSource = &tokSource[nonDelimIdx];
324
 
 
325
 
    if (*tokSource) {
326
 
        nextToken = u_strpbrk(tokSource, delim);
327
 
        if (nextToken != NULL) {
328
 
            /* Create a token */
329
 
            *(nextToken++) = 0;
330
 
            *saveState = nextToken;
331
 
            return tokSource;
332
 
        }
333
 
        else if (*saveState) {
334
 
            /* Return the last token */
335
 
            *saveState = NULL;
336
 
            return tokSource;
337
 
        }
338
 
    }
339
 
    else {
340
 
        /* No tokens were found. Only delimiters were left. */
341
 
        *saveState = NULL;
342
 
    }
343
 
    return NULL;
344
 
}
345
 
 
346
 
U_CAPI UChar* U_EXPORT2
347
 
u_strcat(UChar     *dst, 
348
 
    const UChar     *src)
349
 
{
350
 
    UChar *anchor = dst;            /* save a pointer to start of dst */
351
 
 
352
 
    while(*dst != 0) {              /* To end of first string          */
353
 
        ++dst;
354
 
    }
355
 
    while((*(dst++) = *(src++)) != 0) {     /* copy string 2 over              */
356
 
    }
357
 
 
358
 
    return anchor;
359
 
}
360
 
 
361
 
U_CAPI UChar*  U_EXPORT2
362
 
u_strncat(UChar     *dst, 
363
 
     const UChar     *src, 
364
 
     int32_t     n ) 
365
 
{
366
 
    if(n > 0) {
367
 
        UChar *anchor = dst;            /* save a pointer to start of dst */
368
 
 
369
 
        while(*dst != 0) {              /* To end of first string          */
370
 
            ++dst;
371
 
        }
372
 
        while((*dst = *src) != 0) {     /* copy string 2 over              */
373
 
            ++dst;
374
 
            if(--n == 0) {
375
 
                *dst = 0;
376
 
                break;
377
 
            }
378
 
            ++src;
379
 
        }
380
 
 
381
 
        return anchor;
382
 
    } else {
383
 
        return dst;
384
 
    }
385
 
}
386
 
 
387
 
/* ----- Text property functions --- */
388
 
 
389
 
U_CAPI int32_t   U_EXPORT2
390
 
u_strcmp(const UChar *s1, 
391
 
    const UChar *s2) 
392
 
{
393
 
    UChar  c1, c2;
394
 
 
395
 
    for(;;) {
396
 
        c1=*s1++;
397
 
        c2=*s2++;
398
 
        if (c1 != c2 || c1 == 0) {
399
 
            break;
400
 
        }
401
 
    }
402
 
    return (int32_t)c1 - (int32_t)c2;
403
 
}
404
 
 
405
 
/* rotate surrogates to the top to get code point order; assume c>=0xd800 */
406
 
#define UTF16FIXUP(c) {                  \
407
 
    if ((c) >= 0xe000) {                 \
408
 
        (c) -= 0x800;                    \
409
 
    } else {                             \
410
 
        (c) += 0x2000;                   \
411
 
    }                                    \
412
 
}
413
 
 
414
 
 
415
 
/* String compare in code point order - u_strcmp() compares in code unit order. */
416
 
U_CAPI int32_t U_EXPORT2
417
 
u_strcmpCodePointOrder(const UChar *s1, const UChar *s2) {
418
 
    UChar c1, c2;
419
 
 
420
 
    /* compare identical prefixes - they do not need to be fixed up */
421
 
    for(;;) {
422
 
        c1=*s1++;
423
 
        c2=*s2++;
424
 
        if (c1 != c2) {
425
 
            break;
426
 
        }
427
 
        if (c1 == 0) {
428
 
            return 0;
429
 
        }
430
 
    }
431
 
 
432
 
   /*  if both values are in or above the surrogate range, Fix them up. */
433
 
   if (c1 >= 0xD800 && c2 >= 0xD800) {
434
 
        UTF16FIXUP(c1);
435
 
        UTF16FIXUP(c2);
436
 
    }
437
 
 
438
 
    /* now c1 and c2 are in UTF-32-compatible order */
439
 
    return (int32_t)c1-(int32_t)c2;
440
 
}
441
 
 
442
 
U_CAPI int32_t   U_EXPORT2
443
 
u_strncmp(const UChar     *s1, 
444
 
     const UChar     *s2, 
445
 
     int32_t     n) 
446
 
{
447
 
    if(n > 0) {
448
 
        int32_t rc;
449
 
        for(;;) {
450
 
            rc = (int32_t)*s1 - (int32_t)*s2;
451
 
            if(rc != 0 || *s1 == 0 || --n == 0) {
452
 
                return rc;
453
 
            }
454
 
            ++s1;
455
 
            ++s2;
456
 
        }
457
 
    } else {
458
 
        return 0;
459
 
    }
460
 
}
461
 
 
462
 
U_CAPI int32_t U_EXPORT2
463
 
u_strncmpCodePointOrder(const UChar *s1, const UChar *s2, int32_t n) {
464
 
    UChar c1, c2;
465
 
 
466
 
    if(n<=0) {
467
 
        return 0;
468
 
    }
469
 
 
470
 
    /* compare identical prefixes - they do not need to be fixed up */
471
 
    for(;;) {
472
 
        c1=*s1;
473
 
        c2=*s2;
474
 
        if(c1==c2) {
475
 
            if(c1==0 || --n==0) {
476
 
                return 0;
477
 
            }
478
 
            ++s1;
479
 
            ++s2;
480
 
        } else {
481
 
            break;
482
 
        }
483
 
    }
484
 
 
485
 
   /* c1!=c2, fix up each one if they're both in or above the surrogate range, then compare them */
486
 
   if (c1 >= 0xD800 && c2 >= 0xD800) {
487
 
        UTF16FIXUP(c1);
488
 
        UTF16FIXUP(c2);
489
 
    }
490
 
 
491
 
    /* now c1 and c2 are in UTF-32-compatible order */
492
 
    return (int32_t)c1-(int32_t)c2;
493
 
}
494
 
 
495
 
U_CAPI UChar* U_EXPORT2
496
 
u_strcpy(UChar     *dst, 
497
 
    const UChar     *src) 
498
 
{
499
 
    UChar *anchor = dst;            /* save a pointer to start of dst */
500
 
 
501
 
    while((*(dst++) = *(src++)) != 0) {     /* copy string 2 over              */
502
 
    }
503
 
 
504
 
    return anchor;
505
 
}
506
 
 
507
 
U_CAPI UChar*  U_EXPORT2
508
 
u_strncpy(UChar     *dst, 
509
 
     const UChar     *src, 
510
 
     int32_t     n) 
511
 
{
512
 
    UChar *anchor = dst;            /* save a pointer to start of dst */
513
 
 
514
 
    /* copy string 2 over */
515
 
    while(n > 0 && (*(dst++) = *(src++)) != 0) {
516
 
        --n;
517
 
    }
518
 
 
519
 
    return anchor;
520
 
}
521
 
 
522
 
U_CAPI int32_t   U_EXPORT2
523
 
u_strlen(const UChar *s) 
524
 
{
525
 
#if U_SIZEOF_WCHAR_T == U_SIZEOF_UCHAR
526
 
    return uprv_wcslen(s);
527
 
#else
528
 
    const UChar *t = s;
529
 
    while(*t != 0) {
530
 
      ++t;
531
 
    }
532
 
    return t - s;
533
 
#endif
534
 
}
535
 
 
536
 
U_CAPI int32_t U_EXPORT2
537
 
u_countChar32(const UChar *s, int32_t length) {
538
 
    int32_t count;
539
 
 
540
 
    if(s==NULL || length<-1) {
541
 
        return 0;
542
 
    }
543
 
 
544
 
    count=0;
545
 
    if(length>=0) {
546
 
        while(length>0) {
547
 
            ++count;
548
 
            if(UTF_IS_LEAD(*s) && length>=2 && UTF_IS_TRAIL(*(s+1))) {
549
 
                s+=2;
550
 
                length-=2;
551
 
            } else {
552
 
                ++s;
553
 
                --length;
554
 
            }
555
 
        }
556
 
    } else /* length==-1 */ {
557
 
        UChar c;
558
 
 
559
 
        for(;;) {
560
 
            if((c=*s++)==0) {
561
 
                break;
562
 
            }
563
 
            ++count;
564
 
 
565
 
            /*
566
 
             * sufficient to look ahead one because of UTF-16;
567
 
             * safe to look ahead one because at worst that would be the terminating NUL
568
 
             */
569
 
            if(UTF_IS_LEAD(c) && UTF_IS_TRAIL(*s)) {
570
 
                ++s;
571
 
            }
572
 
        }
573
 
    }
574
 
    return count;
575
 
}
576
 
 
577
 
U_CAPI UChar * U_EXPORT2
578
 
u_memcpy(UChar *dest, const UChar *src, int32_t count) {
579
 
    return (UChar *)uprv_memcpy(dest, src, count*U_SIZEOF_UCHAR);
580
 
}
581
 
 
582
 
U_CAPI UChar * U_EXPORT2
583
 
u_memmove(UChar *dest, const UChar *src, int32_t count) {
584
 
    return (UChar *)uprv_memmove(dest, src, count*U_SIZEOF_UCHAR);
585
 
}
586
 
 
587
 
U_CAPI UChar * U_EXPORT2
588
 
u_memset(UChar *dest, UChar c, int32_t count) {
589
 
    if(count > 0) {
590
 
        UChar *ptr = dest;
591
 
        UChar *limit = dest + count;
592
 
 
593
 
        while (ptr < limit) {
594
 
            *(ptr++) = c;
595
 
        }
596
 
    }
597
 
    return dest;
598
 
}
599
 
 
600
 
U_CAPI int32_t U_EXPORT2
601
 
u_memcmp(const UChar *buf1, const UChar *buf2, int32_t count) {
602
 
    if(count > 0) {
603
 
        const UChar *limit = buf1 + count;
604
 
        int32_t result;
605
 
 
606
 
        while (buf1 < limit) {
607
 
            result = (int32_t)(uint16_t)*buf1 - (int32_t)(uint16_t)*buf2;
608
 
            if (result != 0) {
609
 
                return result;
610
 
            }
611
 
            buf1++;
612
 
            buf2++;
613
 
        }
614
 
    }
615
 
    return 0;
616
 
}
617
 
 
618
 
U_CAPI int32_t U_EXPORT2
619
 
u_memcmpCodePointOrder(const UChar *s1, const UChar *s2, int32_t count) {
620
 
    const UChar *limit;
621
 
    UChar c1, c2;
622
 
 
623
 
    if(count<=0) {
624
 
        return 0;
625
 
    }
626
 
 
627
 
    limit=s1+count;
628
 
 
629
 
    /* compare identical prefixes - they do not need to be fixed up */
630
 
    for(;;) {
631
 
        c1=*s1;
632
 
        c2=*s2;
633
 
        if(c1!=c2) {
634
 
            break;
635
 
        }
636
 
        ++s1;
637
 
        ++s2;
638
 
        if(s1==limit) {
639
 
            return 0;
640
 
        }
641
 
    }
642
 
 
643
 
   /* c1!=c2, fix up each one if they're both in or above the surrogate range, then compare them */
644
 
   if (c1 >= 0xD800 && c2 >= 0xD800) {
645
 
        UTF16FIXUP(c1);
646
 
        UTF16FIXUP(c2);
647
 
    }
648
 
 
649
 
    /* now c1 and c2 are in UTF-32-compatible order */
650
 
    return (int32_t)c1-(int32_t)c2;
651
 
}
652
 
 
653
 
U_CAPI UChar * U_EXPORT2
654
 
u_memchr(const UChar *src, UChar ch, int32_t count) {
655
 
    if(count > 0) {
656
 
        const UChar *ptr = src;
657
 
        const UChar *limit = src + count;
658
 
 
659
 
        do {
660
 
            if (*ptr == ch) {
661
 
                return (UChar *)ptr;
662
 
            }
663
 
        } while (++ptr < limit);
664
 
    }
665
 
    return NULL;
666
 
}
667
 
 
668
 
U_CAPI UChar * U_EXPORT2
669
 
u_memchr32(const UChar *src, UChar32 ch, int32_t count) {
670
 
    if(count<=0 || (uint32_t)ch>0x10ffff) {
671
 
        return NULL; /* no string, or illegal arguments */
672
 
    }
673
 
 
674
 
    if(ch<0xd800) {
675
 
        /* non-surrogate BMP code point */
676
 
        return u_memchr(src, (UChar)ch, count); /* BMP, single UChar */
677
 
    } else if(ch<=0xdfff) {
678
 
        /* surrogate code point */
679
 
        return (UChar *)uprv_strFindSurrogate(src, count, (UChar)ch);
680
 
    } else if(ch<=0xffff) {
681
 
        return u_memchr(src, (UChar)ch, count); /* BMP, single UChar */
682
 
    } else if(count<2) {
683
 
        return NULL; /* too short for a surrogate pair */
684
 
    } else {
685
 
        const UChar *limit=src+count-1; /* -1 so that we do not need a separate check for the trail unit */
686
 
        UChar lead=UTF16_LEAD(ch), trail=UTF16_TRAIL(ch);
687
 
 
688
 
        do {
689
 
            if(*src==lead && *(src+1)==trail) {
690
 
                return (UChar *)src;
691
 
            }
692
 
        } while(++src<limit);
693
 
        return NULL;
694
 
    }
695
 
}
696
 
 
697
 
/* conversions between char* and UChar* ------------------------------------- */
698
 
 
699
 
/*
700
 
 returns the minimum of (the length of the null-terminated string) and n.
701
 
*/
702
 
static int32_t u_astrnlen(const char *s1, int32_t n)
703
 
{
704
 
    int32_t len = 0;
705
 
 
706
 
    if (s1)
707
 
    {
708
 
        while (*(s1++) && n--)
709
 
        {
710
 
            len++;
711
 
        }
712
 
    }
713
 
    return len;
714
 
}
715
 
 
716
 
U_CAPI UChar*  U_EXPORT2
717
 
u_uastrncpy(UChar *ucs1,
718
 
           const char *s2,
719
 
           int32_t n)
720
 
{
721
 
  UChar *target = ucs1;
722
 
  UErrorCode err = U_ZERO_ERROR;
723
 
  UConverter *cnv = u_getDefaultConverter(&err);
724
 
  if(U_SUCCESS(err) && cnv != NULL) {
725
 
    ucnv_reset(cnv);
726
 
    ucnv_toUnicode(cnv,
727
 
                   &target,
728
 
                   ucs1+n,
729
 
                   &s2,
730
 
                   s2+u_astrnlen(s2, n),
731
 
                   NULL,
732
 
                   TRUE,
733
 
                   &err);
734
 
    ucnv_reset(cnv); /* be good citizens */
735
 
    u_releaseDefaultConverter(cnv);
736
 
    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
737
 
      *ucs1 = 0; /* failure */
738
 
    }
739
 
    if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
740
 
      *target = 0;  /* terminate */
741
 
    }
742
 
  } else {
743
 
    *ucs1 = 0;
744
 
  }
745
 
  return ucs1;
746
 
}
747
 
 
748
 
U_CAPI UChar*  U_EXPORT2
749
 
u_uastrcpy(UChar *ucs1,
750
 
          const char *s2 )
751
 
{
752
 
  UErrorCode err = U_ZERO_ERROR;
753
 
  UConverter *cnv = u_getDefaultConverter(&err);
754
 
  if(U_SUCCESS(err) && cnv != NULL) {
755
 
    ucnv_toUChars(cnv,
756
 
                    ucs1,
757
 
                    MAX_STRLEN,
758
 
                    s2,
759
 
                    uprv_strlen(s2),
760
 
                    &err);
761
 
    u_releaseDefaultConverter(cnv);
762
 
    if(U_FAILURE(err)) {
763
 
      *ucs1 = 0;
764
 
    }
765
 
  } else {
766
 
    *ucs1 = 0;
767
 
  }
768
 
  return ucs1;
769
 
}
770
 
 
771
 
/*
772
 
 returns the minimum of (the length of the null-terminated string) and n.
773
 
*/
774
 
static int32_t u_ustrnlen(const UChar *ucs1, int32_t n)
775
 
{
776
 
    int32_t len = 0;
777
 
 
778
 
    if (ucs1)
779
 
    {
780
 
        while (*(ucs1++) && n--)
781
 
        {
782
 
            len++;
783
 
        }
784
 
    }
785
 
    return len;
786
 
}
787
 
 
788
 
U_CAPI char*  U_EXPORT2
789
 
u_austrncpy(char *s1,
790
 
        const UChar *ucs2,
791
 
        int32_t n)
792
 
{
793
 
  char *target = s1;
794
 
  UErrorCode err = U_ZERO_ERROR;
795
 
  UConverter *cnv = u_getDefaultConverter(&err);
796
 
  if(U_SUCCESS(err) && cnv != NULL) {
797
 
    ucnv_reset(cnv);
798
 
    ucnv_fromUnicode(cnv,
799
 
                  &target,
800
 
                  s1+n,
801
 
                  &ucs2,
802
 
                  ucs2+u_ustrnlen(ucs2, n),
803
 
                  NULL,
804
 
                  TRUE,
805
 
                  &err);
806
 
    ucnv_reset(cnv); /* be good citizens */
807
 
    u_releaseDefaultConverter(cnv);
808
 
    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
809
 
      *s1 = 0; /* failure */
810
 
    }
811
 
    if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
812
 
      *target = 0;  /* terminate */
813
 
    }
814
 
  } else {
815
 
    *s1 = 0;
816
 
  }
817
 
  return s1;
818
 
}
819
 
 
820
 
U_CAPI char*  U_EXPORT2
821
 
u_austrcpy(char *s1,
822
 
         const UChar *ucs2 )
823
 
{
824
 
  UErrorCode err = U_ZERO_ERROR;
825
 
  UConverter *cnv = u_getDefaultConverter(&err);
826
 
  if(U_SUCCESS(err) && cnv != NULL) {
827
 
    int32_t len = ucnv_fromUChars(cnv,
828
 
                  s1,
829
 
                  MAX_STRLEN,
830
 
                  ucs2,
831
 
                  -1,
832
 
                  &err);
833
 
    u_releaseDefaultConverter(cnv);
834
 
    s1[len] = 0;
835
 
  } else {
836
 
    *s1 = 0;
837
 
  }
838
 
  return s1;
839
 
}
840
 
 
841
 
/* mutexed access to a shared default converter ----------------------------- */
842
 
 
843
 
UBool ustring_cleanup(void) {
844
 
    if (gDefaultConverter) {
845
 
        ucnv_close(gDefaultConverter);
846
 
        gDefaultConverter = NULL;
847
 
    }
848
 
    
849
 
    /* it's safe to close a 0 converter  */
850
 
    return TRUE;
851
 
}
852
 
 
853
 
U_CAPI UConverter* U_EXPORT2
854
 
u_getDefaultConverter(UErrorCode *status)
855
 
{
856
 
    UConverter *converter = NULL;
857
 
    
858
 
    if (gDefaultConverter != NULL) {
859
 
        umtx_lock(NULL);
860
 
        
861
 
        /* need to check to make sure it wasn't taken out from under us */
862
 
        if (gDefaultConverter != NULL) {
863
 
            converter = gDefaultConverter;
864
 
            gDefaultConverter = NULL;
865
 
        }
866
 
        umtx_unlock(NULL);
867
 
    }
868
 
 
869
 
    /* if the cache was empty, create a converter */
870
 
    if(converter == NULL) {
871
 
        converter = ucnv_open(NULL, status);
872
 
        if(U_FAILURE(*status)) {
873
 
            return NULL;
874
 
        }
875
 
    }
876
 
 
877
 
    return converter;
878
 
}
879
 
 
880
 
U_CAPI void U_EXPORT2
881
 
u_releaseDefaultConverter(UConverter *converter)
882
 
{
883
 
  if(gDefaultConverter == NULL) {
884
 
    if (converter != NULL) {
885
 
      ucnv_reset(converter);
886
 
    }
887
 
    umtx_lock(NULL);
888
 
 
889
 
    if(gDefaultConverter == NULL) {
890
 
      gDefaultConverter = converter;
891
 
      converter = NULL;
892
 
    }
893
 
    umtx_unlock(NULL);
894
 
  }
895
 
 
896
 
  if(converter != NULL) {
897
 
    ucnv_close(converter);
898
 
  }
899
 
}
900
 
 
901
 
/* u_unescape & support fns ------------------------------------------------- */
902
 
 
903
 
/* This map must be in ASCENDING ORDER OF THE ESCAPE CODE */
904
 
static const UChar UNESCAPE_MAP[] = {
905
 
    /*"   0x22, 0x22 */
906
 
    /*'   0x27, 0x27 */
907
 
    /*?   0x3F, 0x3F */
908
 
    /*\   0x5C, 0x5C */
909
 
    /*a*/ 0x61, 0x07,
910
 
    /*b*/ 0x62, 0x08,
911
 
    /*f*/ 0x66, 0x0c,
912
 
    /*n*/ 0x6E, 0x0a,
913
 
    /*r*/ 0x72, 0x0d,
914
 
    /*t*/ 0x74, 0x09,
915
 
    /*v*/ 0x76, 0x0b
916
 
};
917
 
enum { UNESCAPE_MAP_LENGTH = sizeof(UNESCAPE_MAP) / sizeof(UNESCAPE_MAP[0]) };
918
 
 
919
 
/* Convert one octal digit to a numeric value 0..7, or -1 on failure */
920
 
static int8_t _digit8(UChar c) {
921
 
    if (c >= 0x0030 && c <= 0x0037) {
922
 
        return (int8_t)(c - 0x0030);
923
 
    }
924
 
    return -1;
925
 
}
926
 
 
927
 
/* Convert one hex digit to a numeric value 0..F, or -1 on failure */
928
 
static int8_t _digit16(UChar c) {
929
 
    if (c >= 0x0030 && c <= 0x0039) {
930
 
        return (int8_t)(c - 0x0030);
931
 
    }
932
 
    if (c >= 0x0041 && c <= 0x0046) {
933
 
        return (int8_t)(c - (0x0041 - 10));
934
 
    }
935
 
    if (c >= 0x0061 && c <= 0x0066) {
936
 
        return (int8_t)(c - (0x0061 - 10));
937
 
    }
938
 
    return -1;
939
 
}
940
 
 
941
 
/* Parse a single escape sequence.  Although this method deals in
942
 
 * UChars, it does not use C++ or UnicodeString.  This allows it to
943
 
 * be used from C contexts. */
944
 
U_CAPI UChar32 U_EXPORT2
945
 
u_unescapeAt(UNESCAPE_CHAR_AT charAt,
946
 
             int32_t *offset,
947
 
             int32_t length,
948
 
             void *context) {
949
 
 
950
 
    int32_t start = *offset;
951
 
    UChar c;
952
 
    UChar32 result = 0;
953
 
    int8_t n = 0;
954
 
    int8_t minDig = 0;
955
 
    int8_t maxDig = 0;
956
 
    int8_t bitsPerDigit = 4; 
957
 
    int8_t dig;
958
 
    int32_t i;
959
 
 
960
 
    /* Check that offset is in range */
961
 
    if (*offset < 0 || *offset >= length) {
962
 
        goto err;
963
 
    }
964
 
 
965
 
    /* Fetch first UChar after '\\' */
966
 
    c = charAt((*offset)++, context);
967
 
 
968
 
    /* Convert hexadecimal and octal escapes */
969
 
    switch (c) {
970
 
    case 0x0075 /*'u'*/:
971
 
        minDig = maxDig = 4;
972
 
        break;
973
 
    case 0x0055 /*'U'*/:
974
 
        minDig = maxDig = 8;
975
 
        break;
976
 
    case 0x0078 /*'x'*/:
977
 
        minDig = 1;
978
 
        maxDig = 2;
979
 
        break;
980
 
    default:
981
 
        dig = _digit8(c);
982
 
        if (dig >= 0) {
983
 
            minDig = 1;
984
 
            maxDig = 3;
985
 
            n = 1; /* Already have first octal digit */
986
 
            bitsPerDigit = 3;
987
 
            result = dig;
988
 
        }
989
 
        break;
990
 
    }
991
 
    if (minDig != 0) {
992
 
        while (*offset < length && n < maxDig) {
993
 
            c = charAt(*offset, context);
994
 
            dig = (int8_t)((bitsPerDigit == 3) ? _digit8(c) : _digit16(c));
995
 
            if (dig < 0) {
996
 
                break;
997
 
            }
998
 
            result = (result << bitsPerDigit) | dig;
999
 
            ++(*offset);
1000
 
            ++n;
1001
 
        }
1002
 
        if (n < minDig) {
1003
 
            goto err;
1004
 
        }
1005
 
        return result;
1006
 
    }
1007
 
 
1008
 
    /* Convert C-style escapes in table */
1009
 
    for (i=0; i<UNESCAPE_MAP_LENGTH; i+=2) {
1010
 
        if (c == UNESCAPE_MAP[i]) {
1011
 
            return UNESCAPE_MAP[i+1];
1012
 
        } else if (c < UNESCAPE_MAP[i]) {
1013
 
            break;
1014
 
        }
1015
 
    }
1016
 
 
1017
 
    /* If no special forms are recognized, then consider
1018
 
     * the backslash to generically escape the next character.
1019
 
     * Deal with surrogate pairs. */
1020
 
    if (UTF_IS_FIRST_SURROGATE(c) && *offset < length) {
1021
 
        UChar c2 = charAt(*offset, context);
1022
 
        if (UTF_IS_SECOND_SURROGATE(c2)) {
1023
 
            ++(*offset);
1024
 
            return UTF16_GET_PAIR_VALUE(c, c2);
1025
 
        }
1026
 
    }
1027
 
    return c;
1028
 
 
1029
 
 err:
1030
 
    /* Invalid escape sequence */
1031
 
    *offset = start; /* Reset to initial value */
1032
 
    return (UChar32)0xFFFFFFFF;
1033
 
}
1034
 
 
1035
 
/* u_unescapeAt() callback to return a UChar from a char* */
1036
 
static UChar _charPtr_charAt(int32_t offset, void *context) {
1037
 
    UChar c16;
1038
 
    /* It would be more efficient to access the invariant tables
1039
 
     * directly but there is no API for that. */
1040
 
    u_charsToUChars(((char*) context) + offset, &c16, 1);
1041
 
    return c16;
1042
 
}
1043
 
 
1044
 
/* Append an escape-free segment of the text; used by u_unescape() */
1045
 
static void _appendUChars(UChar *dest, int32_t destCapacity,
1046
 
                          const char *src, int32_t srcLen) {
1047
 
    if (destCapacity < 0) {
1048
 
        destCapacity = 0;
1049
 
    }
1050
 
    if (srcLen > destCapacity) {
1051
 
        srcLen = destCapacity;
1052
 
    }
1053
 
    u_charsToUChars(src, dest, srcLen);
1054
 
}
1055
 
 
1056
 
/* Do an invariant conversion of char* -> UChar*, with escape parsing */
1057
 
U_CAPI int32_t U_EXPORT2
1058
 
u_unescape(const char *src, UChar *dest, int32_t destCapacity) {
1059
 
    const char *segment = src;
1060
 
    int32_t i = 0;
1061
 
    char c;
1062
 
 
1063
 
    while ((c=*src) != 0) {
1064
 
        /* '\\' intentionally written as compiler-specific
1065
 
         * character constant to correspond to compiler-specific
1066
 
         * char* constants. */
1067
 
        if (c == '\\') {
1068
 
            int32_t lenParsed = 0;
1069
 
            UChar32 c32;
1070
 
            if (src != segment) {
1071
 
                if (dest != NULL) {
1072
 
                    _appendUChars(dest + i, destCapacity - i,
1073
 
                                  segment, src - segment);
1074
 
                }
1075
 
                i += src - segment;
1076
 
            }
1077
 
            ++src; /* advance past '\\' */
1078
 
            c32 = u_unescapeAt(_charPtr_charAt, &lenParsed, uprv_strlen(src), (void*)src);
1079
 
            if (lenParsed == 0) {
1080
 
                goto err;
1081
 
            }
1082
 
            src += lenParsed; /* advance past escape seq. */
1083
 
            if (dest != NULL && UTF_CHAR_LENGTH(c32) <= (destCapacity - i)) {
1084
 
                UTF_APPEND_CHAR_UNSAFE(dest, i, c32);
1085
 
            } else {
1086
 
                i += UTF_CHAR_LENGTH(c32);
1087
 
            }
1088
 
            segment = src;
1089
 
        } else {
1090
 
            ++src;
1091
 
        }
1092
 
    }
1093
 
    if (src != segment) {
1094
 
        if (dest != NULL) {
1095
 
            _appendUChars(dest + i, destCapacity - i,
1096
 
                          segment, src - segment);
1097
 
        }
1098
 
        i += src - segment;
1099
 
    }
1100
 
    if (dest != NULL && i < destCapacity) {
1101
 
        dest[i] = 0;
1102
 
    }
1103
 
    return i + 1; /* add 1 for zero term */
1104
 
 
1105
 
 err:
1106
 
    if (dest != NULL && destCapacity > 0) {
1107
 
        *dest = 0;
1108
 
    }
1109
 
    return 0;
1110
 
}
1111
 
 
1112
 
/* C UGrowBuffer implementation --------------------------------------------- */
1113
 
 
1114
 
U_CAPI UBool /* U_CALLCONV U_EXPORT2 */
1115
 
u_growBufferFromStatic(void *context,
1116
 
                       UChar **pBuffer, int32_t *pCapacity, int32_t reqCapacity,
1117
 
                       int32_t length) {
1118
 
    UChar *newBuffer=(UChar *)uprv_malloc(reqCapacity*U_SIZEOF_UCHAR);
1119
 
    if(newBuffer!=NULL) {
1120
 
        if(length>0) {
1121
 
            uprv_memcpy(newBuffer, *pBuffer, length*U_SIZEOF_UCHAR);
1122
 
        }
1123
 
        *pCapacity=reqCapacity;
1124
 
    } else {
1125
 
        *pCapacity=0;
1126
 
    }
1127
 
 
1128
 
    /* release the old pBuffer if it was not statically allocated */
1129
 
    if(*pBuffer!=(UChar *)context) {
1130
 
        uprv_free(*pBuffer);
1131
 
    }
1132
 
 
1133
 
    *pBuffer=newBuffer;
1134
 
    return (UBool)(newBuffer!=NULL);
1135
 
}
1136
 
 
1137
 
/* NUL-termination of strings ----------------------------------------------- */
1138
 
 
1139
 
/**
1140
 
 * NUL-terminate a string no matter what its type.
1141
 
 * Set warning and error codes accordingly.
1142
 
 */
1143
 
#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode)      \
1144
 
    if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) {                    \
1145
 
        /* not a public function, so no complete argument checking */   \
1146
 
                                                                        \
1147
 
        if(length<0) {                                                  \
1148
 
            /* assume that the caller handles this */                   \
1149
 
        } else if(length<destCapacity) {                                \
1150
 
            /* NUL-terminate the string, the NUL fits */                \
1151
 
            dest[length]=0;                                             \
1152
 
            /* unset the not-terminated warning but leave all others */ \
1153
 
            if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {          \
1154
 
                *pErrorCode=U_ZERO_ERROR;                               \
1155
 
            }                                                           \
1156
 
        } else if(length==destCapacity) {                               \
1157
 
            /* unable to NUL-terminate, but the string itself fit - set a warning code */ \
1158
 
            *pErrorCode=U_STRING_NOT_TERMINATED_WARNING;                \
1159
 
        } else /* length>destCapacity */ {                              \
1160
 
            /* even the string itself did not fit - set an error code */ \
1161
 
            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;                        \
1162
 
        }                                                               \
1163
 
    }
1164
 
 
1165
 
U_CAPI int32_t U_EXPORT2
1166
 
u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1167
 
    __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1168
 
    return length;
1169
 
}
1170
 
 
1171
 
U_CAPI int32_t U_EXPORT2
1172
 
u_terminateChars(char *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1173
 
    __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1174
 
    return length;
1175
 
}
1176
 
 
1177
 
U_CAPI int32_t U_EXPORT2
1178
 
u_terminateUChar32s(UChar32 *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1179
 
    __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1180
 
    return length;
1181
 
}
1182
 
 
1183
 
U_CAPI int32_t U_EXPORT2
1184
 
u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1185
 
    __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1186
 
    return length;
1187
 
}