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 */