]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/ustring.c
2 ******************************************************************************
4 * Copyright (C) 1998-2004, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 12/07/98 bertrand Creation.
15 ******************************************************************************
18 #include "unicode/utypes.h"
19 #include "unicode/putil.h"
20 #include "unicode/ustring.h"
26 /* ANSI string.h - style functions ------------------------------------------ */
28 /* U+ffff is the highest BMP code point, the highest one that fits into a 16-bit UChar */
29 #define U_BMP_MAX 0xffff
31 /* Forward binary string search functions ----------------------------------- */
34 * Test if a substring match inside a string is at code point boundaries.
35 * All pointers refer to the same buffer.
36 * The limit pointer may be NULL, all others must be real pointers.
39 isMatchAtCPBoundary(const UChar
*start
, const UChar
*match
, const UChar
*matchLimit
, const UChar
*limit
) {
40 if(U16_IS_TRAIL(*match
) && start
!=match
&& U16_IS_LEAD(*(match
-1))) {
41 /* the leading edge of the match is in the middle of a surrogate pair */
44 if(U16_IS_LEAD(*(matchLimit
-1)) && match
!=limit
&& U16_IS_TRAIL(*matchLimit
)) {
45 /* the trailing edge of the match is in the middle of a surrogate pair */
51 U_CAPI UChar
* U_EXPORT2
52 u_strFindFirst(const UChar
*s
, int32_t length
,
53 const UChar
*sub
, int32_t subLength
) {
54 const UChar
*start
, *p
, *q
, *subLimit
;
57 if(sub
==NULL
|| subLength
<-1) {
60 if(s
==NULL
|| length
<-1) {
66 if(length
<0 && subLength
<0) {
67 /* both strings are NUL-terminated */
71 if(*sub
==0 && !U16_IS_SURROGATE(cs
)) {
72 /* the substring consists of a single, non-surrogate BMP code point */
73 return u_strchr(s
, cs
);
78 /* found first substring UChar, compare rest */
83 if(isMatchAtCPBoundary(start
, s
-1, p
, NULL
)) {
84 return (UChar
*)(s
-1); /* well-formed match */
86 break; /* no match because surrogate pair is split */
90 return NULL
; /* no match, and none possible after s */
106 subLength
=u_strlen(sub
);
112 /* get sub[0] to search for it fast */
115 subLimit
=sub
+subLength
;
117 if(subLength
==0 && !U16_IS_SURROGATE(cs
)) {
118 /* the substring consists of a single, non-surrogate BMP code point */
119 return length
<0 ? u_strchr(s
, cs
) : u_memchr(s
, cs
, length
);
123 /* s is NUL-terminated */
126 /* found first substring UChar, compare rest */
131 if(isMatchAtCPBoundary(start
, s
-1, p
, NULL
)) {
132 return (UChar
*)(s
-1); /* well-formed match */
134 break; /* no match because surrogate pair is split */
138 return NULL
; /* no match, and none possible after s */
141 break; /* no match */
149 const UChar
*limit
, *preLimit
;
151 /* subLength was decremented above */
152 if(length
<=subLength
) {
153 return NULL
; /* s is shorter than sub */
158 /* the substring must start before preLimit */
159 preLimit
=limit
-subLength
;
164 /* found first substring UChar, compare rest */
169 if(isMatchAtCPBoundary(start
, s
-1, p
, limit
)) {
170 return (UChar
*)(s
-1); /* well-formed match */
172 break; /* no match because surrogate pair is split */
176 break; /* no match */
189 U_CAPI UChar
* U_EXPORT2
190 u_strstr(const UChar
*s
, const UChar
*substring
) {
191 return u_strFindFirst(s
, -1, substring
, -1);
194 U_CAPI UChar
* U_EXPORT2
195 u_strchr(const UChar
*s
, UChar c
) {
196 if(U16_IS_SURROGATE(c
)) {
197 /* make sure to not find half of a surrogate pair */
198 return u_strFindFirst(s
, -1, &c
, 1);
202 /* trivial search for a BMP code point */
215 U_CAPI UChar
* U_EXPORT2
216 u_strchr32(const UChar
*s
, UChar32 c
) {
217 if((uint32_t)c
<=U_BMP_MAX
) {
218 /* find BMP code point */
219 return u_strchr(s
, (UChar
)c
);
220 } else if((uint32_t)c
<=UCHAR_MAX_VALUE
) {
221 /* find supplementary code point as surrogate pair */
222 UChar cs
, lead
=U16_LEAD(c
), trail
=U16_TRAIL(c
);
224 while((cs
=*s
++)!=0) {
225 if(cs
==lead
&& *s
==trail
) {
226 return (UChar
*)(s
-1);
231 /* not a Unicode code point, not findable */
236 U_CAPI UChar
* U_EXPORT2
237 u_memchr(const UChar
*s
, UChar c
, int32_t count
) {
239 return NULL
; /* no string */
240 } else if(U16_IS_SURROGATE(c
)) {
241 /* make sure to not find half of a surrogate pair */
242 return u_strFindFirst(s
, count
, &c
, 1);
244 /* trivial search for a BMP code point */
245 const UChar
*limit
=s
+count
;
255 U_CAPI UChar
* U_EXPORT2
256 u_memchr32(const UChar
*s
, UChar32 c
, int32_t count
) {
257 if((uint32_t)c
<=U_BMP_MAX
) {
258 /* find BMP code point */
259 return u_memchr(s
, (UChar
)c
, count
);
261 /* too short for a surrogate pair */
263 } else if((uint32_t)c
<=UCHAR_MAX_VALUE
) {
264 /* find supplementary code point as surrogate pair */
265 const UChar
*limit
=s
+count
-1; /* -1 so that we do not need a separate check for the trail unit */
266 UChar lead
=U16_LEAD(c
), trail
=U16_TRAIL(c
);
269 if(*s
==lead
&& *(s
+1)==trail
) {
275 /* not a Unicode code point, not findable */
280 /* Backward binary string search functions ---------------------------------- */
282 U_CAPI UChar
* U_EXPORT2
283 u_strFindLast(const UChar
*s
, int32_t length
,
284 const UChar
*sub
, int32_t subLength
) {
285 const UChar
*start
, *limit
, *p
, *q
, *subLimit
;
288 if(sub
==NULL
|| subLength
<-1) {
291 if(s
==NULL
|| length
<-1) {
296 * This implementation is more lazy than the one for u_strFindFirst():
297 * There is no special search code for NUL-terminated strings.
298 * It does not seem to be worth it for searching substrings to
299 * search forward and find all matches like in u_strrchr() and similar.
300 * Therefore, we simply get both string lengths and search backward.
306 subLength
=u_strlen(sub
);
312 /* get sub[subLength-1] to search for it fast */
313 subLimit
=sub
+subLength
;
317 if(subLength
==0 && !U16_IS_SURROGATE(cs
)) {
318 /* the substring consists of a single, non-surrogate BMP code point */
319 return length
<0 ? u_strrchr(s
, cs
) : u_memrchr(s
, cs
, length
);
326 /* subLength was decremented above */
327 if(length
<=subLength
) {
328 return NULL
; /* s is shorter than sub */
334 /* the substring must start no later than s+subLength */
340 /* found last substring UChar, compare rest */
345 if(isMatchAtCPBoundary(start
, p
, limit
+1, start
+length
)) {
346 return (UChar
*)p
; /* well-formed match */
348 break; /* no match because surrogate pair is split */
352 break; /* no match */
362 U_CAPI UChar
* U_EXPORT2
363 u_strrstr(const UChar
*s
, const UChar
*substring
) {
364 return u_strFindLast(s
, -1, substring
, -1);
367 U_CAPI UChar
* U_EXPORT2
368 u_strrchr(const UChar
*s
, UChar c
) {
369 if(U16_IS_SURROGATE(c
)) {
370 /* make sure to not find half of a surrogate pair */
371 return u_strFindLast(s
, -1, &c
, 1);
373 const UChar
*result
=NULL
;
376 /* trivial search for a BMP code point */
382 return (UChar
*)result
;
389 U_CAPI UChar
* U_EXPORT2
390 u_strrchr32(const UChar
*s
, UChar32 c
) {
391 if((uint32_t)c
<=U_BMP_MAX
) {
392 /* find BMP code point */
393 return u_strrchr(s
, (UChar
)c
);
394 } else if((uint32_t)c
<=UCHAR_MAX_VALUE
) {
395 /* find supplementary code point as surrogate pair */
396 const UChar
*result
=NULL
;
397 UChar cs
, lead
=U16_LEAD(c
), trail
=U16_TRAIL(c
);
399 while((cs
=*s
++)!=0) {
400 if(cs
==lead
&& *s
==trail
) {
404 return (UChar
*)result
;
406 /* not a Unicode code point, not findable */
411 U_CAPI UChar
* U_EXPORT2
412 u_memrchr(const UChar
*s
, UChar c
, int32_t count
) {
414 return NULL
; /* no string */
415 } else if(U16_IS_SURROGATE(c
)) {
416 /* make sure to not find half of a surrogate pair */
417 return u_strFindLast(s
, count
, &c
, 1);
419 /* trivial search for a BMP code point */
420 const UChar
*limit
=s
+count
;
423 return (UChar
*)limit
;
430 U_CAPI UChar
* U_EXPORT2
431 u_memrchr32(const UChar
*s
, UChar32 c
, int32_t count
) {
432 if((uint32_t)c
<=U_BMP_MAX
) {
433 /* find BMP code point */
434 return u_memrchr(s
, (UChar
)c
, count
);
436 /* too short for a surrogate pair */
438 } else if((uint32_t)c
<=UCHAR_MAX_VALUE
) {
439 /* find supplementary code point as surrogate pair */
440 const UChar
*limit
=s
+count
-1;
441 UChar lead
=U16_LEAD(c
), trail
=U16_TRAIL(c
);
444 if(*limit
==trail
&& *(limit
-1)==lead
) {
445 return (UChar
*)(limit
-1);
450 /* not a Unicode code point, not findable */
455 /* Tokenization functions --------------------------------------------------- */
458 * Match each code point in a string against each code point in the matchSet.
459 * Return the index of the first string code point that
460 * is (polarity==TRUE) or is not (FALSE) contained in the matchSet.
461 * Return -(string length)-1 if there is no such code point.
464 _matchFromSet(const UChar
*string
, const UChar
*matchSet
, UBool polarity
) {
465 int32_t matchLen
, matchBMPLen
, strItr
, matchItr
;
466 UChar32 stringCh
, matchCh
;
469 /* first part of matchSet contains only BMP code points */
471 while((c
= matchSet
[matchBMPLen
]) != 0 && U16_IS_SINGLE(c
)) {
475 /* second part of matchSet contains BMP and supplementary code points */
476 matchLen
= matchBMPLen
;
477 while(matchSet
[matchLen
] != 0) {
481 for(strItr
= 0; (c
= string
[strItr
]) != 0;) {
483 if(U16_IS_SINGLE(c
)) {
485 for(matchItr
= 0; matchItr
< matchLen
; ++matchItr
) {
486 if(c
== matchSet
[matchItr
]) {
487 return strItr
- 1; /* one matches */
491 for(matchItr
= 0; matchItr
< matchLen
; ++matchItr
) {
492 if(c
== matchSet
[matchItr
]) {
496 return strItr
- 1; /* none matches */
500 * No need to check for string length before U16_IS_TRAIL
501 * because c2 could at worst be the terminating NUL.
503 if(U16_IS_SURROGATE_LEAD(c
) && U16_IS_TRAIL(c2
= string
[strItr
])) {
505 stringCh
= U16_GET_SUPPLEMENTARY(c
, c2
);
507 stringCh
= c
; /* unpaired trail surrogate */
511 for(matchItr
= matchBMPLen
; matchItr
< matchLen
;) {
512 U16_NEXT(matchSet
, matchItr
, matchLen
, matchCh
);
513 if(stringCh
== matchCh
) {
514 return strItr
- U16_LENGTH(stringCh
); /* one matches */
518 for(matchItr
= matchBMPLen
; matchItr
< matchLen
;) {
519 U16_NEXT(matchSet
, matchItr
, matchLen
, matchCh
);
520 if(stringCh
== matchCh
) {
524 return strItr
- U16_LENGTH(stringCh
); /* none matches */
528 /* wish C had continue with labels like Java... */;
531 /* Didn't find it. */
535 /* Search for a codepoint in a string that matches one of the matchSet codepoints. */
536 U_CAPI UChar
* U_EXPORT2
537 u_strpbrk(const UChar
*string
, const UChar
*matchSet
)
539 int32_t index
= _matchFromSet(string
, matchSet
, TRUE
);
541 return (UChar
*)string
+ index
;
547 /* Search for a codepoint in a string that matches one of the matchSet codepoints. */
548 U_CAPI
int32_t U_EXPORT2
549 u_strcspn(const UChar
*string
, const UChar
*matchSet
)
551 int32_t index
= _matchFromSet(string
, matchSet
, TRUE
);
555 return -index
- 1; /* == u_strlen(string) */
559 /* Search for a codepoint in a string that does not match one of the matchSet codepoints. */
560 U_CAPI
int32_t U_EXPORT2
561 u_strspn(const UChar
*string
, const UChar
*matchSet
)
563 int32_t index
= _matchFromSet(string
, matchSet
, FALSE
);
567 return -index
- 1; /* == u_strlen(string) */
571 /* ----- Text manipulation functions --- */
573 U_CAPI UChar
* U_EXPORT2
574 u_strtok_r(UChar
*src
,
580 uint32_t nonDelimIdx
;
582 /* If saveState is NULL, the user messed up. */
585 *saveState
= src
; /* Set to "src" in case there are no delimiters */
587 else if (*saveState
) {
588 tokSource
= *saveState
;
591 /* src == NULL && *saveState == NULL */
592 /* This shouldn't happen. We already finished tokenizing. */
596 /* Skip initial delimiters */
597 nonDelimIdx
= u_strspn(tokSource
, delim
);
598 tokSource
= &tokSource
[nonDelimIdx
];
601 nextToken
= u_strpbrk(tokSource
, delim
);
602 if (nextToken
!= NULL
) {
605 *saveState
= nextToken
;
608 else if (*saveState
) {
609 /* Return the last token */
615 /* No tokens were found. Only delimiters were left. */
621 /* Miscellaneous functions -------------------------------------------------- */
623 U_CAPI UChar
* U_EXPORT2
627 UChar
*anchor
= dst
; /* save a pointer to start of dst */
629 while(*dst
!= 0) { /* To end of first string */
632 while((*(dst
++) = *(src
++)) != 0) { /* copy string 2 over */
638 U_CAPI UChar
* U_EXPORT2
639 u_strncat(UChar
*dst
,
644 UChar
*anchor
= dst
; /* save a pointer to start of dst */
646 while(*dst
!= 0) { /* To end of first string */
649 while((*dst
= *src
) != 0) { /* copy string 2 over */
664 /* ----- Text property functions --- */
666 U_CAPI
int32_t U_EXPORT2
667 u_strcmp(const UChar
*s1
,
675 if (c1
!= c2
|| c1
== 0) {
679 return (int32_t)c1
- (int32_t)c2
;
682 U_CAPI
int32_t U_EXPORT2
683 uprv_strCompare(const UChar
*s1
, int32_t length1
,
684 const UChar
*s2
, int32_t length2
,
685 UBool strncmpStyle
, UBool codePointOrder
) {
686 const UChar
*start1
, *start2
, *limit1
, *limit2
;
689 /* setup for fix-up */
693 /* compare identical prefixes - they do not need to be fixed up */
694 if(length1
<0 && length2
<0) {
695 /* strcmp style, both NUL-terminated */
713 /* setup for fix-up */
715 } else if(strncmpStyle
) {
716 /* special handling for strncmp, assume length1==length2>=0 but also check for NUL */
721 limit1
=start1
+length1
;
724 /* both lengths are same, check only one limit */
741 /* setup for fix-up */
742 limit2
=start2
+length1
; /* use length1 here, too, to enforce assumption */
744 /* memcmp/UnicodeString style, both length-specified */
745 int32_t lengthResult
;
748 length1
=u_strlen(s1
);
751 length2
=u_strlen(s2
);
754 /* limit1=start1+min(lenght1, length2) */
755 if(length1
<length2
) {
757 limit1
=start1
+length1
;
758 } else if(length1
==length2
) {
760 limit1
=start1
+length1
;
761 } else /* length1>length2 */ {
763 limit1
=start1
+length2
;
771 /* check pseudo-limit */
785 /* setup for fix-up */
786 limit1
=start1
+length1
;
787 limit2
=start2
+length2
;
790 /* if both values are in or above the surrogate range, fix them up */
791 if(c1
>=0xd800 && c2
>=0xd800 && codePointOrder
) {
792 /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
794 (c1
<=0xdbff && (s1
+1)!=limit1
&& UTF_IS_TRAIL(*(s1
+1))) ||
795 (UTF_IS_TRAIL(c1
) && start1
!=s1
&& UTF_IS_LEAD(*(s1
-1)))
797 /* part of a surrogate pair, leave >=d800 */
799 /* BMP code point - may be surrogate code point - make <d800 */
804 (c2
<=0xdbff && (s2
+1)!=limit2
&& UTF_IS_TRAIL(*(s2
+1))) ||
805 (UTF_IS_TRAIL(c2
) && start2
!=s2
&& UTF_IS_LEAD(*(s2
-1)))
807 /* part of a surrogate pair, leave >=d800 */
809 /* BMP code point - may be surrogate code point - make <d800 */
814 /* now c1 and c2 are in the requested (code unit or code point) order */
815 return (int32_t)c1
-(int32_t)c2
;
819 * Compare two strings as presented by UCharIterators.
820 * Use code unit or code point order.
821 * When the function returns, it is undefined where the iterators
824 U_CAPI
int32_t U_EXPORT2
825 u_strCompareIter(UCharIterator
*iter1
, UCharIterator
*iter2
, UBool codePointOrder
) {
828 /* argument checking */
829 if(iter1
==NULL
|| iter2
==NULL
) {
830 return 0; /* bad arguments */
833 return 0; /* identical iterators */
836 /* reset iterators to start? */
837 iter1
->move(iter1
, 0, UITER_START
);
838 iter2
->move(iter2
, 0, UITER_START
);
840 /* compare identical prefixes - they do not need to be fixed up */
842 c1
=iter1
->next(iter1
);
843 c2
=iter2
->next(iter2
);
852 /* if both values are in or above the surrogate range, fix them up */
853 if(c1
>=0xd800 && c2
>=0xd800 && codePointOrder
) {
854 /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
856 (c1
<=0xdbff && UTF_IS_TRAIL(iter1
->current(iter1
))) ||
857 (UTF_IS_TRAIL(c1
) && (iter1
->previous(iter1
), UTF_IS_LEAD(iter1
->previous(iter1
))))
859 /* part of a surrogate pair, leave >=d800 */
861 /* BMP code point - may be surrogate code point - make <d800 */
866 (c2
<=0xdbff && UTF_IS_TRAIL(iter2
->current(iter2
))) ||
867 (UTF_IS_TRAIL(c2
) && (iter2
->previous(iter2
), UTF_IS_LEAD(iter2
->previous(iter2
))))
869 /* part of a surrogate pair, leave >=d800 */
871 /* BMP code point - may be surrogate code point - make <d800 */
876 /* now c1 and c2 are in the requested (code unit or code point) order */
877 return (int32_t)c1
-(int32_t)c2
;
882 * u_strCompareIter() does not leave the iterators _on_ the different units.
883 * This is possible but would cost a few extra indirect function calls to back
884 * up if the last unit (c1 or c2 respectively) was >=0.
886 * Consistently leaving them _behind_ the different units is not an option
887 * because the current "unit" is the end of the string if that is reached,
888 * and in such a case the iterator does not move.
889 * For example, when comparing "ab" with "abc", both iterators rest _on_ the end
890 * of their strings. Calling previous() on each does not move them to where
891 * the comparison fails.
893 * So the simplest semantics is to not define where the iterators end up.
895 * The following fragment is part of what would need to be done for backing up.
898 /* iff a surrogate is part of a surrogate pair, leave >=d800 */
900 if(!UTF_IS_TRAIL(iter1
->current(iter1
))) {
901 /* lead surrogate code point - make <d800 */
904 } else if(c1
<=0xdfff) {
905 int32_t index
=iter1
->getIndex(iter1
, UITER_CURRENT
);
906 iter1
->previous(iter1
); /* ==c1 */
907 if(!UTF_IS_LEAD(iter1
->previous(iter1
))) {
908 /* trail surrogate code point - make <d800 */
911 /* go back to behind where the difference is */
912 iter1
->move(iter1
, index
, UITER_ZERO
);
913 } else /* 0xe000<=c1<=0xffff */ {
914 /* BMP code point - make <d800 */
920 U_CAPI
int32_t U_EXPORT2
921 u_strCompare(const UChar
*s1
, int32_t length1
,
922 const UChar
*s2
, int32_t length2
,
923 UBool codePointOrder
) {
924 /* argument checking */
925 if(s1
==NULL
|| length1
<-1 || s2
==NULL
|| length2
<-1) {
928 return uprv_strCompare(s1
, length1
, s2
, length2
, FALSE
, codePointOrder
);
931 /* String compare in code point order - u_strcmp() compares in code unit order. */
932 U_CAPI
int32_t U_EXPORT2
933 u_strcmpCodePointOrder(const UChar
*s1
, const UChar
*s2
) {
934 return uprv_strCompare(s1
, -1, s2
, -1, FALSE
, TRUE
);
937 U_CAPI
int32_t U_EXPORT2
938 u_strncmp(const UChar
*s1
,
945 rc
= (int32_t)*s1
- (int32_t)*s2
;
946 if(rc
!= 0 || *s1
== 0 || --n
== 0) {
957 U_CAPI
int32_t U_EXPORT2
958 u_strncmpCodePointOrder(const UChar
*s1
, const UChar
*s2
, int32_t n
) {
959 return uprv_strCompare(s1
, n
, s2
, n
, TRUE
, TRUE
);
962 U_CAPI UChar
* U_EXPORT2
966 UChar
*anchor
= dst
; /* save a pointer to start of dst */
968 while((*(dst
++) = *(src
++)) != 0) { /* copy string 2 over */
974 U_CAPI UChar
* U_EXPORT2
975 u_strncpy(UChar
*dst
,
979 UChar
*anchor
= dst
; /* save a pointer to start of dst */
981 /* copy string 2 over */
982 while(n
> 0 && (*(dst
++) = *(src
++)) != 0) {
989 U_CAPI
int32_t U_EXPORT2
990 u_strlen(const UChar
*s
)
992 #if U_SIZEOF_WCHAR_T == U_SIZEOF_UCHAR
993 return uprv_wcslen(s
);
1003 U_CAPI
int32_t U_EXPORT2
1004 u_countChar32(const UChar
*s
, int32_t length
) {
1007 if(s
==NULL
|| length
<-1) {
1015 if(UTF_IS_LEAD(*s
) && length
>=2 && UTF_IS_TRAIL(*(s
+1))) {
1023 } else /* length==-1 */ {
1033 * sufficient to look ahead one because of UTF-16;
1034 * safe to look ahead one because at worst that would be the terminating NUL
1036 if(UTF_IS_LEAD(c
) && UTF_IS_TRAIL(*s
)) {
1044 U_CAPI UBool U_EXPORT2
1045 u_strHasMoreChar32Than(const UChar
*s
, int32_t length
, int32_t number
) {
1050 if(s
==NULL
|| length
<-1) {
1055 /* s is NUL-terminated */
1058 /* count code points until they exceed */
1066 if(U16_IS_LEAD(c
) && U16_IS_TRAIL(*s
)) {
1072 /* length>=0 known */
1074 int32_t maxSupplementary
;
1076 /* s contains at least (length+1)/2 code points: <=2 UChars per cp */
1077 if(((length
+1)/2)>number
) {
1081 /* check if s does not even contain enough UChars */
1082 maxSupplementary
=length
-number
;
1083 if(maxSupplementary
<=0) {
1086 /* there are maxSupplementary=length-number more UChars than asked-for code points */
1089 * count code points until they exceed and also check that there are
1090 * no more than maxSupplementary supplementary code points (UChar pairs)
1100 if(U16_IS_LEAD(*s
++) && s
!=limit
&& U16_IS_TRAIL(*s
)) {
1102 if(--maxSupplementary
<=0) {
1103 /* too many pairs - too few code points */
1112 U_CAPI UChar
* U_EXPORT2
1113 u_memcpy(UChar
*dest
, const UChar
*src
, int32_t count
) {
1114 return (UChar
*)uprv_memcpy(dest
, src
, count
*U_SIZEOF_UCHAR
);
1117 U_CAPI UChar
* U_EXPORT2
1118 u_memmove(UChar
*dest
, const UChar
*src
, int32_t count
) {
1119 return (UChar
*)uprv_memmove(dest
, src
, count
*U_SIZEOF_UCHAR
);
1122 U_CAPI UChar
* U_EXPORT2
1123 u_memset(UChar
*dest
, UChar c
, int32_t count
) {
1126 UChar
*limit
= dest
+ count
;
1128 while (ptr
< limit
) {
1135 U_CAPI
int32_t U_EXPORT2
1136 u_memcmp(const UChar
*buf1
, const UChar
*buf2
, int32_t count
) {
1138 const UChar
*limit
= buf1
+ count
;
1141 while (buf1
< limit
) {
1142 result
= (int32_t)(uint16_t)*buf1
- (int32_t)(uint16_t)*buf2
;
1153 U_CAPI
int32_t U_EXPORT2
1154 u_memcmpCodePointOrder(const UChar
*s1
, const UChar
*s2
, int32_t count
) {
1155 return uprv_strCompare(s1
, count
, s2
, count
, FALSE
, TRUE
);
1158 /* u_unescape & support fns ------------------------------------------------- */
1160 /* This map must be in ASCENDING ORDER OF THE ESCAPE CODE */
1161 static const UChar UNESCAPE_MAP
[] = {
1175 enum { UNESCAPE_MAP_LENGTH
= sizeof(UNESCAPE_MAP
) / sizeof(UNESCAPE_MAP
[0]) };
1177 /* Convert one octal digit to a numeric value 0..7, or -1 on failure */
1178 static int8_t _digit8(UChar c
) {
1179 if (c
>= 0x0030 && c
<= 0x0037) {
1180 return (int8_t)(c
- 0x0030);
1185 /* Convert one hex digit to a numeric value 0..F, or -1 on failure */
1186 static int8_t _digit16(UChar c
) {
1187 if (c
>= 0x0030 && c
<= 0x0039) {
1188 return (int8_t)(c
- 0x0030);
1190 if (c
>= 0x0041 && c
<= 0x0046) {
1191 return (int8_t)(c
- (0x0041 - 10));
1193 if (c
>= 0x0061 && c
<= 0x0066) {
1194 return (int8_t)(c
- (0x0061 - 10));
1199 /* Parse a single escape sequence. Although this method deals in
1200 * UChars, it does not use C++ or UnicodeString. This allows it to
1201 * be used from C contexts. */
1202 U_CAPI UChar32 U_EXPORT2
1203 u_unescapeAt(UNESCAPE_CHAR_AT charAt
,
1208 int32_t start
= *offset
;
1214 int8_t bitsPerDigit
= 4;
1217 UBool braces
= FALSE
;
1219 /* Check that offset is in range */
1220 if (*offset
< 0 || *offset
>= length
) {
1224 /* Fetch first UChar after '\\' */
1225 c
= charAt((*offset
)++, context
);
1227 /* Convert hexadecimal and octal escapes */
1229 case 0x0075 /*'u'*/:
1230 minDig
= maxDig
= 4;
1232 case 0x0055 /*'U'*/:
1233 minDig
= maxDig
= 8;
1235 case 0x0078 /*'x'*/:
1237 if (*offset
< length
&& charAt(*offset
, context
) == 0x7B /*{*/) {
1250 n
= 1; /* Already have first octal digit */
1257 while (*offset
< length
&& n
< maxDig
) {
1258 c
= charAt(*offset
, context
);
1259 dig
= (int8_t)((bitsPerDigit
== 3) ? _digit8(c
) : _digit16(c
));
1263 result
= (result
<< bitsPerDigit
) | dig
;
1271 if (c
!= 0x7D /*}*/) {
1276 if (result
< 0 || result
>= 0x110000) {
1279 /* If an escape sequence specifies a lead surrogate, see if
1280 * there is a trail surrogate after it, either as an escape or
1281 * as a literal. If so, join them up into a supplementary.
1283 if (*offset
< length
&& U16_IS_LEAD(result
)) {
1284 int32_t ahead
= *offset
+ 1;
1285 c
= charAt(*offset
, context
);
1286 if (c
== 0x5C /*'\\'*/ && ahead
< length
) {
1287 c
= (UChar
) u_unescapeAt(charAt
, &ahead
, length
, context
);
1289 if (U16_IS_TRAIL(c
)) {
1291 result
= U16_GET_SUPPLEMENTARY(result
, c
);
1297 /* Convert C-style escapes in table */
1298 for (i
=0; i
<UNESCAPE_MAP_LENGTH
; i
+=2) {
1299 if (c
== UNESCAPE_MAP
[i
]) {
1300 return UNESCAPE_MAP
[i
+1];
1301 } else if (c
< UNESCAPE_MAP
[i
]) {
1306 /* Map \cX to control-X: X & 0x1F */
1307 if (c
== 0x0063 /*'c'*/ && *offset
< length
) {
1308 c
= charAt((*offset
)++, context
);
1309 if (UTF_IS_FIRST_SURROGATE(c
) && *offset
< length
) {
1310 UChar c2
= charAt(*offset
, context
);
1311 if (UTF_IS_SECOND_SURROGATE(c2
)) {
1313 c
= (UChar
) UTF16_GET_PAIR_VALUE(c
, c2
); /* [sic] */
1319 /* If no special forms are recognized, then consider
1320 * the backslash to generically escape the next character.
1321 * Deal with surrogate pairs. */
1322 if (UTF_IS_FIRST_SURROGATE(c
) && *offset
< length
) {
1323 UChar c2
= charAt(*offset
, context
);
1324 if (UTF_IS_SECOND_SURROGATE(c2
)) {
1326 return UTF16_GET_PAIR_VALUE(c
, c2
);
1332 /* Invalid escape sequence */
1333 *offset
= start
; /* Reset to initial value */
1334 return (UChar32
)0xFFFFFFFF;
1337 /* u_unescapeAt() callback to return a UChar from a char* */
1338 static UChar U_CALLCONV
1339 _charPtr_charAt(int32_t offset
, void *context
) {
1341 /* It would be more efficient to access the invariant tables
1342 * directly but there is no API for that. */
1343 u_charsToUChars(((char*) context
) + offset
, &c16
, 1);
1347 /* Append an escape-free segment of the text; used by u_unescape() */
1348 static void _appendUChars(UChar
*dest
, int32_t destCapacity
,
1349 const char *src
, int32_t srcLen
) {
1350 if (destCapacity
< 0) {
1353 if (srcLen
> destCapacity
) {
1354 srcLen
= destCapacity
;
1356 u_charsToUChars(src
, dest
, srcLen
);
1359 /* Do an invariant conversion of char* -> UChar*, with escape parsing */
1360 U_CAPI
int32_t U_EXPORT2
1361 u_unescape(const char *src
, UChar
*dest
, int32_t destCapacity
) {
1362 const char *segment
= src
;
1366 while ((c
=*src
) != 0) {
1367 /* '\\' intentionally written as compiler-specific
1368 * character constant to correspond to compiler-specific
1369 * char* constants. */
1371 int32_t lenParsed
= 0;
1373 if (src
!= segment
) {
1375 _appendUChars(dest
+ i
, destCapacity
- i
,
1376 segment
, src
- segment
);
1380 ++src
; /* advance past '\\' */
1381 c32
= u_unescapeAt(_charPtr_charAt
, &lenParsed
, uprv_strlen(src
), (void*)src
);
1382 if (lenParsed
== 0) {
1385 src
+= lenParsed
; /* advance past escape seq. */
1386 if (dest
!= NULL
&& UTF_CHAR_LENGTH(c32
) <= (destCapacity
- i
)) {
1387 UTF_APPEND_CHAR_UNSAFE(dest
, i
, c32
);
1389 i
+= UTF_CHAR_LENGTH(c32
);
1396 if (src
!= segment
) {
1398 _appendUChars(dest
+ i
, destCapacity
- i
,
1399 segment
, src
- segment
);
1403 if (dest
!= NULL
&& i
< destCapacity
) {
1409 if (dest
!= NULL
&& destCapacity
> 0) {
1415 /* C UGrowBuffer implementation --------------------------------------------- */
1417 U_CAPI UBool
/* U_CALLCONV U_EXPORT2 */
1418 u_growBufferFromStatic(void *context
,
1419 UChar
**pBuffer
, int32_t *pCapacity
, int32_t reqCapacity
,
1421 UChar
*newBuffer
=(UChar
*)uprv_malloc(reqCapacity
*U_SIZEOF_UCHAR
);
1422 if(newBuffer
!=NULL
) {
1424 uprv_memcpy(newBuffer
, *pBuffer
, length
*U_SIZEOF_UCHAR
);
1426 *pCapacity
=reqCapacity
;
1431 /* release the old pBuffer if it was not statically allocated */
1432 if(*pBuffer
!=(UChar
*)context
) {
1433 uprv_free(*pBuffer
);
1437 return (UBool
)(newBuffer
!=NULL
);
1440 /* NUL-termination of strings ----------------------------------------------- */
1443 * NUL-terminate a string no matter what its type.
1444 * Set warning and error codes accordingly.
1446 #define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) \
1447 if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) { \
1448 /* not a public function, so no complete argument checking */ \
1451 /* assume that the caller handles this */ \
1452 } else if(length<destCapacity) { \
1453 /* NUL-terminate the string, the NUL fits */ \
1455 /* unset the not-terminated warning but leave all others */ \
1456 if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) { \
1457 *pErrorCode=U_ZERO_ERROR; \
1459 } else if(length==destCapacity) { \
1460 /* unable to NUL-terminate, but the string itself fit - set a warning code */ \
1461 *pErrorCode=U_STRING_NOT_TERMINATED_WARNING; \
1462 } else /* length>destCapacity */ { \
1463 /* even the string itself did not fit - set an error code */ \
1464 *pErrorCode=U_BUFFER_OVERFLOW_ERROR; \
1468 U_CAPI
int32_t U_EXPORT2
1469 u_terminateUChars(UChar
*dest
, int32_t destCapacity
, int32_t length
, UErrorCode
*pErrorCode
) {
1470 __TERMINATE_STRING(dest
, destCapacity
, length
, pErrorCode
);
1474 U_CAPI
int32_t U_EXPORT2
1475 u_terminateChars(char *dest
, int32_t destCapacity
, int32_t length
, UErrorCode
*pErrorCode
) {
1476 __TERMINATE_STRING(dest
, destCapacity
, length
, pErrorCode
);
1480 U_CAPI
int32_t U_EXPORT2
1481 u_terminateUChar32s(UChar32
*dest
, int32_t destCapacity
, int32_t length
, UErrorCode
*pErrorCode
) {
1482 __TERMINATE_STRING(dest
, destCapacity
, length
, pErrorCode
);
1486 U_CAPI
int32_t U_EXPORT2
1487 u_terminateWChars(wchar_t *dest
, int32_t destCapacity
, int32_t length
, UErrorCode
*pErrorCode
) {
1488 __TERMINATE_STRING(dest
, destCapacity
, length
, pErrorCode
);