1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *
6 * Copyright (C) 1998-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
8 *
9 ******************************************************************************
10 *
11 * File ustring.cpp
12 *
13 * Modification History:
14 *
15 * Date Name Description
16 * 12/07/98 bertrand Creation.
17 ******************************************************************************
18 */
19
20 #include "unicode/utypes.h"
21 #include "unicode/putil.h"
22 #include "unicode/uchar.h"
23 #include "unicode/ustring.h"
24 #include "unicode/utf16.h"
25 #include "cstring.h"
26 #include "cwchar.h"
27 #include "cmemory.h"
28 #include "ustr_imp.h"
29
30 /* ANSI string.h - style functions ------------------------------------------ */
31
32 /* U+ffff is the highest BMP code point, the highest one that fits into a 16-bit UChar */
33 #define U_BMP_MAX 0xffff
34
35 /* Forward binary string search functions ----------------------------------- */
36
37 /*
38 * Test if a substring match inside a string is at code point boundaries.
39 * All pointers refer to the same buffer.
40 * The limit pointer may be NULL, all others must be real pointers.
41 */
42 static inline UBool
isMatchAtCPBoundary(const UChar * start,const UChar * match,const UChar * matchLimit,const UChar * limit)43 isMatchAtCPBoundary(const UChar *start, const UChar *match, const UChar *matchLimit, const UChar *limit) {
44 if(U16_IS_TRAIL(*match) && start!=match && U16_IS_LEAD(*(match-1))) {
45 /* the leading edge of the match is in the middle of a surrogate pair */
46 return FALSE;
47 }
48 if(U16_IS_LEAD(*(matchLimit-1)) && match!=limit && U16_IS_TRAIL(*matchLimit)) {
49 /* the trailing edge of the match is in the middle of a surrogate pair */
50 return FALSE;
51 }
52 return TRUE;
53 }
54
55 U_CAPI UChar * U_EXPORT2
u_strFindFirst(const UChar * s,int32_t length,const UChar * sub,int32_t subLength)56 u_strFindFirst(const UChar *s, int32_t length,
57 const UChar *sub, int32_t subLength) {
58 const UChar *start, *p, *q, *subLimit;
59 UChar c, cs, cq;
60
61 if(sub==NULL || subLength<-1) {
62 return (UChar *)s;
63 }
64 if(s==NULL || length<-1) {
65 return NULL;
66 }
67
68 start=s;
69
70 if(length<0 && subLength<0) {
71 /* both strings are NUL-terminated */
72 if((cs=*sub++)==0) {
73 return (UChar *)s;
74 }
75 if(*sub==0 && !U16_IS_SURROGATE(cs)) {
76 /* the substring consists of a single, non-surrogate BMP code point */
77 return u_strchr(s, cs);
78 }
79
80 while((c=*s++)!=0) {
81 if(c==cs) {
82 /* found first substring UChar, compare rest */
83 p=s;
84 q=sub;
85 for(;;) {
86 if((cq=*q)==0) {
87 if(isMatchAtCPBoundary(start, s-1, p, NULL)) {
88 return (UChar *)(s-1); /* well-formed match */
89 } else {
90 break; /* no match because surrogate pair is split */
91 }
92 }
93 if((c=*p)==0) {
94 return NULL; /* no match, and none possible after s */
95 }
96 if(c!=cq) {
97 break; /* no match */
98 }
99 ++p;
100 ++q;
101 }
102 }
103 }
104
105 /* not found */
106 return NULL;
107 }
108
109 if(subLength<0) {
110 subLength=u_strlen(sub);
111 }
112 if(subLength==0) {
113 return (UChar *)s;
114 }
115
116 /* get sub[0] to search for it fast */
117 cs=*sub++;
118 --subLength;
119 subLimit=sub+subLength;
120
121 if(subLength==0 && !U16_IS_SURROGATE(cs)) {
122 /* the substring consists of a single, non-surrogate BMP code point */
123 return length<0 ? u_strchr(s, cs) : u_memchr(s, cs, length);
124 }
125
126 if(length<0) {
127 /* s is NUL-terminated */
128 while((c=*s++)!=0) {
129 if(c==cs) {
130 /* found first substring UChar, compare rest */
131 p=s;
132 q=sub;
133 for(;;) {
134 if(q==subLimit) {
135 if(isMatchAtCPBoundary(start, s-1, p, NULL)) {
136 return (UChar *)(s-1); /* well-formed match */
137 } else {
138 break; /* no match because surrogate pair is split */
139 }
140 }
141 if((c=*p)==0) {
142 return NULL; /* no match, and none possible after s */
143 }
144 if(c!=*q) {
145 break; /* no match */
146 }
147 ++p;
148 ++q;
149 }
150 }
151 }
152 } else {
153 const UChar *limit, *preLimit;
154
155 /* subLength was decremented above */
156 if(length<=subLength) {
157 return NULL; /* s is shorter than sub */
158 }
159
160 limit=s+length;
161
162 /* the substring must start before preLimit */
163 preLimit=limit-subLength;
164
165 while(s!=preLimit) {
166 c=*s++;
167 if(c==cs) {
168 /* found first substring UChar, compare rest */
169 p=s;
170 q=sub;
171 for(;;) {
172 if(q==subLimit) {
173 if(isMatchAtCPBoundary(start, s-1, p, limit)) {
174 return (UChar *)(s-1); /* well-formed match */
175 } else {
176 break; /* no match because surrogate pair is split */
177 }
178 }
179 if(*p!=*q) {
180 break; /* no match */
181 }
182 ++p;
183 ++q;
184 }
185 }
186 }
187 }
188
189 /* not found */
190 return NULL;
191 }
192
193 U_CAPI UChar * U_EXPORT2
u_strstr(const UChar * s,const UChar * substring)194 u_strstr(const UChar *s, const UChar *substring) {
195 return u_strFindFirst(s, -1, substring, -1);
196 }
197
198 U_CAPI UChar * U_EXPORT2
u_strchr(const UChar * s,UChar c)199 u_strchr(const UChar *s, UChar c) {
200 if(U16_IS_SURROGATE(c)) {
201 /* make sure to not find half of a surrogate pair */
202 return u_strFindFirst(s, -1, &c, 1);
203 } else {
204 UChar cs;
205
206 /* trivial search for a BMP code point */
207 for(;;) {
208 if((cs=*s)==c) {
209 return (UChar *)s;
210 }
211 if(cs==0) {
212 return NULL;
213 }
214 ++s;
215 }
216 }
217 }
218
219 U_CAPI UChar * U_EXPORT2
u_strchr32(const UChar * s,UChar32 c)220 u_strchr32(const UChar *s, UChar32 c) {
221 if((uint32_t)c<=U_BMP_MAX) {
222 /* find BMP code point */
223 return u_strchr(s, (UChar)c);
224 } else if((uint32_t)c<=UCHAR_MAX_VALUE) {
225 /* find supplementary code point as surrogate pair */
226 UChar cs, lead=U16_LEAD(c), trail=U16_TRAIL(c);
227
228 while((cs=*s++)!=0) {
229 if(cs==lead && *s==trail) {
230 return (UChar *)(s-1);
231 }
232 }
233 return NULL;
234 } else {
235 /* not a Unicode code point, not findable */
236 return NULL;
237 }
238 }
239
240 U_CAPI UChar * U_EXPORT2
u_memchr(const UChar * s,UChar c,int32_t count)241 u_memchr(const UChar *s, UChar c, int32_t count) {
242 if(count<=0) {
243 return NULL; /* no string */
244 } else if(U16_IS_SURROGATE(c)) {
245 /* make sure to not find half of a surrogate pair */
246 return u_strFindFirst(s, count, &c, 1);
247 } else {
248 /* trivial search for a BMP code point */
249 const UChar *limit=s+count;
250 do {
251 if(*s==c) {
252 return (UChar *)s;
253 }
254 } while(++s!=limit);
255 return NULL;
256 }
257 }
258
259 U_CAPI UChar * U_EXPORT2
u_memchr32(const UChar * s,UChar32 c,int32_t count)260 u_memchr32(const UChar *s, UChar32 c, int32_t count) {
261 if((uint32_t)c<=U_BMP_MAX) {
262 /* find BMP code point */
263 return u_memchr(s, (UChar)c, count);
264 } else if(count<2) {
265 /* too short for a surrogate pair */
266 return NULL;
267 } else if((uint32_t)c<=UCHAR_MAX_VALUE) {
268 /* find supplementary code point as surrogate pair */
269 const UChar *limit=s+count-1; /* -1 so that we do not need a separate check for the trail unit */
270 UChar lead=U16_LEAD(c), trail=U16_TRAIL(c);
271
272 do {
273 if(*s==lead && *(s+1)==trail) {
274 return (UChar *)s;
275 }
276 } while(++s!=limit);
277 return NULL;
278 } else {
279 /* not a Unicode code point, not findable */
280 return NULL;
281 }
282 }
283
284 /* Backward binary string search functions ---------------------------------- */
285
286 U_CAPI UChar * U_EXPORT2
u_strFindLast(const UChar * s,int32_t length,const UChar * sub,int32_t subLength)287 u_strFindLast(const UChar *s, int32_t length,
288 const UChar *sub, int32_t subLength) {
289 const UChar *start, *limit, *p, *q, *subLimit;
290 UChar c, cs;
291
292 if(sub==NULL || subLength<-1) {
293 return (UChar *)s;
294 }
295 if(s==NULL || length<-1) {
296 return NULL;
297 }
298
299 /*
300 * This implementation is more lazy than the one for u_strFindFirst():
301 * There is no special search code for NUL-terminated strings.
302 * It does not seem to be worth it for searching substrings to
303 * search forward and find all matches like in u_strrchr() and similar.
304 * Therefore, we simply get both string lengths and search backward.
305 *
306 * markus 2002oct23
307 */
308
309 if(subLength<0) {
310 subLength=u_strlen(sub);
311 }
312 if(subLength==0) {
313 return (UChar *)s;
314 }
315
316 /* get sub[subLength-1] to search for it fast */
317 subLimit=sub+subLength;
318 cs=*(--subLimit);
319 --subLength;
320
321 if(subLength==0 && !U16_IS_SURROGATE(cs)) {
322 /* the substring consists of a single, non-surrogate BMP code point */
323 return length<0 ? u_strrchr(s, cs) : u_memrchr(s, cs, length);
324 }
325
326 if(length<0) {
327 length=u_strlen(s);
328 }
329
330 /* subLength was decremented above */
331 if(length<=subLength) {
332 return NULL; /* s is shorter than sub */
333 }
334
335 start=s;
336 limit=s+length;
337
338 /* the substring must start no later than s+subLength */
339 s+=subLength;
340
341 while(s!=limit) {
342 c=*(--limit);
343 if(c==cs) {
344 /* found last substring UChar, compare rest */
345 p=limit;
346 q=subLimit;
347 for(;;) {
348 if(q==sub) {
349 if(isMatchAtCPBoundary(start, p, limit+1, start+length)) {
350 return (UChar *)p; /* well-formed match */
351 } else {
352 break; /* no match because surrogate pair is split */
353 }
354 }
355 if(*(--p)!=*(--q)) {
356 break; /* no match */
357 }
358 }
359 }
360 }
361
362 /* not found */
363 return NULL;
364 }
365
366 U_CAPI UChar * U_EXPORT2
u_strrstr(const UChar * s,const UChar * substring)367 u_strrstr(const UChar *s, const UChar *substring) {
368 return u_strFindLast(s, -1, substring, -1);
369 }
370
371 U_CAPI UChar * U_EXPORT2
u_strrchr(const UChar * s,UChar c)372 u_strrchr(const UChar *s, UChar c) {
373 if(U16_IS_SURROGATE(c)) {
374 /* make sure to not find half of a surrogate pair */
375 return u_strFindLast(s, -1, &c, 1);
376 } else {
377 const UChar *result=NULL;
378 UChar cs;
379
380 /* trivial search for a BMP code point */
381 for(;;) {
382 if((cs=*s)==c) {
383 result=s;
384 }
385 if(cs==0) {
386 return (UChar *)result;
387 }
388 ++s;
389 }
390 }
391 }
392
393 U_CAPI UChar * U_EXPORT2
u_strrchr32(const UChar * s,UChar32 c)394 u_strrchr32(const UChar *s, UChar32 c) {
395 if((uint32_t)c<=U_BMP_MAX) {
396 /* find BMP code point */
397 return u_strrchr(s, (UChar)c);
398 } else if((uint32_t)c<=UCHAR_MAX_VALUE) {
399 /* find supplementary code point as surrogate pair */
400 const UChar *result=NULL;
401 UChar cs, lead=U16_LEAD(c), trail=U16_TRAIL(c);
402
403 while((cs=*s++)!=0) {
404 if(cs==lead && *s==trail) {
405 result=s-1;
406 }
407 }
408 return (UChar *)result;
409 } else {
410 /* not a Unicode code point, not findable */
411 return NULL;
412 }
413 }
414
415 U_CAPI UChar * U_EXPORT2
u_memrchr(const UChar * s,UChar c,int32_t count)416 u_memrchr(const UChar *s, UChar c, int32_t count) {
417 if(count<=0) {
418 return NULL; /* no string */
419 } else if(U16_IS_SURROGATE(c)) {
420 /* make sure to not find half of a surrogate pair */
421 return u_strFindLast(s, count, &c, 1);
422 } else {
423 /* trivial search for a BMP code point */
424 const UChar *limit=s+count;
425 do {
426 if(*(--limit)==c) {
427 return (UChar *)limit;
428 }
429 } while(s!=limit);
430 return NULL;
431 }
432 }
433
434 U_CAPI UChar * U_EXPORT2
u_memrchr32(const UChar * s,UChar32 c,int32_t count)435 u_memrchr32(const UChar *s, UChar32 c, int32_t count) {
436 if((uint32_t)c<=U_BMP_MAX) {
437 /* find BMP code point */
438 return u_memrchr(s, (UChar)c, count);
439 } else if(count<2) {
440 /* too short for a surrogate pair */
441 return NULL;
442 } else if((uint32_t)c<=UCHAR_MAX_VALUE) {
443 /* find supplementary code point as surrogate pair */
444 const UChar *limit=s+count-1;
445 UChar lead=U16_LEAD(c), trail=U16_TRAIL(c);
446
447 do {
448 if(*limit==trail && *(limit-1)==lead) {
449 return (UChar *)(limit-1);
450 }
451 } while(s!=--limit);
452 return NULL;
453 } else {
454 /* not a Unicode code point, not findable */
455 return NULL;
456 }
457 }
458
459 /* Tokenization functions --------------------------------------------------- */
460
461 /*
462 * Match each code point in a string against each code point in the matchSet.
463 * Return the index of the first string code point that
464 * is (polarity==TRUE) or is not (FALSE) contained in the matchSet.
465 * Return -(string length)-1 if there is no such code point.
466 */
467 static int32_t
_matchFromSet(const UChar * string,const UChar * matchSet,UBool polarity)468 _matchFromSet(const UChar *string, const UChar *matchSet, UBool polarity) {
469 int32_t matchLen, matchBMPLen, strItr, matchItr;
470 UChar32 stringCh, matchCh;
471 UChar c, c2;
472
473 /* first part of matchSet contains only BMP code points */
474 matchBMPLen = 0;
475 while((c = matchSet[matchBMPLen]) != 0 && U16_IS_SINGLE(c)) {
476 ++matchBMPLen;
477 }
478
479 /* second part of matchSet contains BMP and supplementary code points */
480 matchLen = matchBMPLen;
481 while(matchSet[matchLen] != 0) {
482 ++matchLen;
483 }
484
485 for(strItr = 0; (c = string[strItr]) != 0;) {
486 ++strItr;
487 if(U16_IS_SINGLE(c)) {
488 if(polarity) {
489 for(matchItr = 0; matchItr < matchLen; ++matchItr) {
490 if(c == matchSet[matchItr]) {
491 return strItr - 1; /* one matches */
492 }
493 }
494 } else {
495 for(matchItr = 0; matchItr < matchLen; ++matchItr) {
496 if(c == matchSet[matchItr]) {
497 goto endloop;
498 }
499 }
500 return strItr - 1; /* none matches */
501 }
502 } else {
503 /*
504 * No need to check for string length before U16_IS_TRAIL
505 * because c2 could at worst be the terminating NUL.
506 */
507 if(U16_IS_SURROGATE_LEAD(c) && U16_IS_TRAIL(c2 = string[strItr])) {
508 ++strItr;
509 stringCh = U16_GET_SUPPLEMENTARY(c, c2);
510 } else {
511 stringCh = c; /* unpaired trail surrogate */
512 }
513
514 if(polarity) {
515 for(matchItr = matchBMPLen; matchItr < matchLen;) {
516 U16_NEXT(matchSet, matchItr, matchLen, matchCh);
517 if(stringCh == matchCh) {
518 return strItr - U16_LENGTH(stringCh); /* one matches */
519 }
520 }
521 } else {
522 for(matchItr = matchBMPLen; matchItr < matchLen;) {
523 U16_NEXT(matchSet, matchItr, matchLen, matchCh);
524 if(stringCh == matchCh) {
525 goto endloop;
526 }
527 }
528 return strItr - U16_LENGTH(stringCh); /* none matches */
529 }
530 }
531 endloop:
532 /* wish C had continue with labels like Java... */;
533 }
534
535 /* Didn't find it. */
536 return -strItr-1;
537 }
538
539 /* Search for a codepoint in a string that matches one of the matchSet codepoints. */
540 U_CAPI UChar * U_EXPORT2
u_strpbrk(const UChar * string,const UChar * matchSet)541 u_strpbrk(const UChar *string, const UChar *matchSet)
542 {
543 int32_t idx = _matchFromSet(string, matchSet, TRUE);
544 if(idx >= 0) {
545 return (UChar *)string + idx;
546 } else {
547 return NULL;
548 }
549 }
550
551 /* Search for a codepoint in a string that matches one of the matchSet codepoints. */
552 U_CAPI int32_t U_EXPORT2
u_strcspn(const UChar * string,const UChar * matchSet)553 u_strcspn(const UChar *string, const UChar *matchSet)
554 {
555 int32_t idx = _matchFromSet(string, matchSet, TRUE);
556 if(idx >= 0) {
557 return idx;
558 } else {
559 return -idx - 1; /* == u_strlen(string) */
560 }
561 }
562
563 /* Search for a codepoint in a string that does not match one of the matchSet codepoints. */
564 U_CAPI int32_t U_EXPORT2
u_strspn(const UChar * string,const UChar * matchSet)565 u_strspn(const UChar *string, const UChar *matchSet)
566 {
567 int32_t idx = _matchFromSet(string, matchSet, FALSE);
568 if(idx >= 0) {
569 return idx;
570 } else {
571 return -idx - 1; /* == u_strlen(string) */
572 }
573 }
574
575 /* ----- Text manipulation functions --- */
576
577 U_CAPI UChar* U_EXPORT2
u_strtok_r(UChar * src,const UChar * delim,UChar ** saveState)578 u_strtok_r(UChar *src,
579 const UChar *delim,
580 UChar **saveState)
581 {
582 UChar *tokSource;
583 UChar *nextToken;
584 uint32_t nonDelimIdx;
585
586 /* If saveState is NULL, the user messed up. */
587 if (src != NULL) {
588 tokSource = src;
589 *saveState = src; /* Set to "src" in case there are no delimiters */
590 }
591 else if (*saveState) {
592 tokSource = *saveState;
593 }
594 else {
595 /* src == NULL && *saveState == NULL */
596 /* This shouldn't happen. We already finished tokenizing. */
597 return NULL;
598 }
599
600 /* Skip initial delimiters */
601 nonDelimIdx = u_strspn(tokSource, delim);
602 tokSource = &tokSource[nonDelimIdx];
603
604 if (*tokSource) {
605 nextToken = u_strpbrk(tokSource, delim);
606 if (nextToken != NULL) {
607 /* Create a token */
608 *(nextToken++) = 0;
609 *saveState = nextToken;
610 return tokSource;
611 }
612 else if (*saveState) {
613 /* Return the last token */
614 *saveState = NULL;
615 return tokSource;
616 }
617 }
618 else {
619 /* No tokens were found. Only delimiters were left. */
620 *saveState = NULL;
621 }
622 return NULL;
623 }
624
625 /* Miscellaneous functions -------------------------------------------------- */
626
627 U_CAPI UChar* U_EXPORT2
u_strcat(UChar * dst,const UChar * src)628 u_strcat(UChar *dst,
629 const UChar *src)
630 {
631 UChar *anchor = dst; /* save a pointer to start of dst */
632
633 while(*dst != 0) { /* To end of first string */
634 ++dst;
635 }
636 while((*(dst++) = *(src++)) != 0) { /* copy string 2 over */
637 }
638
639 return anchor;
640 }
641
642 U_CAPI UChar* U_EXPORT2
u_strncat(UChar * dst,const UChar * src,int32_t n)643 u_strncat(UChar *dst,
644 const UChar *src,
645 int32_t n )
646 {
647 if(n > 0) {
648 UChar *anchor = dst; /* save a pointer to start of dst */
649
650 while(*dst != 0) { /* To end of first string */
651 ++dst;
652 }
653 while((*dst = *src) != 0) { /* copy string 2 over */
654 ++dst;
655 if(--n == 0) {
656 *dst = 0;
657 break;
658 }
659 ++src;
660 }
661
662 return anchor;
663 } else {
664 return dst;
665 }
666 }
667
668 /* ----- Text property functions --- */
669
670 U_CAPI int32_t U_EXPORT2
u_strcmp(const UChar * s1,const UChar * s2)671 u_strcmp(const UChar *s1,
672 const UChar *s2)
673 {
674 UChar c1, c2;
675
676 for(;;) {
677 c1=*s1++;
678 c2=*s2++;
679 if (c1 != c2 || c1 == 0) {
680 break;
681 }
682 }
683 return (int32_t)c1 - (int32_t)c2;
684 }
685
686 U_CFUNC int32_t U_EXPORT2
uprv_strCompare(const UChar * s1,int32_t length1,const UChar * s2,int32_t length2,UBool strncmpStyle,UBool codePointOrder)687 uprv_strCompare(const UChar *s1, int32_t length1,
688 const UChar *s2, int32_t length2,
689 UBool strncmpStyle, UBool codePointOrder) {
690 const UChar *start1, *start2, *limit1, *limit2;
691 UChar c1, c2;
692
693 /* setup for fix-up */
694 start1=s1;
695 start2=s2;
696
697 /* compare identical prefixes - they do not need to be fixed up */
698 if(length1<0 && length2<0) {
699 /* strcmp style, both NUL-terminated */
700 if(s1==s2) {
701 return 0;
702 }
703
704 for(;;) {
705 c1=*s1;
706 c2=*s2;
707 if(c1!=c2) {
708 break;
709 }
710 if(c1==0) {
711 return 0;
712 }
713 ++s1;
714 ++s2;
715 }
716
717 /* setup for fix-up */
718 limit1=limit2=NULL;
719 } else if(strncmpStyle) {
720 /* special handling for strncmp, assume length1==length2>=0 but also check for NUL */
721 if(s1==s2) {
722 return 0;
723 }
724
725 limit1=start1+length1;
726
727 for(;;) {
728 /* both lengths are same, check only one limit */
729 if(s1==limit1) {
730 return 0;
731 }
732
733 c1=*s1;
734 c2=*s2;
735 if(c1!=c2) {
736 break;
737 }
738 if(c1==0) {
739 return 0;
740 }
741 ++s1;
742 ++s2;
743 }
744
745 /* setup for fix-up */
746 limit2=start2+length1; /* use length1 here, too, to enforce assumption */
747 } else {
748 /* memcmp/UnicodeString style, both length-specified */
749 int32_t lengthResult;
750
751 if(length1<0) {
752 length1=u_strlen(s1);
753 }
754 if(length2<0) {
755 length2=u_strlen(s2);
756 }
757
758 /* limit1=start1+min(lenght1, length2) */
759 if(length1<length2) {
760 lengthResult=-1;
761 limit1=start1+length1;
762 } else if(length1==length2) {
763 lengthResult=0;
764 limit1=start1+length1;
765 } else /* length1>length2 */ {
766 lengthResult=1;
767 limit1=start1+length2;
768 }
769
770 if(s1==s2) {
771 return lengthResult;
772 }
773
774 for(;;) {
775 /* check pseudo-limit */
776 if(s1==limit1) {
777 return lengthResult;
778 }
779
780 c1=*s1;
781 c2=*s2;
782 if(c1!=c2) {
783 break;
784 }
785 ++s1;
786 ++s2;
787 }
788
789 /* setup for fix-up */
790 limit1=start1+length1;
791 limit2=start2+length2;
792 }
793
794 /* if both values are in or above the surrogate range, fix them up */
795 if(c1>=0xd800 && c2>=0xd800 && codePointOrder) {
796 /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
797 if(
798 (c1<=0xdbff && (s1+1)!=limit1 && U16_IS_TRAIL(*(s1+1))) ||
799 (U16_IS_TRAIL(c1) && start1!=s1 && U16_IS_LEAD(*(s1-1)))
800 ) {
801 /* part of a surrogate pair, leave >=d800 */
802 } else {
803 /* BMP code point - may be surrogate code point - make <d800 */
804 c1-=0x2800;
805 }
806
807 if(
808 (c2<=0xdbff && (s2+1)!=limit2 && U16_IS_TRAIL(*(s2+1))) ||
809 (U16_IS_TRAIL(c2) && start2!=s2 && U16_IS_LEAD(*(s2-1)))
810 ) {
811 /* part of a surrogate pair, leave >=d800 */
812 } else {
813 /* BMP code point - may be surrogate code point - make <d800 */
814 c2-=0x2800;
815 }
816 }
817
818 /* now c1 and c2 are in the requested (code unit or code point) order */
819 return (int32_t)c1-(int32_t)c2;
820 }
821
822 /*
823 * Compare two strings as presented by UCharIterators.
824 * Use code unit or code point order.
825 * When the function returns, it is undefined where the iterators
826 * have stopped.
827 */
828 U_CAPI int32_t U_EXPORT2
u_strCompareIter(UCharIterator * iter1,UCharIterator * iter2,UBool codePointOrder)829 u_strCompareIter(UCharIterator *iter1, UCharIterator *iter2, UBool codePointOrder) {
830 UChar32 c1, c2;
831
832 /* argument checking */
833 if(iter1==NULL || iter2==NULL) {
834 return 0; /* bad arguments */
835 }
836 if(iter1==iter2) {
837 return 0; /* identical iterators */
838 }
839
840 /* reset iterators to start? */
841 iter1->move(iter1, 0, UITER_START);
842 iter2->move(iter2, 0, UITER_START);
843
844 /* compare identical prefixes - they do not need to be fixed up */
845 for(;;) {
846 c1=iter1->next(iter1);
847 c2=iter2->next(iter2);
848 if(c1!=c2) {
849 break;
850 }
851 if(c1==-1) {
852 return 0;
853 }
854 }
855
856 /* if both values are in or above the surrogate range, fix them up */
857 if(c1>=0xd800 && c2>=0xd800 && codePointOrder) {
858 /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
859 if(
860 (c1<=0xdbff && U16_IS_TRAIL(iter1->current(iter1))) ||
861 (U16_IS_TRAIL(c1) && (iter1->previous(iter1), U16_IS_LEAD(iter1->previous(iter1))))
862 ) {
863 /* part of a surrogate pair, leave >=d800 */
864 } else {
865 /* BMP code point - may be surrogate code point - make <d800 */
866 c1-=0x2800;
867 }
868
869 if(
870 (c2<=0xdbff && U16_IS_TRAIL(iter2->current(iter2))) ||
871 (U16_IS_TRAIL(c2) && (iter2->previous(iter2), U16_IS_LEAD(iter2->previous(iter2))))
872 ) {
873 /* part of a surrogate pair, leave >=d800 */
874 } else {
875 /* BMP code point - may be surrogate code point - make <d800 */
876 c2-=0x2800;
877 }
878 }
879
880 /* now c1 and c2 are in the requested (code unit or code point) order */
881 return (int32_t)c1-(int32_t)c2;
882 }
883
884 #if 0
885 /*
886 * u_strCompareIter() does not leave the iterators _on_ the different units.
887 * This is possible but would cost a few extra indirect function calls to back
888 * up if the last unit (c1 or c2 respectively) was >=0.
889 *
890 * Consistently leaving them _behind_ the different units is not an option
891 * because the current "unit" is the end of the string if that is reached,
892 * and in such a case the iterator does not move.
893 * For example, when comparing "ab" with "abc", both iterators rest _on_ the end
894 * of their strings. Calling previous() on each does not move them to where
895 * the comparison fails.
896 *
897 * So the simplest semantics is to not define where the iterators end up.
898 *
899 * The following fragment is part of what would need to be done for backing up.
900 */
901 void fragment {
902 /* iff a surrogate is part of a surrogate pair, leave >=d800 */
903 if(c1<=0xdbff) {
904 if(!U16_IS_TRAIL(iter1->current(iter1))) {
905 /* lead surrogate code point - make <d800 */
906 c1-=0x2800;
907 }
908 } else if(c1<=0xdfff) {
909 int32_t idx=iter1->getIndex(iter1, UITER_CURRENT);
910 iter1->previous(iter1); /* ==c1 */
911 if(!U16_IS_LEAD(iter1->previous(iter1))) {
912 /* trail surrogate code point - make <d800 */
913 c1-=0x2800;
914 }
915 /* go back to behind where the difference is */
916 iter1->move(iter1, idx, UITER_ZERO);
917 } else /* 0xe000<=c1<=0xffff */ {
918 /* BMP code point - make <d800 */
919 c1-=0x2800;
920 }
921 }
922 #endif
923
924 U_CAPI int32_t U_EXPORT2
u_strCompare(const UChar * s1,int32_t length1,const UChar * s2,int32_t length2,UBool codePointOrder)925 u_strCompare(const UChar *s1, int32_t length1,
926 const UChar *s2, int32_t length2,
927 UBool codePointOrder) {
928 /* argument checking */
929 if(s1==NULL || length1<-1 || s2==NULL || length2<-1) {
930 return 0;
931 }
932 return uprv_strCompare(s1, length1, s2, length2, FALSE, codePointOrder);
933 }
934
935 /* String compare in code point order - u_strcmp() compares in code unit order. */
936 U_CAPI int32_t U_EXPORT2
u_strcmpCodePointOrder(const UChar * s1,const UChar * s2)937 u_strcmpCodePointOrder(const UChar *s1, const UChar *s2) {
938 return uprv_strCompare(s1, -1, s2, -1, FALSE, TRUE);
939 }
940
941 U_CAPI int32_t U_EXPORT2
u_strncmp(const UChar * s1,const UChar * s2,int32_t n)942 u_strncmp(const UChar *s1,
943 const UChar *s2,
944 int32_t n)
945 {
946 if(n > 0) {
947 int32_t rc;
948 for(;;) {
949 rc = (int32_t)*s1 - (int32_t)*s2;
950 if(rc != 0 || *s1 == 0 || --n == 0) {
951 return rc;
952 }
953 ++s1;
954 ++s2;
955 }
956 } else {
957 return 0;
958 }
959 }
960
961 U_CAPI int32_t U_EXPORT2
u_strncmpCodePointOrder(const UChar * s1,const UChar * s2,int32_t n)962 u_strncmpCodePointOrder(const UChar *s1, const UChar *s2, int32_t n) {
963 return uprv_strCompare(s1, n, s2, n, TRUE, TRUE);
964 }
965
966 U_CAPI UChar* U_EXPORT2
u_strcpy(UChar * dst,const UChar * src)967 u_strcpy(UChar *dst,
968 const UChar *src)
969 {
970 UChar *anchor = dst; /* save a pointer to start of dst */
971
972 while((*(dst++) = *(src++)) != 0) { /* copy string 2 over */
973 }
974
975 return anchor;
976 }
977
978 U_CAPI UChar* U_EXPORT2
u_strncpy(UChar * dst,const UChar * src,int32_t n)979 u_strncpy(UChar *dst,
980 const UChar *src,
981 int32_t n)
982 {
983 UChar *anchor = dst; /* save a pointer to start of dst */
984
985 /* copy string 2 over */
986 while(n > 0 && (*(dst++) = *(src++)) != 0) {
987 --n;
988 }
989
990 return anchor;
991 }
992
993 U_CAPI int32_t U_EXPORT2
u_strlen(const UChar * s)994 u_strlen(const UChar *s)
995 {
996 #if U_SIZEOF_WCHAR_T == U_SIZEOF_UCHAR
997 return (int32_t)uprv_wcslen((const wchar_t *)s);
998 #else
999 const UChar *t = s;
1000 while(*t != 0) {
1001 ++t;
1002 }
1003 return t - s;
1004 #endif
1005 }
1006
1007 U_CAPI int32_t U_EXPORT2
u_countChar32(const UChar * s,int32_t length)1008 u_countChar32(const UChar *s, int32_t length) {
1009 int32_t count;
1010
1011 if(s==NULL || length<-1) {
1012 return 0;
1013 }
1014
1015 count=0;
1016 if(length>=0) {
1017 while(length>0) {
1018 ++count;
1019 if(U16_IS_LEAD(*s) && length>=2 && U16_IS_TRAIL(*(s+1))) {
1020 s+=2;
1021 length-=2;
1022 } else {
1023 ++s;
1024 --length;
1025 }
1026 }
1027 } else /* length==-1 */ {
1028 UChar c;
1029
1030 for(;;) {
1031 if((c=*s++)==0) {
1032 break;
1033 }
1034 ++count;
1035
1036 /*
1037 * sufficient to look ahead one because of UTF-16;
1038 * safe to look ahead one because at worst that would be the terminating NUL
1039 */
1040 if(U16_IS_LEAD(c) && U16_IS_TRAIL(*s)) {
1041 ++s;
1042 }
1043 }
1044 }
1045 return count;
1046 }
1047
1048 U_CAPI UBool U_EXPORT2
u_strHasMoreChar32Than(const UChar * s,int32_t length,int32_t number)1049 u_strHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) {
1050
1051 if(number<0) {
1052 return TRUE;
1053 }
1054 if(s==NULL || length<-1) {
1055 return FALSE;
1056 }
1057
1058 if(length==-1) {
1059 /* s is NUL-terminated */
1060 UChar c;
1061
1062 /* count code points until they exceed */
1063 for(;;) {
1064 if((c=*s++)==0) {
1065 return FALSE;
1066 }
1067 if(number==0) {
1068 return TRUE;
1069 }
1070 if(U16_IS_LEAD(c) && U16_IS_TRAIL(*s)) {
1071 ++s;
1072 }
1073 --number;
1074 }
1075 } else {
1076 /* length>=0 known */
1077 const UChar *limit;
1078 int32_t maxSupplementary;
1079
1080 /* s contains at least (length+1)/2 code points: <=2 UChars per cp */
1081 if(((length+1)/2)>number) {
1082 return TRUE;
1083 }
1084
1085 /* check if s does not even contain enough UChars */
1086 maxSupplementary=length-number;
1087 if(maxSupplementary<=0) {
1088 return FALSE;
1089 }
1090 /* there are maxSupplementary=length-number more UChars than asked-for code points */
1091
1092 /*
1093 * count code points until they exceed and also check that there are
1094 * no more than maxSupplementary supplementary code points (UChar pairs)
1095 */
1096 limit=s+length;
1097 for(;;) {
1098 if(s==limit) {
1099 return FALSE;
1100 }
1101 if(number==0) {
1102 return TRUE;
1103 }
1104 if(U16_IS_LEAD(*s++) && s!=limit && U16_IS_TRAIL(*s)) {
1105 ++s;
1106 if(--maxSupplementary<=0) {
1107 /* too many pairs - too few code points */
1108 return FALSE;
1109 }
1110 }
1111 --number;
1112 }
1113 }
1114 }
1115
1116 U_CAPI UChar * U_EXPORT2
u_memcpy(UChar * dest,const UChar * src,int32_t count)1117 u_memcpy(UChar *dest, const UChar *src, int32_t count) {
1118 if(count > 0) {
1119 uprv_memcpy(dest, src, (size_t)count*U_SIZEOF_UCHAR);
1120 }
1121 return dest;
1122 }
1123
1124 U_CAPI UChar * U_EXPORT2
u_memmove(UChar * dest,const UChar * src,int32_t count)1125 u_memmove(UChar *dest, const UChar *src, int32_t count) {
1126 if(count > 0) {
1127 uprv_memmove(dest, src, (size_t)count*U_SIZEOF_UCHAR);
1128 }
1129 return dest;
1130 }
1131
1132 U_CAPI UChar * U_EXPORT2
u_memset(UChar * dest,UChar c,int32_t count)1133 u_memset(UChar *dest, UChar c, int32_t count) {
1134 if(count > 0) {
1135 UChar *ptr = dest;
1136 UChar *limit = dest + count;
1137
1138 while (ptr < limit) {
1139 *(ptr++) = c;
1140 }
1141 }
1142 return dest;
1143 }
1144
1145 U_CAPI int32_t U_EXPORT2
u_memcmp(const UChar * buf1,const UChar * buf2,int32_t count)1146 u_memcmp(const UChar *buf1, const UChar *buf2, int32_t count) {
1147 if(count > 0) {
1148 const UChar *limit = buf1 + count;
1149 int32_t result;
1150
1151 while (buf1 < limit) {
1152 result = (int32_t)(uint16_t)*buf1 - (int32_t)(uint16_t)*buf2;
1153 if (result != 0) {
1154 return result;
1155 }
1156 buf1++;
1157 buf2++;
1158 }
1159 }
1160 return 0;
1161 }
1162
1163 U_CAPI int32_t U_EXPORT2
u_memcmpCodePointOrder(const UChar * s1,const UChar * s2,int32_t count)1164 u_memcmpCodePointOrder(const UChar *s1, const UChar *s2, int32_t count) {
1165 return uprv_strCompare(s1, count, s2, count, FALSE, TRUE);
1166 }
1167
1168 /* u_unescape & support fns ------------------------------------------------- */
1169
1170 /* This map must be in ASCENDING ORDER OF THE ESCAPE CODE */
1171 static const UChar UNESCAPE_MAP[] = {
1172 /*" 0x22, 0x22 */
1173 /*' 0x27, 0x27 */
1174 /*? 0x3F, 0x3F */
1175 /*\ 0x5C, 0x5C */
1176 /*a*/ 0x61, 0x07,
1177 /*b*/ 0x62, 0x08,
1178 /*e*/ 0x65, 0x1b,
1179 /*f*/ 0x66, 0x0c,
1180 /*n*/ 0x6E, 0x0a,
1181 /*r*/ 0x72, 0x0d,
1182 /*t*/ 0x74, 0x09,
1183 /*v*/ 0x76, 0x0b
1184 };
1185 enum { UNESCAPE_MAP_LENGTH = UPRV_LENGTHOF(UNESCAPE_MAP) };
1186
1187 /* Convert one octal digit to a numeric value 0..7, or -1 on failure */
_digit8(UChar c)1188 static int8_t _digit8(UChar c) {
1189 if (c >= 0x0030 && c <= 0x0037) {
1190 return (int8_t)(c - 0x0030);
1191 }
1192 return -1;
1193 }
1194
1195 /* Convert one hex digit to a numeric value 0..F, or -1 on failure */
_digit16(UChar c)1196 static int8_t _digit16(UChar c) {
1197 if (c >= 0x0030 && c <= 0x0039) {
1198 return (int8_t)(c - 0x0030);
1199 }
1200 if (c >= 0x0041 && c <= 0x0046) {
1201 return (int8_t)(c - (0x0041 - 10));
1202 }
1203 if (c >= 0x0061 && c <= 0x0066) {
1204 return (int8_t)(c - (0x0061 - 10));
1205 }
1206 return -1;
1207 }
1208
1209 /* Parse a single escape sequence. Although this method deals in
1210 * UChars, it does not use C++ or UnicodeString. This allows it to
1211 * be used from C contexts. */
1212 U_CAPI UChar32 U_EXPORT2
u_unescapeAt(UNESCAPE_CHAR_AT charAt,int32_t * offset,int32_t length,void * context)1213 u_unescapeAt(UNESCAPE_CHAR_AT charAt,
1214 int32_t *offset,
1215 int32_t length,
1216 void *context) {
1217
1218 int32_t start = *offset;
1219 UChar c;
1220 UChar32 result = 0;
1221 int8_t n = 0;
1222 int8_t minDig = 0;
1223 int8_t maxDig = 0;
1224 int8_t bitsPerDigit = 4;
1225 int8_t dig;
1226 int32_t i;
1227 UBool braces = FALSE;
1228
1229 /* Check that offset is in range */
1230 if (*offset < 0 || *offset >= length) {
1231 goto err;
1232 }
1233
1234 /* Fetch first UChar after '\\' */
1235 c = charAt((*offset)++, context);
1236
1237 /* Convert hexadecimal and octal escapes */
1238 switch (c) {
1239 case 0x0075 /*'u'*/:
1240 minDig = maxDig = 4;
1241 break;
1242 case 0x0055 /*'U'*/:
1243 minDig = maxDig = 8;
1244 break;
1245 case 0x0078 /*'x'*/:
1246 minDig = 1;
1247 if (*offset < length && charAt(*offset, context) == 0x7B /*{*/) {
1248 ++(*offset);
1249 braces = TRUE;
1250 maxDig = 8;
1251 } else {
1252 maxDig = 2;
1253 }
1254 break;
1255 default:
1256 dig = _digit8(c);
1257 if (dig >= 0) {
1258 minDig = 1;
1259 maxDig = 3;
1260 n = 1; /* Already have first octal digit */
1261 bitsPerDigit = 3;
1262 result = dig;
1263 }
1264 break;
1265 }
1266 if (minDig != 0) {
1267 while (*offset < length && n < maxDig) {
1268 c = charAt(*offset, context);
1269 dig = (int8_t)((bitsPerDigit == 3) ? _digit8(c) : _digit16(c));
1270 if (dig < 0) {
1271 break;
1272 }
1273 result = (result << bitsPerDigit) | dig;
1274 ++(*offset);
1275 ++n;
1276 }
1277 if (n < minDig) {
1278 goto err;
1279 }
1280 if (braces) {
1281 if (c != 0x7D /*}*/) {
1282 goto err;
1283 }
1284 ++(*offset);
1285 }
1286 if (result < 0 || result >= 0x110000) {
1287 goto err;
1288 }
1289 /* If an escape sequence specifies a lead surrogate, see if
1290 * there is a trail surrogate after it, either as an escape or
1291 * as a literal. If so, join them up into a supplementary.
1292 */
1293 if (*offset < length && U16_IS_LEAD(result)) {
1294 int32_t ahead = *offset + 1;
1295 c = charAt(*offset, context);
1296 if (c == 0x5C /*'\\'*/ && ahead < length) {
1297 c = (UChar) u_unescapeAt(charAt, &ahead, length, context);
1298 }
1299 if (U16_IS_TRAIL(c)) {
1300 *offset = ahead;
1301 result = U16_GET_SUPPLEMENTARY(result, c);
1302 }
1303 }
1304 return result;
1305 }
1306
1307 /* Convert C-style escapes in table */
1308 for (i=0; i<UNESCAPE_MAP_LENGTH; i+=2) {
1309 if (c == UNESCAPE_MAP[i]) {
1310 return UNESCAPE_MAP[i+1];
1311 } else if (c < UNESCAPE_MAP[i]) {
1312 break;
1313 }
1314 }
1315
1316 /* Map \cX to control-X: X & 0x1F */
1317 if (c == 0x0063 /*'c'*/ && *offset < length) {
1318 c = charAt((*offset)++, context);
1319 if (U16_IS_LEAD(c) && *offset < length) {
1320 UChar c2 = charAt(*offset, context);
1321 if (U16_IS_TRAIL(c2)) {
1322 ++(*offset);
1323 c = (UChar) U16_GET_SUPPLEMENTARY(c, c2); /* [sic] */
1324 }
1325 }
1326 return 0x1F & c;
1327 }
1328
1329 /* If no special forms are recognized, then consider
1330 * the backslash to generically escape the next character.
1331 * Deal with surrogate pairs. */
1332 if (U16_IS_LEAD(c) && *offset < length) {
1333 UChar c2 = charAt(*offset, context);
1334 if (U16_IS_TRAIL(c2)) {
1335 ++(*offset);
1336 return U16_GET_SUPPLEMENTARY(c, c2);
1337 }
1338 }
1339 return c;
1340
1341 err:
1342 /* Invalid escape sequence */
1343 *offset = start; /* Reset to initial value */
1344 return (UChar32)0xFFFFFFFF;
1345 }
1346
1347 /* u_unescapeAt() callback to return a UChar from a char* */
1348 static UChar U_CALLCONV
_charPtr_charAt(int32_t offset,void * context)1349 _charPtr_charAt(int32_t offset, void *context) {
1350 UChar c16;
1351 /* It would be more efficient to access the invariant tables
1352 * directly but there is no API for that. */
1353 u_charsToUChars(((char*) context) + offset, &c16, 1);
1354 return c16;
1355 }
1356
1357 /* Append an escape-free segment of the text; used by u_unescape() */
_appendUChars(UChar * dest,int32_t destCapacity,const char * src,int32_t srcLen)1358 static void _appendUChars(UChar *dest, int32_t destCapacity,
1359 const char *src, int32_t srcLen) {
1360 if (destCapacity < 0) {
1361 destCapacity = 0;
1362 }
1363 if (srcLen > destCapacity) {
1364 srcLen = destCapacity;
1365 }
1366 u_charsToUChars(src, dest, srcLen);
1367 }
1368
1369 /* Do an invariant conversion of char* -> UChar*, with escape parsing */
1370 U_CAPI int32_t U_EXPORT2
u_unescape(const char * src,UChar * dest,int32_t destCapacity)1371 u_unescape(const char *src, UChar *dest, int32_t destCapacity) {
1372 const char *segment = src;
1373 int32_t i = 0;
1374 char c;
1375
1376 while ((c=*src) != 0) {
1377 /* '\\' intentionally written as compiler-specific
1378 * character constant to correspond to compiler-specific
1379 * char* constants. */
1380 if (c == '\\') {
1381 int32_t lenParsed = 0;
1382 UChar32 c32;
1383 if (src != segment) {
1384 if (dest != NULL) {
1385 _appendUChars(dest + i, destCapacity - i,
1386 segment, (int32_t)(src - segment));
1387 }
1388 i += (int32_t)(src - segment);
1389 }
1390 ++src; /* advance past '\\' */
1391 c32 = (UChar32)u_unescapeAt(_charPtr_charAt, &lenParsed, (int32_t)uprv_strlen(src), (void*)src);
1392 if (lenParsed == 0) {
1393 goto err;
1394 }
1395 src += lenParsed; /* advance past escape seq. */
1396 if (dest != NULL && U16_LENGTH(c32) <= (destCapacity - i)) {
1397 U16_APPEND_UNSAFE(dest, i, c32);
1398 } else {
1399 i += U16_LENGTH(c32);
1400 }
1401 segment = src;
1402 } else {
1403 ++src;
1404 }
1405 }
1406 if (src != segment) {
1407 if (dest != NULL) {
1408 _appendUChars(dest + i, destCapacity - i,
1409 segment, (int32_t)(src - segment));
1410 }
1411 i += (int32_t)(src - segment);
1412 }
1413 if (dest != NULL && i < destCapacity) {
1414 dest[i] = 0;
1415 }
1416 return i;
1417
1418 err:
1419 if (dest != NULL && destCapacity > 0) {
1420 *dest = 0;
1421 }
1422 return 0;
1423 }
1424
1425 /* NUL-termination of strings ----------------------------------------------- */
1426
1427 /**
1428 * NUL-terminate a string no matter what its type.
1429 * Set warning and error codes accordingly.
1430 */
1431 #define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) \
1432 if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) { \
1433 /* not a public function, so no complete argument checking */ \
1434 \
1435 if(length<0) { \
1436 /* assume that the caller handles this */ \
1437 } else if(length<destCapacity) { \
1438 /* NUL-terminate the string, the NUL fits */ \
1439 dest[length]=0; \
1440 /* unset the not-terminated warning but leave all others */ \
1441 if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) { \
1442 *pErrorCode=U_ZERO_ERROR; \
1443 } \
1444 } else if(length==destCapacity) { \
1445 /* unable to NUL-terminate, but the string itself fit - set a warning code */ \
1446 *pErrorCode=U_STRING_NOT_TERMINATED_WARNING; \
1447 } else /* length>destCapacity */ { \
1448 /* even the string itself did not fit - set an error code */ \
1449 *pErrorCode=U_BUFFER_OVERFLOW_ERROR; \
1450 } \
1451 }
1452
1453 U_CAPI int32_t U_EXPORT2
u_terminateUChars(UChar * dest,int32_t destCapacity,int32_t length,UErrorCode * pErrorCode)1454 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1455 __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1456 return length;
1457 }
1458
1459 U_CAPI int32_t U_EXPORT2
u_terminateChars(char * dest,int32_t destCapacity,int32_t length,UErrorCode * pErrorCode)1460 u_terminateChars(char *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1461 __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1462 return length;
1463 }
1464
1465 U_CAPI int32_t U_EXPORT2
u_terminateUChar32s(UChar32 * dest,int32_t destCapacity,int32_t length,UErrorCode * pErrorCode)1466 u_terminateUChar32s(UChar32 *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1467 __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1468 return length;
1469 }
1470
1471 U_CAPI int32_t U_EXPORT2
u_terminateWChars(wchar_t * dest,int32_t destCapacity,int32_t length,UErrorCode * pErrorCode)1472 u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
1473 __TERMINATE_STRING(dest, destCapacity, length, pErrorCode);
1474 return length;
1475 }
1476
1477 // Compute the hash code for a string -------------------------------------- ***
1478
1479 // Moved here from uhash.c so that UnicodeString::hashCode() does not depend
1480 // on UHashtable code.
1481
1482 /*
1483 Compute the hash by iterating sparsely over about 32 (up to 63)
1484 characters spaced evenly through the string. For each character,
1485 multiply the previous hash value by a prime number and add the new
1486 character in, like a linear congruential random number generator,
1487 producing a pseudorandom deterministic value well distributed over
1488 the output range. [LIU]
1489 */
1490
1491 #define STRING_HASH(TYPE, STR, STRLEN, DEREF) \
1492 uint32_t hash = 0; \
1493 const TYPE *p = (const TYPE*) STR; \
1494 if (p != NULL) { \
1495 int32_t len = (int32_t)(STRLEN); \
1496 int32_t inc = ((len - 32) / 32) + 1; \
1497 const TYPE *limit = p + len; \
1498 while (p<limit) { \
1499 hash = (hash * 37) + DEREF; \
1500 p += inc; \
1501 } \
1502 } \
1503 return static_cast<int32_t>(hash)
1504
1505 /* Used by UnicodeString to compute its hashcode - Not public API. */
1506 U_CAPI int32_t U_EXPORT2
ustr_hashUCharsN(const UChar * str,int32_t length)1507 ustr_hashUCharsN(const UChar *str, int32_t length) {
1508 STRING_HASH(UChar, str, length, *p);
1509 }
1510
1511 U_CAPI int32_t U_EXPORT2
ustr_hashCharsN(const char * str,int32_t length)1512 ustr_hashCharsN(const char *str, int32_t length) {
1513 STRING_HASH(uint8_t, str, length, *p);
1514 }
1515
1516 U_CAPI int32_t U_EXPORT2
ustr_hashICharsN(const char * str,int32_t length)1517 ustr_hashICharsN(const char *str, int32_t length) {
1518 STRING_HASH(char, str, length, (uint8_t)uprv_tolower(*p));
1519 }
1520