~ubuntu-branches/ubuntu/quantal/icu/quantal

« back to all changes in this revision

Viewing changes to source/common/ustring.c

  • Committer: Package Import Robot
  • Author(s): Yves Arrouye
  • Date: 2002-03-03 15:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20020303153113-3ssceqlq45xbmbnc
Tags: upstream-2.0-2.1pre20020303
ImportĀ upstreamĀ versionĀ 2.0-2.1pre20020303

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