2 *******************************************************************************
4 * Copyright (C) 2003-2011, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: idnaref.cpp
10 * tab size: 8 (not used)
13 * created on: 2003feb1
14 * created by: Ram Viswanadha
17 #include "unicode/utypes.h"
19 #if !UCONFIG_NO_IDNA && !UCONFIG_NO_TRANSLITERATION
28 #include "unicode/ustring.h"
30 /* it is official IDNA ACE Prefix is "xn--" */
31 static const UChar ACE_PREFIX
[] ={ 0x0078,0x006E,0x002d,0x002d } ;
32 #define ACE_PREFIX_LENGTH 4
34 #define MAX_LABEL_LENGTH 63
36 /* The Max length of the labels should not be more than 64 */
37 #define MAX_LABEL_BUFFER_SIZE 100
38 #define MAX_IDN_BUFFER_SIZE 300
40 #define CAPITAL_A 0x0041
41 #define CAPITAL_Z 0x005A
42 #define LOWER_CASE_DELTA 0x0020
43 #define FULL_STOP 0x002E
47 startsWithPrefix(const UChar
* src
, int32_t srcLength
){
48 UBool startsWithPrefix
= TRUE
;
50 if(srcLength
< ACE_PREFIX_LENGTH
){
54 for(int8_t i
=0; i
< ACE_PREFIX_LENGTH
; i
++){
55 if(u_tolower(src
[i
]) != ACE_PREFIX
[i
]){
56 startsWithPrefix
= FALSE
;
59 return startsWithPrefix
;
63 toASCIILower(UChar ch
){
64 if(CAPITAL_A
<= ch
&& ch
<= CAPITAL_Z
){
65 return ch
+ LOWER_CASE_DELTA
;
71 compareCaseInsensitiveASCII(const UChar
* s1
, int32_t s1Len
,
72 const UChar
* s2
, int32_t s2Len
){
74 return (s1Len
> s2Len
) ? s1Len
: s2Len
;
79 for(int32_t i
=0;/* no condition */;i
++) {
80 /* If we reach the ends of both strings then they match */
88 /* Case-insensitive comparison */
90 rc
=(int32_t)toASCIILower(c1
)-(int32_t)toASCIILower(c2
);
99 static UErrorCode
getError(enum punycode_status status
){
101 case punycode_success
:
103 case punycode_bad_input
: /* Input is invalid. */
104 return U_INVALID_CHAR_FOUND
;
105 case punycode_big_output
: /* Output would exceed the space provided. */
106 return U_BUFFER_OVERFLOW_ERROR
;
107 case punycode_overflow
: /* Input requires wider integers to process. */
108 return U_INDEX_OUTOFBOUNDS_ERROR
;
110 return U_INTERNAL_PROGRAM_ERROR
;
114 static inline int32_t convertASCIIToUChars(const char* src
,UChar
* dest
, int32_t length
){
116 for(i
=0;i
<length
;i
++){
121 static inline int32_t convertUCharsToASCII(const UChar
* src
,char* dest
, int32_t length
){
123 for(i
=0;i
<length
;i
++){
124 dest
[i
] = (char)src
[i
];
128 // wrapper around the reference Punycode implementation
129 static int32_t convertToPuny(const UChar
* src
, int32_t srcLength
,
130 UChar
* dest
, int32_t destCapacity
,
132 uint32_t b1Stack
[MAX_LABEL_BUFFER_SIZE
];
133 int32_t b1Len
= 0, b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
134 uint32_t* b1
= b1Stack
;
135 char b2Stack
[MAX_LABEL_BUFFER_SIZE
];
137 int32_t b2Len
=MAX_LABEL_BUFFER_SIZE
;
138 punycode_status error
;
139 unsigned char* caseFlags
= NULL
;
141 u_strToUTF32((UChar32
*)b1
,b1Capacity
,&b1Len
,src
,srcLength
,&status
);
142 if(status
== U_BUFFER_OVERFLOW_ERROR
){
143 // redo processing of string
144 /* we do not have enough room so grow the buffer*/
145 b1
= (uint32_t*) uprv_malloc(b1Len
* sizeof(uint32_t));
147 status
= U_MEMORY_ALLOCATION_ERROR
;
151 status
= U_ZERO_ERROR
; // reset error
153 u_strToUTF32((UChar32
*)b1
,b1Len
,&b1Len
,src
,srcLength
,&status
);
155 if(U_FAILURE(status
)){
159 //caseFlags = (unsigned char*) uprv_malloc(b1Len *sizeof(unsigned char));
161 error
= punycode_encode(b1Len
,b1
,caseFlags
, (uint32_t*)&b2Len
, b2
);
162 status
= getError(error
);
164 if(status
== U_BUFFER_OVERFLOW_ERROR
){
165 /* we do not have enough room so grow the buffer*/
166 b2
= (char*) uprv_malloc( b2Len
* sizeof(char));
168 status
= U_MEMORY_ALLOCATION_ERROR
;
172 status
= U_ZERO_ERROR
; // reset error
174 punycode_status error
= punycode_encode(b1Len
,b1
,caseFlags
, (uint32_t*)&b2Len
, b2
);
175 status
= getError(error
);
177 if(U_FAILURE(status
)){
181 if(b2Len
< destCapacity
){
182 convertASCIIToUChars(b2
,dest
,b2Len
);
184 status
=U_BUFFER_OVERFLOW_ERROR
;
194 uprv_free(caseFlags
);
199 static int32_t convertFromPuny( const UChar
* src
, int32_t srcLength
,
200 UChar
* dest
, int32_t destCapacity
,
202 char b1Stack
[MAX_LABEL_BUFFER_SIZE
];
206 convertUCharsToASCII(src
, b1
,srcLength
);
208 uint32_t b2Stack
[MAX_LABEL_BUFFER_SIZE
];
209 uint32_t* b2
= b2Stack
;
210 int32_t b2Len
=MAX_LABEL_BUFFER_SIZE
;
211 unsigned char* caseFlags
= NULL
; //(unsigned char*) uprv_malloc(srcLength * sizeof(unsigned char*));
212 punycode_status error
= punycode_decode(srcLength
,b1
,(uint32_t*)&b2Len
,b2
,caseFlags
);
213 status
= getError(error
);
214 if(status
== U_BUFFER_OVERFLOW_ERROR
){
215 b2
= (uint32_t*) uprv_malloc(b2Len
* sizeof(uint32_t));
217 status
= U_MEMORY_ALLOCATION_ERROR
;
220 error
= punycode_decode(srcLength
,b1
,(uint32_t*)&b2Len
,b2
,caseFlags
);
221 status
= getError(error
);
224 if(U_FAILURE(status
)){
228 u_strFromUTF32(dest
,destCapacity
,&destLen
,(UChar32
*)b2
,b2Len
,&status
);
237 uprv_free(caseFlags
);
243 U_CFUNC
int32_t U_EXPORT2
244 idnaref_toASCII(const UChar
* src
, int32_t srcLength
,
245 UChar
* dest
, int32_t destCapacity
,
247 UParseError
* parseError
,
250 if(status
== NULL
|| U_FAILURE(*status
)){
253 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
254 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
257 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
];
258 //initialize pointers to stack buffers
259 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
260 int32_t b1Len
=0, b2Len
=0,
261 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
262 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
266 UBool allowUnassigned
= (UBool
)((options
& IDNAREF_ALLOW_UNASSIGNED
) != 0);
267 UBool useSTD3ASCIIRules
= (UBool
)((options
& IDNAREF_USE_STD3_RULES
) != 0);
269 UBool
* caseFlags
= NULL
;
271 // assume the source contains all ascii codepoints
272 UBool srcIsASCII
= TRUE
;
273 // assume the source contains all LDH codepoints
274 UBool srcIsLDH
= TRUE
;
278 srcLength
= u_strlen(src
);
282 for( j
=0;j
<srcLength
;j
++){
286 b1
[b1Len
++] = src
[j
];
289 NamePrepTransform
* prep
= TestIDNA::getInstance(*status
);
290 if(U_FAILURE(*status
)){
294 // step 2 is performed only if the source contains non ASCII
296 b1Len
= prep
->process(src
,srcLength
,b1
, b1Capacity
,allowUnassigned
,parseError
,*status
);
298 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
299 // redo processing of string
300 /* we do not have enough room so grow the buffer*/
301 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
303 *status
= U_MEMORY_ALLOCATION_ERROR
;
307 *status
= U_ZERO_ERROR
; // reset error
309 b1Len
= prep
->process(src
,srcLength
,b1
, b1Len
,allowUnassigned
, parseError
, *status
);
312 if(U_FAILURE(*status
)){
318 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
324 for( j
=0;j
<b1Len
;j
++){
325 if(b1
[j
] > 0x7F){// check if output of usprep_prepare is all ASCII
327 }else if(prep
->isLDHChar(b1
[j
])==FALSE
){ // if the char is in ASCII range verify that it is an LDH character{
332 if(useSTD3ASCIIRules
== TRUE
){
334 if( srcIsLDH
== FALSE
/* source contains some non-LDH characters */
335 || b1
[0] == HYPHEN
|| b1
[b1Len
-1] == HYPHEN
){
336 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
341 if(b1Len
<= destCapacity
){
342 uprv_memmove(dest
, b1
, b1Len
* U_SIZEOF_UCHAR
);
349 // step 5 : verify the sequence does not begin with ACE prefix
350 if(!startsWithPrefix(b1
,b1Len
)){
352 //step 6: encode the sequence with punycode
353 //caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
355 b2Len
= convertToPuny(b1
,b1Len
, b2
,b2Capacity
,*status
);
356 //b2Len = u_strToPunycode(b2,b2Capacity,b1,b1Len, caseFlags, status);
357 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
358 // redo processing of string
359 /* we do not have enough room so grow the buffer*/
360 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
362 *status
= U_MEMORY_ALLOCATION_ERROR
;
366 *status
= U_ZERO_ERROR
; // reset error
368 b2Len
= convertToPuny(b1
, b1Len
, b2
, b2Len
, *status
);
369 //b2Len = u_strToPunycode(b2,b2Len,b1,b1Len, caseFlags, status);
373 if(U_FAILURE(*status
)){
376 reqLength
= b2Len
+ACE_PREFIX_LENGTH
;
378 if(reqLength
> destCapacity
){
379 *status
= U_BUFFER_OVERFLOW_ERROR
;
382 //Step 7: prepend the ACE prefix
383 uprv_memcpy(dest
,ACE_PREFIX
,ACE_PREFIX_LENGTH
* U_SIZEOF_UCHAR
);
384 //Step 6: copy the contents in b2 into dest
385 uprv_memcpy(dest
+ACE_PREFIX_LENGTH
, b2
, b2Len
* U_SIZEOF_UCHAR
);
388 *status
= U_IDNA_ACE_PREFIX_ERROR
;
393 if(reqLength
> MAX_LABEL_LENGTH
){
394 *status
= U_IDNA_LABEL_TOO_LONG_ERROR
;
404 uprv_free(caseFlags
);
408 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
412 U_CFUNC
int32_t U_EXPORT2
413 idnaref_toUnicode(const UChar
* src
, int32_t srcLength
,
414 UChar
* dest
, int32_t destCapacity
,
416 UParseError
* parseError
,
419 if(status
== NULL
|| U_FAILURE(*status
)){
422 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
423 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
429 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
], b3Stack
[MAX_LABEL_BUFFER_SIZE
];
431 //initialize pointers to stack buffers
432 UChar
*b1
= b1Stack
, *b2
= b2Stack
, *b1Prime
=NULL
, *b3
=b3Stack
;
433 int32_t b1Len
, b2Len
, b1PrimeLen
, b3Len
,
434 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
435 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
436 b3Capacity
= MAX_LABEL_BUFFER_SIZE
,
438 // UParseError parseError;
440 NamePrepTransform
* prep
= TestIDNA::getInstance(*status
);
442 UBool
* caseFlags
= NULL
;
445 UBool allowUnassigned
= (UBool
)((options
& IDNAREF_ALLOW_UNASSIGNED
) != 0);
446 UBool useSTD3ASCIIRules
= (UBool
)((options
& IDNAREF_USE_STD3_RULES
) != 0);
448 UBool srcIsASCII
= TRUE
;
449 UBool srcIsLDH
= TRUE
;
452 if(U_FAILURE(*status
)){
455 // step 1: find out if all the codepoints in src are ASCII
458 for(;src
[srcLength
]!=0;){
459 if(src
[srcLength
]> 0x7f){
461 }if(prep
->isLDHChar(src
[srcLength
])==FALSE
){
462 // here we do not assemble surrogates
463 // since we know that LDH code points
464 // are in the ASCII range only
471 for(int32_t j
=0; j
<srcLength
; j
++){
474 }else if(prep
->isLDHChar(src
[j
])==FALSE
){
475 // here we do not assemble surrogates
476 // since we know that LDH code points
477 // are in the ASCII range only
484 if(srcIsASCII
== FALSE
){
485 // step 2: process the string
486 b1Len
= prep
->process(src
,srcLength
,b1
,b1Capacity
,allowUnassigned
, parseError
, *status
);
487 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
488 // redo processing of string
489 /* we do not have enough room so grow the buffer*/
490 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
492 *status
= U_MEMORY_ALLOCATION_ERROR
;
496 *status
= U_ZERO_ERROR
; // reset error
498 b1Len
= prep
->process(src
,srcLength
,b1
, b1Len
,allowUnassigned
, parseError
, *status
);
501 if(U_FAILURE(*status
)){
506 // copy everything to b1
507 if(srcLength
< b1Capacity
){
508 uprv_memmove(b1
,src
, srcLength
* U_SIZEOF_UCHAR
);
510 /* we do not have enough room so grow the buffer*/
511 b1
= (UChar
*) uprv_malloc(srcLength
* U_SIZEOF_UCHAR
);
513 *status
= U_MEMORY_ALLOCATION_ERROR
;
516 uprv_memmove(b1
,src
, srcLength
* U_SIZEOF_UCHAR
);
520 //step 3: verify ACE Prefix
521 if(startsWithPrefix(src
,srcLength
)){
523 //step 4: Remove the ACE Prefix
524 b1Prime
= b1
+ ACE_PREFIX_LENGTH
;
525 b1PrimeLen
= b1Len
- ACE_PREFIX_LENGTH
;
527 //step 5: Decode using punycode
528 b2Len
= convertFromPuny(b1Prime
,b1PrimeLen
, b2
, b2Capacity
, *status
);
529 //b2Len = u_strFromPunycode(b2, b2Capacity,b1Prime,b1PrimeLen, caseFlags, status);
531 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
532 // redo processing of string
533 /* we do not have enough room so grow the buffer*/
534 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
536 *status
= U_MEMORY_ALLOCATION_ERROR
;
540 *status
= U_ZERO_ERROR
; // reset error
542 b2Len
= convertFromPuny(b1Prime
,b1PrimeLen
, b2
, b2Len
, *status
);
543 //b2Len = u_strFromPunycode(b2, b2Len,b1Prime,b1PrimeLen,caseFlags, status);
547 //step 6:Apply toASCII
548 b3Len
= idnaref_toASCII(b2
,b2Len
,b3
,b3Capacity
,options
,parseError
, status
);
550 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
551 // redo processing of string
552 /* we do not have enough room so grow the buffer*/
553 b3
= (UChar
*) uprv_malloc(b3Len
* U_SIZEOF_UCHAR
);
555 *status
= U_MEMORY_ALLOCATION_ERROR
;
559 *status
= U_ZERO_ERROR
; // reset error
561 b3Len
= idnaref_toASCII(b2
,b2Len
,b3
,b3Len
, options
, parseError
, status
);
565 if(U_FAILURE(*status
)){
570 if(compareCaseInsensitiveASCII(b1
, b1Len
, b3
, b3Len
) !=0){
571 *status
= U_IDNA_VERIFICATION_ERROR
;
575 //step 8: return output of step 5
577 if(b2Len
<= destCapacity
) {
578 uprv_memmove(dest
, b2
, b2Len
* U_SIZEOF_UCHAR
);
581 // verify that STD3 ASCII rules are satisfied
582 if(useSTD3ASCIIRules
== TRUE
){
583 if( srcIsLDH
== FALSE
/* source contains some non-LDH characters */
584 || src
[0] == HYPHEN
|| src
[srcLength
-1] == HYPHEN
){
585 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
587 /* populate the parseError struct */
589 // failPos is always set the index of failure
590 uprv_syntaxError(src
,failPos
, srcLength
,parseError
);
591 }else if(src
[0] == HYPHEN
){
592 // fail position is 0
593 uprv_syntaxError(src
,0,srcLength
,parseError
);
595 // the last index in the source is always length-1
596 uprv_syntaxError(src
, (srcLength
>0) ? srcLength
-1 : srcLength
, srcLength
,parseError
);
602 //copy the source to destination
603 if(srcLength
<= destCapacity
){
604 uprv_memmove(dest
,src
,srcLength
* U_SIZEOF_UCHAR
);
606 reqLength
= srcLength
;
617 uprv_free(caseFlags
);
619 // The RFC states that
621 // ToUnicode never fails. If any step fails, then the original input
622 // is returned immediately in that step.
624 // So if any step fails lets copy source to destination
625 if(U_FAILURE(*status
)){
626 //copy the source to destination
627 if(dest
&& srcLength
<= destCapacity
){
628 if(srcLength
== -1) {
629 uprv_memmove(dest
,src
,u_strlen(src
)* U_SIZEOF_UCHAR
);
631 uprv_memmove(dest
,src
,srcLength
* U_SIZEOF_UCHAR
);
634 reqLength
= srcLength
;
635 *status
= U_ZERO_ERROR
;
637 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
642 getNextSeparator(UChar
*src
,int32_t srcLength
,NamePrepTransform
* prep
,
650 *limit
= src
+ i
; // point to null
654 if(prep
->isLabelSeparator(src
[i
],*status
)){
655 *limit
= src
+ (i
+1); // go past the delimiter
662 for(i
=0;i
<srcLength
;i
++){
663 if(prep
->isLabelSeparator(src
[i
],*status
)){
664 *limit
= src
+ (i
+1); // go past the delimiter
668 // we have not found the delimiter
670 *limit
= src
+srcLength
;
677 U_CFUNC
int32_t U_EXPORT2
678 idnaref_IDNToASCII( const UChar
* src
, int32_t srcLength
,
679 UChar
* dest
, int32_t destCapacity
,
681 UParseError
* parseError
,
684 if(status
== NULL
|| U_FAILURE(*status
)){
687 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
688 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
692 int32_t reqLength
= 0;
693 // UParseError parseError;
695 NamePrepTransform
* prep
= TestIDNA::getInstance(*status
);
697 //initialize pointers to stack buffers
698 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
];
700 int32_t b1Len
, labelLen
;
701 UChar
* delimiter
= (UChar
*)src
;
702 UChar
* labelStart
= (UChar
*)src
;
703 int32_t remainingLen
= srcLength
;
704 int32_t b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
707 // UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0);
708 // UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0);
711 if(U_FAILURE(*status
)){
723 labelLen
= getNextSeparator(labelStart
, -1, prep
, &delimiter
, &done
, status
);
725 if(!(labelLen
==0 && done
)){// make sure this is not a root label separator.
727 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Capacity
,
728 options
, parseError
, status
);
730 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
731 // redo processing of string
732 /* we do not have enough room so grow the buffer*/
733 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
735 *status
= U_MEMORY_ALLOCATION_ERROR
;
739 *status
= U_ZERO_ERROR
; // reset error
741 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Len
,
742 options
, parseError
, status
);
747 if(U_FAILURE(*status
)){
750 int32_t tempLen
= (reqLength
+ b1Len
);
752 if( tempLen
< destCapacity
){
753 uprv_memmove(dest
+reqLength
, b1
, b1Len
* U_SIZEOF_UCHAR
);
758 // add the label separator
760 if(reqLength
< destCapacity
){
761 dest
[reqLength
] = FULL_STOP
;
766 labelStart
= delimiter
;
771 if(delimiter
== src
+srcLength
){
775 labelLen
= getNextSeparator(labelStart
, remainingLen
, prep
, &delimiter
, &done
, status
);
777 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Capacity
,
778 options
,parseError
, status
);
780 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
781 // redo processing of string
782 /* we do not have enough room so grow the buffer*/
783 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
785 *status
= U_MEMORY_ALLOCATION_ERROR
;
789 *status
= U_ZERO_ERROR
; // reset error
791 b1Len
= idnaref_toASCII(labelStart
, labelLen
, b1
, b1Len
,
792 options
, parseError
, status
);
796 if(U_FAILURE(*status
)){
799 int32_t tempLen
= (reqLength
+ b1Len
);
801 if( tempLen
< destCapacity
){
802 uprv_memmove(dest
+reqLength
, b1
, b1Len
* U_SIZEOF_UCHAR
);
807 // add the label separator
809 if(reqLength
< destCapacity
){
810 dest
[reqLength
] = FULL_STOP
;
815 labelStart
= delimiter
;
816 remainingLen
= srcLength
- (delimiter
- src
);
829 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
832 U_CFUNC
int32_t U_EXPORT2
833 idnaref_IDNToUnicode( const UChar
* src
, int32_t srcLength
,
834 UChar
* dest
, int32_t destCapacity
,
836 UParseError
* parseError
,
839 if(status
== NULL
|| U_FAILURE(*status
)){
842 if((src
== NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
843 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
847 int32_t reqLength
= 0;
851 NamePrepTransform
* prep
= TestIDNA::getInstance(*status
);
853 //initialize pointers to stack buffers
854 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
];
856 int32_t b1Len
, labelLen
;
857 UChar
* delimiter
= (UChar
*)src
;
858 UChar
* labelStart
= (UChar
*)src
;
859 int32_t remainingLen
= srcLength
;
860 int32_t b1Capacity
= MAX_LABEL_BUFFER_SIZE
;
863 // UBool allowUnassigned = (UBool)((options & IDNAREF_ALLOW_UNASSIGNED) != 0);
864 // UBool useSTD3ASCIIRules = (UBool)((options & IDNAREF_USE_STD3_RULES) != 0);
866 if(U_FAILURE(*status
)){
877 labelLen
= getNextSeparator(labelStart
, -1, prep
, &delimiter
, &done
, status
);
879 if(labelLen
==0 && done
==FALSE
){
880 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
882 b1Len
= idnaref_toUnicode(labelStart
, labelLen
, b1
, b1Capacity
,
883 options
, parseError
, status
);
885 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
886 // redo processing of string
887 /* we do not have enough room so grow the buffer*/
888 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
890 *status
= U_MEMORY_ALLOCATION_ERROR
;
894 *status
= U_ZERO_ERROR
; // reset error
896 b1Len
= idnaref_toUnicode( labelStart
, labelLen
, b1
, b1Len
,
897 options
, parseError
, status
);
901 if(U_FAILURE(*status
)){
904 int32_t tempLen
= (reqLength
+ b1Len
);
906 if( tempLen
< destCapacity
){
907 uprv_memmove(dest
+reqLength
, b1
, b1Len
* U_SIZEOF_UCHAR
);
911 // add the label separator
913 if(reqLength
< destCapacity
){
914 dest
[reqLength
] = FULL_STOP
;
919 labelStart
= delimiter
;
924 if(delimiter
== src
+srcLength
){
928 labelLen
= getNextSeparator(labelStart
, remainingLen
, prep
, &delimiter
, &done
, status
);
930 if(labelLen
==0 && done
==FALSE
){
931 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
934 b1Len
= idnaref_toUnicode( labelStart
,labelLen
, b1
, b1Capacity
,
935 options
, parseError
, status
);
937 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
938 // redo processing of string
939 /* we do not have enough room so grow the buffer*/
940 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
942 *status
= U_MEMORY_ALLOCATION_ERROR
;
946 *status
= U_ZERO_ERROR
; // reset error
948 b1Len
= idnaref_toUnicode( labelStart
, labelLen
, b1
, b1Len
,
949 options
, parseError
, status
);
953 if(U_FAILURE(*status
)){
956 int32_t tempLen
= (reqLength
+ b1Len
);
958 if( tempLen
< destCapacity
){
959 uprv_memmove(dest
+reqLength
, b1
, b1Len
* U_SIZEOF_UCHAR
);
964 // add the label separator
966 if(reqLength
< destCapacity
){
967 dest
[reqLength
] = FULL_STOP
;
972 labelStart
= delimiter
;
973 remainingLen
= srcLength
- (delimiter
- src
);
985 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
988 U_CFUNC
int32_t U_EXPORT2
989 idnaref_compare( const UChar
*s1
, int32_t length1
,
990 const UChar
*s2
, int32_t length2
,
994 if(status
== NULL
|| U_FAILURE(*status
)){
998 UChar b1Stack
[MAX_IDN_BUFFER_SIZE
], b2Stack
[MAX_IDN_BUFFER_SIZE
];
999 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
1000 int32_t b1Len
, b2Len
, b1Capacity
= MAX_IDN_BUFFER_SIZE
, b2Capacity
= MAX_IDN_BUFFER_SIZE
;
1001 int32_t result
= -1;
1003 UParseError parseError
;
1005 b1Len
= idnaref_IDNToASCII(s1
, length1
, b1
, b1Capacity
, options
, &parseError
, status
);
1006 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
1007 // redo processing of string
1008 /* we do not have enough room so grow the buffer*/
1009 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
1011 *status
= U_MEMORY_ALLOCATION_ERROR
;
1015 *status
= U_ZERO_ERROR
; // reset error
1017 b1Len
= idnaref_IDNToASCII(s1
,length1
,b1
,b1Len
, options
, &parseError
, status
);
1021 b2Len
= idnaref_IDNToASCII(s2
,length2
,b2
,b2Capacity
,options
, &parseError
, status
);
1022 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
1023 // redo processing of string
1024 /* we do not have enough room so grow the buffer*/
1025 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
1027 *status
= U_MEMORY_ALLOCATION_ERROR
;
1031 *status
= U_ZERO_ERROR
; // reset error
1033 b2Len
= idnaref_IDNToASCII(s2
,length2
,b2
,b2Len
,options
, &parseError
, status
);
1036 // when toASCII is applied all label separators are replaced with FULL_STOP
1037 result
= compareCaseInsensitiveASCII(b1
,b1Len
,b2
,b2Len
);
1050 #endif /* #if !UCONFIG_NO_IDNA */