1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2003-2011, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: idnaref.cpp
12 * tab size: 8 (not used)
15 * created on: 2003feb1
16 * created by: Ram Viswanadha
19 #include "unicode/utypes.h"
21 #if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION
30 #include "unicode/ustring.h"
32 /* it is official IDNA ACE Prefix is "xn--" */
33 static const UChar ACE_PREFIX
[] ={ 0x0078,0x006E,0x002d,0x002d } ;
34 #define ACE_PREFIX_LENGTH 4
36 #define MAX_LABEL_LENGTH 63
38 /* The Max length of the labels should not be more than 64 */
39 #define MAX_LABEL_BUFFER_SIZE 100
40 #define MAX_IDN_BUFFER_SIZE 300
42 #define CAPITAL_A 0x0041
43 #define CAPITAL_Z 0x005A
44 #define LOWER_CASE_DELTA 0x0020
45 #define FULL_STOP 0x002E
49 startsWithPrefix(const UChar
* src
, int32_t srcLength
){
50 UBool startsWithPrefix
= TRUE
;
52 if(srcLength
< ACE_PREFIX_LENGTH
){
56 for(int8_t i
=0; i
< ACE_PREFIX_LENGTH
; i
++){
57 if(u_tolower(src
[i
]) != ACE_PREFIX
[i
]){
58 startsWithPrefix
= FALSE
;
61 return startsWithPrefix
;
65 toASCIILower(UChar ch
){
66 if(CAPITAL_A
<= ch
&& ch
<= CAPITAL_Z
){
67 return ch
+ LOWER_CASE_DELTA
;
73 compareCaseInsensitiveASCII(const UChar
* s1
, int32_t s1Len
,
74 const UChar
* s2
, int32_t s2Len
){
76 return (s1Len
> s2Len
) ? s1Len
: s2Len
;
81 for(int32_t i
=0;/* no condition */;i
++) {
82 /* If we reach the ends of both strings then they match */
90 /* Case-insensitive comparison */
92 rc
=(int32_t)toASCIILower(c1
)-(int32_t)toASCIILower(c2
);
101 static UErrorCode
getError(enum punycode_status status
){
103 case punycode_success
:
105 case punycode_bad_input
: /* Input is invalid. */
106 return U_INVALID_CHAR_FOUND
;
107 case punycode_big_output
: /* Output would exceed the space provided. */
108 return U_BUFFER_OVERFLOW_ERROR
;
109 case punycode_overflow
: /* Input requires wider integers to process. */
110 return U_INDEX_OUTOFBOUNDS_ERROR
;
112 return U_INTERNAL_PROGRAM_ERROR
;
116 static inline int32_t convertASCIIToUChars(const char* src
,UChar
* dest
, int32_t length
){
118 for(i
=0;i
<length
;i
++){
123 static inline int32_t convertUCharsToASCII(const UChar
* src
,char* dest
, int32_t length
){
125 for(i
=0;i
<length
;i
++){
126 dest
[i
] = (char)src
[i
];
130 // wrapper around the reference Punycode implementation
131 static int32_t convertToPuny(const UChar
* src
, int32_t srcLength
,
132 UChar
* dest
, int32_t destCapacity
,
134 uint32_t b1Stack
[MAX_LABEL_BUFFER_SIZE
];
135 int32_t b1Len
= 0, b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
136 uint32_t* b1
= b1Stack
;
137 char b2Stack
[MAX_LABEL_BUFFER_SIZE
];
139 int32_t b2Len
=MAX_LABEL_BUFFER_SIZE
;
140 punycode_status error
;
141 unsigned char* caseFlags
= NULL
;
143 u_strToUTF32((UChar32
*)b1
,b1Capacity
,&b1Len
,src
,srcLength
,&status
);
144 if(status
== U_BUFFER_OVERFLOW_ERROR
){
145 // redo processing of string
146 /* we do not have enough room so grow the buffer*/
147 b1
= (uint32_t*) uprv_malloc(b1Len
* sizeof(uint32_t));
149 status
= U_MEMORY_ALLOCATION_ERROR
;
153 status
= U_ZERO_ERROR
; // reset error
155 u_strToUTF32((UChar32
*)b1
,b1Len
,&b1Len
,src
,srcLength
,&status
);
157 if(U_FAILURE(status
)){
161 //caseFlags = (unsigned char*) uprv_malloc(b1Len *sizeof(unsigned char));
163 error
= punycode_encode(b1Len
,b1
,caseFlags
, (uint32_t*)&b2Len
, b2
);
164 status
= getError(error
);
166 if(status
== U_BUFFER_OVERFLOW_ERROR
){
167 /* we do not have enough room so grow the buffer*/
168 b2
= (char*) uprv_malloc( b2Len
* sizeof(char));
170 status
= U_MEMORY_ALLOCATION_ERROR
;
174 status
= U_ZERO_ERROR
; // reset error
176 punycode_status error
= punycode_encode(b1Len
,b1
,caseFlags
, (uint32_t*)&b2Len
, b2
);
177 status
= getError(error
);
179 if(U_FAILURE(status
)){
183 if(b2Len
< destCapacity
){
184 convertASCIIToUChars(b2
,dest
,b2Len
);
186 status
=U_BUFFER_OVERFLOW_ERROR
;
196 uprv_free(caseFlags
);
202 static NamePrepTransform
* getInstance(UErrorCode
& status
){
203 TestIDNA
*thisTest
= dynamic_cast<TestIDNA
*>(IntlTest::gTest
);
204 if (thisTest
== nullptr && U_SUCCESS(status
)) {
205 status
= U_INTERNAL_PROGRAM_ERROR
;
207 if (U_FAILURE(status
)) return nullptr;
208 return thisTest
->getInstance(status
);
212 static int32_t convertFromPuny( const UChar
* src
, int32_t srcLength
,
213 UChar
* dest
, int32_t destCapacity
,
215 char b1Stack
[MAX_LABEL_BUFFER_SIZE
];
219 convertUCharsToASCII(src
, b1
,srcLength
);
221 uint32_t b2Stack
[MAX_LABEL_BUFFER_SIZE
];
222 uint32_t* b2
= b2Stack
;
223 int32_t b2Len
=MAX_LABEL_BUFFER_SIZE
;
224 unsigned char* caseFlags
= NULL
; //(unsigned char*) uprv_malloc(srcLength * sizeof(unsigned char*));
225 punycode_status error
= punycode_decode(srcLength
,b1
,(uint32_t*)&b2Len
,b2
,caseFlags
);
226 status
= getError(error
);
227 if(status
== U_BUFFER_OVERFLOW_ERROR
){
228 b2
= (uint32_t*) uprv_malloc(b2Len
* sizeof(uint32_t));
230 status
= U_MEMORY_ALLOCATION_ERROR
;
233 error
= punycode_decode(srcLength
,b1
,(uint32_t*)&b2Len
,b2
,caseFlags
);
234 status
= getError(error
);
237 if(U_FAILURE(status
)){
241 u_strFromUTF32(dest
,destCapacity
,&destLen
,(UChar32
*)b2
,b2Len
,&status
);
250 uprv_free(caseFlags
);
256 U_CFUNC
int32_t U_EXPORT2
257 idnaref_toASCII(const UChar
* src
, int32_t srcLength
,
258 UChar
* dest
, int32_t destCapacity
,
260 UParseError
* parseError
,
263 if(status
== NULL
|| U_FAILURE(*status
)){
266 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
267 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
270 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
];
271 //initialize pointers to stack buffers
272 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
273 int32_t b1Len
=0, b2Len
=0,
274 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
275 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
279 UBool allowUnassigned
= (UBool
)((options
& IDNAREF_ALLOW_UNASSIGNED
) != 0);
280 UBool useSTD3ASCIIRules
= (UBool
)((options
& IDNAREF_USE_STD3_RULES
) != 0);
282 UBool
* caseFlags
= NULL
;
284 // assume the source contains all ascii codepoints
285 UBool srcIsASCII
= TRUE
;
286 // assume the source contains all LDH codepoints
287 UBool srcIsLDH
= TRUE
;
291 srcLength
= u_strlen(src
);
295 for( j
=0;j
<srcLength
;j
++){
299 b1
[b1Len
++] = src
[j
];
302 NamePrepTransform
* prep
= getInstance(*status
);
303 if(U_FAILURE(*status
)){
307 // step 2 is performed only if the source contains non ASCII
309 b1Len
= prep
->process(src
,srcLength
,b1
, b1Capacity
,allowUnassigned
,parseError
,*status
);
311 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
312 // redo processing of string
313 /* we do not have enough room so grow the buffer*/
314 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
316 *status
= U_MEMORY_ALLOCATION_ERROR
;
320 *status
= U_ZERO_ERROR
; // reset error
322 b1Len
= prep
->process(src
,srcLength
,b1
, b1Len
,allowUnassigned
, parseError
, *status
);
325 if(U_FAILURE(*status
)){
331 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
337 for( j
=0;j
<b1Len
;j
++){
338 if(b1
[j
] > 0x7F){// check if output of usprep_prepare is all ASCII
340 }else if(prep
->isLDHChar(b1
[j
])==FALSE
){ // if the char is in ASCII range verify that it is an LDH character{
345 if(useSTD3ASCIIRules
== TRUE
){
347 if( srcIsLDH
== FALSE
/* source contains some non-LDH characters */
348 || b1
[0] == HYPHEN
|| b1
[b1Len
-1] == HYPHEN
){
349 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
354 if(b1Len
<= destCapacity
){
355 u_memmove(dest
, b1
, b1Len
);
362 // step 5 : verify the sequence does not begin with ACE prefix
363 if(!startsWithPrefix(b1
,b1Len
)){
365 //step 6: encode the sequence with punycode
366 //caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
368 b2Len
= convertToPuny(b1
,b1Len
, b2
,b2Capacity
,*status
);
369 //b2Len = u_strToPunycode(b2,b2Capacity,b1,b1Len, caseFlags, status);
370 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
371 // redo processing of string
372 /* we do not have enough room so grow the buffer*/
373 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
375 *status
= U_MEMORY_ALLOCATION_ERROR
;
379 *status
= U_ZERO_ERROR
; // reset error
381 b2Len
= convertToPuny(b1
, b1Len
, b2
, b2Len
, *status
);
382 //b2Len = u_strToPunycode(b2,b2Len,b1,b1Len, caseFlags, status);
386 if(U_FAILURE(*status
)){
389 reqLength
= b2Len
+ACE_PREFIX_LENGTH
;
391 if(reqLength
> destCapacity
){
392 *status
= U_BUFFER_OVERFLOW_ERROR
;
395 //Step 7: prepend the ACE prefix
396 u_memcpy(dest
, ACE_PREFIX
, ACE_PREFIX_LENGTH
);
397 //Step 6: copy the contents in b2 into dest
398 u_memcpy(dest
+ACE_PREFIX_LENGTH
, b2
, b2Len
);
401 *status
= U_IDNA_ACE_PREFIX_ERROR
;
406 if(reqLength
> MAX_LABEL_LENGTH
){
407 *status
= U_IDNA_LABEL_TOO_LONG_ERROR
;
417 uprv_free(caseFlags
);
421 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
425 U_CFUNC
int32_t U_EXPORT2
426 idnaref_toUnicode(const UChar
* src
, int32_t srcLength
,
427 UChar
* dest
, int32_t destCapacity
,
429 UParseError
* parseError
,
432 if(status
== NULL
|| U_FAILURE(*status
)){
435 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
436 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
442 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
], b3Stack
[MAX_LABEL_BUFFER_SIZE
];
444 //initialize pointers to stack buffers
445 UChar
*b1
= b1Stack
, *b2
= b2Stack
, *b1Prime
=NULL
, *b3
=b3Stack
;
446 int32_t b1Len
, b2Len
, b1PrimeLen
, b3Len
,
447 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
448 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
449 b3Capacity
= MAX_LABEL_BUFFER_SIZE
,
451 // UParseError parseError;
453 NamePrepTransform
* prep
= getInstance(*status
);
455 UBool
* caseFlags
= NULL
;
458 UBool allowUnassigned
= (UBool
)((options
& IDNAREF_ALLOW_UNASSIGNED
) != 0);
459 UBool useSTD3ASCIIRules
= (UBool
)((options
& IDNAREF_USE_STD3_RULES
) != 0);
461 UBool srcIsASCII
= TRUE
;
462 UBool srcIsLDH
= TRUE
;
465 if(U_FAILURE(*status
)){
468 // step 1: find out if all the codepoints in src are ASCII
471 for(;src
[srcLength
]!=0;){
472 if(src
[srcLength
]> 0x7f){
474 }if(prep
->isLDHChar(src
[srcLength
])==FALSE
){
475 // here we do not assemble surrogates
476 // since we know that LDH code points
477 // are in the ASCII range only
484 for(int32_t j
=0; j
<srcLength
; j
++){
487 }else if(prep
->isLDHChar(src
[j
])==FALSE
){
488 // here we do not assemble surrogates
489 // since we know that LDH code points
490 // are in the ASCII range only
497 if(srcIsASCII
== FALSE
){
498 // step 2: process the string
499 b1Len
= prep
->process(src
,srcLength
,b1
,b1Capacity
,allowUnassigned
, parseError
, *status
);
500 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
501 // redo processing of string
502 /* we do not have enough room so grow the buffer*/
503 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
505 *status
= U_MEMORY_ALLOCATION_ERROR
;
509 *status
= U_ZERO_ERROR
; // reset error
511 b1Len
= prep
->process(src
,srcLength
,b1
, b1Len
,allowUnassigned
, parseError
, *status
);
514 if(U_FAILURE(*status
)){
519 // copy everything to b1
520 if(srcLength
< b1Capacity
){
521 u_memmove(b1
, src
, srcLength
);
523 /* we do not have enough room so grow the buffer*/
524 b1
= (UChar
*) uprv_malloc(srcLength
* U_SIZEOF_UCHAR
);
526 *status
= U_MEMORY_ALLOCATION_ERROR
;
529 u_memmove(b1
, src
, srcLength
);
533 //step 3: verify ACE Prefix
534 if(startsWithPrefix(src
,srcLength
)){
536 //step 4: Remove the ACE Prefix
537 b1Prime
= b1
+ ACE_PREFIX_LENGTH
;
538 b1PrimeLen
= b1Len
- ACE_PREFIX_LENGTH
;
540 //step 5: Decode using punycode
541 b2Len
= convertFromPuny(b1Prime
,b1PrimeLen
, b2
, b2Capacity
, *status
);
542 //b2Len = u_strFromPunycode(b2, b2Capacity,b1Prime,b1PrimeLen, caseFlags, status);
544 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
545 // redo processing of string
546 /* we do not have enough room so grow the buffer*/
547 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
549 *status
= U_MEMORY_ALLOCATION_ERROR
;
553 *status
= U_ZERO_ERROR
; // reset error
555 b2Len
= convertFromPuny(b1Prime
,b1PrimeLen
, b2
, b2Len
, *status
);
556 //b2Len = u_strFromPunycode(b2, b2Len,b1Prime,b1PrimeLen,caseFlags, status);
560 //step 6:Apply toASCII
561 b3Len
= idnaref_toASCII(b2
,b2Len
,b3
,b3Capacity
,options
,parseError
, status
);
563 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
564 // redo processing of string
565 /* we do not have enough room so grow the buffer*/
566 b3
= (UChar
*) uprv_malloc(b3Len
* U_SIZEOF_UCHAR
);
568 *status
= U_MEMORY_ALLOCATION_ERROR
;
572 *status
= U_ZERO_ERROR
; // reset error
574 b3Len
= idnaref_toASCII(b2
,b2Len
,b3
,b3Len
, options
, parseError
, status
);
578 if(U_FAILURE(*status
)){
583 if(compareCaseInsensitiveASCII(b1
, b1Len
, b3
, b3Len
) !=0){
584 *status
= U_IDNA_VERIFICATION_ERROR
;
588 //step 8: return output of step 5
590 if(b2Len
<= destCapacity
) {
591 u_memmove(dest
, b2
, b2Len
);
594 // verify that STD3 ASCII rules are satisfied
595 if(useSTD3ASCIIRules
== TRUE
){
596 if( srcIsLDH
== FALSE
/* source contains some non-LDH characters */
597 || src
[0] == HYPHEN
|| src
[srcLength
-1] == HYPHEN
){
598 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
600 /* populate the parseError struct */
602 // failPos is always set the index of failure
603 uprv_syntaxError(src
,failPos
, srcLength
,parseError
);
604 }else if(src
[0] == HYPHEN
){
605 // fail position is 0
606 uprv_syntaxError(src
,0,srcLength
,parseError
);
608 // the last index in the source is always length-1
609 uprv_syntaxError(src
, (srcLength
>0) ? srcLength
-1 : srcLength
, srcLength
,parseError
);
615 //copy the source to destination
616 if(srcLength
<= destCapacity
){
617 u_memmove(dest
, src
, srcLength
);
619 reqLength
= srcLength
;
630 uprv_free(caseFlags
);
632 // The RFC states that
634 // ToUnicode never fails. If any step fails, then the original input
635 // is returned immediately in that step.
637 // So if any step fails lets copy source to destination
638 if(U_FAILURE(*status
)){
639 //copy the source to destination
640 if(dest
&& srcLength
<= destCapacity
){
641 if(srcLength
== -1) {
642 u_memmove(dest
, src
, u_strlen(src
));
644 u_memmove(dest
, src
, srcLength
);
647 reqLength
= srcLength
;
648 *status
= U_ZERO_ERROR
;
650 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
655 getNextSeparator(UChar
*src
,int32_t srcLength
,NamePrepTransform
* prep
,
663 *limit
= src
+ i
; // point to null
667 if(prep
->isLabelSeparator(src
[i
],*status
)){
668 *limit
= src
+ (i
+1); // go past the delimiter
675 for(i
=0;i
<srcLength
;i
++){
676 if(prep
->isLabelSeparator(src
[i
],*status
)){
677 *limit
= src
+ (i
+1); // go past the delimiter
681 // we have not found the delimiter
683 *limit
= src
+srcLength
;
690 U_CFUNC
int32_t U_EXPORT2
691 idnaref_IDNToASCII( const UChar
* src
, int32_t srcLength
,
692 UChar
* dest
, int32_t destCapacity
,
694 UParseError
* parseError
,
697 if(status
== NULL
|| U_FAILURE(*status
)){
700 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
701 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
705 int32_t reqLength
= 0;
706 // UParseError parseError;
708 NamePrepTransform
* prep
= getInstance(*status
);
710 //initialize pointers to stack buffers
711 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
];
713 int32_t b1Len
, labelLen
;
714 UChar
* delimiter
= (UChar
*)src
;
715 UChar
* labelStart
= (UChar
*)src
;
716 int32_t remainingLen
= srcLength
;
717 int32_t b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
720 // UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0);
721 // UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0);
724 if(U_FAILURE(*status
)){
736 labelLen
= getNextSeparator(labelStart
, -1, prep
, &delimiter
, &done
, status
);
738 if(!(labelLen
==0 && done
)){// make sure this is not a root label separator.
740 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Capacity
,
741 options
, parseError
, status
);
743 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
744 // redo processing of string
745 /* we do not have enough room so grow the buffer*/
746 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
748 *status
= U_MEMORY_ALLOCATION_ERROR
;
752 *status
= U_ZERO_ERROR
; // reset error
754 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Len
,
755 options
, parseError
, status
);
760 if(U_FAILURE(*status
)){
763 int32_t tempLen
= (reqLength
+ b1Len
);
765 if( tempLen
< destCapacity
){
766 u_memmove(dest
+reqLength
, b1
, b1Len
);
771 // add the label separator
773 if(reqLength
< destCapacity
){
774 dest
[reqLength
] = FULL_STOP
;
779 labelStart
= delimiter
;
784 if(delimiter
== src
+srcLength
){
788 labelLen
= getNextSeparator(labelStart
, remainingLen
, prep
, &delimiter
, &done
, status
);
790 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Capacity
,
791 options
,parseError
, status
);
793 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
794 // redo processing of string
795 /* we do not have enough room so grow the buffer*/
796 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
798 *status
= U_MEMORY_ALLOCATION_ERROR
;
802 *status
= U_ZERO_ERROR
; // reset error
804 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Len
,
805 options
, parseError
, status
);
809 if(U_FAILURE(*status
)){
812 int32_t tempLen
= (reqLength
+ b1Len
);
814 if( tempLen
< destCapacity
){
815 u_memmove(dest
+reqLength
, b1
, b1Len
);
820 // add the label separator
822 if(reqLength
< destCapacity
){
823 dest
[reqLength
] = FULL_STOP
;
828 labelStart
= delimiter
;
829 remainingLen
= static_cast<int32_t>(srcLength
- (delimiter
- src
));
842 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
845 U_CFUNC
int32_t U_EXPORT2
846 idnaref_IDNToUnicode( const UChar
* src
, int32_t srcLength
,
847 UChar
* dest
, int32_t destCapacity
,
849 UParseError
* parseError
,
852 if(status
== NULL
|| U_FAILURE(*status
)){
855 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
856 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
860 int32_t reqLength
= 0;
864 NamePrepTransform
* prep
= getInstance(*status
);
866 //initialize pointers to stack buffers
867 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
];
869 int32_t b1Len
, labelLen
;
870 UChar
* delimiter
= (UChar
*)src
;
871 UChar
* labelStart
= (UChar
*)src
;
872 int32_t remainingLen
= srcLength
;
873 int32_t b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
876 // UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0);
877 // UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0);
879 if(U_FAILURE(*status
)){
890 labelLen
= getNextSeparator(labelStart
, -1, prep
, &delimiter
, &done
, status
);
892 if(labelLen
==0 && done
==FALSE
){
893 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
895 b1Len
= idnaref_toUnicode(labelStart
, labelLen
, b1
, b1Capacity
,
896 options
, parseError
, status
);
898 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
899 // redo processing of string
900 /* we do not have enough room so grow the buffer*/
901 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
903 *status
= U_MEMORY_ALLOCATION_ERROR
;
907 *status
= U_ZERO_ERROR
; // reset error
909 b1Len
= idnaref_toUnicode( labelStart
, labelLen
, b1
, b1Len
,
910 options
, parseError
, status
);
914 if(U_FAILURE(*status
)){
917 int32_t tempLen
= (reqLength
+ b1Len
);
919 if( tempLen
< destCapacity
){
920 u_memmove(dest
+reqLength
, b1
, b1Len
);
924 // add the label separator
926 if(reqLength
< destCapacity
){
927 dest
[reqLength
] = FULL_STOP
;
932 labelStart
= delimiter
;
937 if(delimiter
== src
+srcLength
){
941 labelLen
= getNextSeparator(labelStart
, remainingLen
, prep
, &delimiter
, &done
, status
);
943 if(labelLen
==0 && done
==FALSE
){
944 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
947 b1Len
= idnaref_toUnicode( labelStart
,labelLen
, b1
, b1Capacity
,
948 options
, parseError
, status
);
950 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
951 // redo processing of string
952 /* we do not have enough room so grow the buffer*/
953 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
955 *status
= U_MEMORY_ALLOCATION_ERROR
;
959 *status
= U_ZERO_ERROR
; // reset error
961 b1Len
= idnaref_toUnicode( labelStart
, labelLen
, b1
, b1Len
,
962 options
, parseError
, status
);
966 if(U_FAILURE(*status
)){
969 int32_t tempLen
= (reqLength
+ b1Len
);
971 if( tempLen
< destCapacity
){
972 u_memmove(dest
+reqLength
, b1
, b1Len
);
977 // add the label separator
979 if(reqLength
< destCapacity
){
980 dest
[reqLength
] = FULL_STOP
;
985 labelStart
= delimiter
;
986 remainingLen
= static_cast<int32_t>(srcLength
- (delimiter
- src
));
998 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
1001 U_CFUNC
int32_t U_EXPORT2
1002 idnaref_compare( const UChar
*s1
, int32_t length1
,
1003 const UChar
*s2
, int32_t length2
,
1005 UErrorCode
* status
){
1007 if(status
== NULL
|| U_FAILURE(*status
)){
1011 UChar b1Stack
[MAX_IDN_BUFFER_SIZE
], b2Stack
[MAX_IDN_BUFFER_SIZE
];
1012 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
1013 int32_t b1Len
, b2Len
, b1Capacity
= MAX_IDN_BUFFER_SIZE
, b2Capacity
= MAX_IDN_BUFFER_SIZE
;
1014 int32_t result
= -1;
1016 UParseError parseError
;
1018 b1Len
= idnaref_IDNToASCII(s1
, length1
, b1
, b1Capacity
, options
, &parseError
, status
);
1019 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
1020 // redo processing of string
1021 /* we do not have enough room so grow the buffer*/
1022 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
1024 *status
= U_MEMORY_ALLOCATION_ERROR
;
1028 *status
= U_ZERO_ERROR
; // reset error
1030 b1Len
= idnaref_IDNToASCII(s1
,length1
,b1
,b1Len
, options
, &parseError
, status
);
1034 b2Len
= idnaref_IDNToASCII(s2
,length2
,b2
,b2Capacity
,options
, &parseError
, status
);
1035 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
1036 // redo processing of string
1037 /* we do not have enough room so grow the buffer*/
1038 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
1040 *status
= U_MEMORY_ALLOCATION_ERROR
;
1044 *status
= U_ZERO_ERROR
; // reset error
1046 b2Len
= idnaref_IDNToASCII(s2
,length2
,b2
,b2Len
,options
, &parseError
, status
);
1049 // when toASCII is applied all label separators are replaced with FULL_STOP
1050 result
= compareCaseInsensitiveASCII(b1
,b1Len
,b2
,b2Len
);
1063 #endif /* #if !UCONFIG_NO_IDNA */