2 *******************************************************************************
4 * Copyright (C) 2003-2007, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
10 * tab size: 8 (not used)
13 * created on: 2003feb1
14 * created by: Ram Viswanadha
17 #include "unicode/utypes.h"
21 #include "unicode/uidna.h"
22 #include "unicode/ustring.h"
23 #include "unicode/usprep.h"
29 /* it is official IDNA ACE Prefix is "xn--" */
30 static const UChar ACE_PREFIX
[] ={ 0x0078,0x006E,0x002d,0x002d } ;
31 #define ACE_PREFIX_LENGTH 4
33 #define MAX_LABEL_LENGTH 63
35 /* The Max length of the labels should not be more than 64 */
36 #define MAX_LABEL_BUFFER_SIZE 100
37 #define MAX_IDN_BUFFER_SIZE 300
39 #define CAPITAL_A 0x0041
40 #define CAPITAL_Z 0x005A
41 #define LOWER_CASE_DELTA 0x0020
42 #define FULL_STOP 0x002E
43 #define DATA_FILE_NAME "uidna"
46 toASCIILower(UChar ch
){
47 if(CAPITAL_A
<= ch
&& ch
<= CAPITAL_Z
){
48 return ch
+ LOWER_CASE_DELTA
;
54 startsWithPrefix(const UChar
* src
, int32_t srcLength
){
55 UBool startsWithPrefix
= TRUE
;
57 if(srcLength
< ACE_PREFIX_LENGTH
){
61 for(int8_t i
=0; i
< ACE_PREFIX_LENGTH
; i
++){
62 if(toASCIILower(src
[i
]) != ACE_PREFIX
[i
]){
63 startsWithPrefix
= FALSE
;
66 return startsWithPrefix
;
71 compareCaseInsensitiveASCII(const UChar
* s1
, int32_t s1Len
,
72 const UChar
* s2
, int32_t s2Len
){
77 // are we comparing different lengths?
87 // ok the lengths are equal
95 for(int32_t i
=0;/* no condition */;i
++) {
97 /* If we reach the ends of both strings then they match */
105 /* Case-insensitive comparison */
107 rc
=(int32_t)toASCIILower(c1
)-(int32_t)toASCIILower(c2
);
119 * Ascertain if the given code point is a label separator as
120 * defined by the IDNA RFC
122 * @param ch The code point to be ascertained
123 * @return true if the char is a label separator
126 static inline UBool
isLabelSeparator(UChar ch
){
138 // returns the length of the label excluding the separator
139 // if *limit == separator then the length returned does not include
141 static inline int32_t
142 getNextSeparator(UChar
*src
,int32_t srcLength
,
149 *limit
= src
+ i
; // point to null
153 if(isLabelSeparator(src
[i
])){
154 *limit
= src
+ (i
+1); // go past the delimiter
161 for(i
=0;i
<srcLength
;i
++){
162 if(isLabelSeparator(src
[i
])){
163 *limit
= src
+ (i
+1); // go past the delimiter
167 // we have not found the delimiter
169 *limit
= src
+srcLength
;
175 static inline UBool
isLDHChar(UChar ch
){
180 //[\\u002D \\u0030-\\u0039 \\u0041-\\u005A \\u0061-\\u007A]
182 (0x0030 <= ch
&& ch
<= 0x0039) ||
183 (0x0041 <= ch
&& ch
<= 0x005A) ||
184 (0x0061 <= ch
&& ch
<= 0x007A)
192 _internal_toASCII(const UChar
* src
, int32_t srcLength
,
193 UChar
* dest
, int32_t destCapacity
,
195 UStringPrepProfile
* nameprep
,
196 UParseError
* parseError
,
199 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
];
200 //initialize pointers to stack buffers
201 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
202 int32_t b1Len
=0, b2Len
,
203 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
204 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
207 int32_t namePrepOptions
= ((options
& UIDNA_ALLOW_UNASSIGNED
) != 0) ? USPREP_ALLOW_UNASSIGNED
: 0;
208 UBool
* caseFlags
= NULL
;
210 // the source contains all ascii codepoints
211 UBool srcIsASCII
= TRUE
;
212 // assume the source contains all LDH codepoints
213 UBool srcIsLDH
= TRUE
;
218 UBool useSTD3ASCIIRules
= (UBool
)((options
& UIDNA_USE_STD3_RULES
) != 0);
220 int32_t failPos
= -1;
223 srcLength
= u_strlen(src
);
226 if(srcLength
> b1Capacity
){
227 b1
= (UChar
*) uprv_malloc(srcLength
* U_SIZEOF_UCHAR
);
229 *status
= U_MEMORY_ALLOCATION_ERROR
;
232 b1Capacity
= srcLength
;
236 for( j
=0;j
<srcLength
;j
++){
240 b1
[b1Len
++] = src
[j
];
243 // step 2 is performed only if the source contains non ASCII
244 if(srcIsASCII
== FALSE
){
247 b1Len
= usprep_prepare(nameprep
, src
, srcLength
, b1
, b1Capacity
, namePrepOptions
, parseError
, status
);
249 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
250 // redo processing of string
251 // we do not have enough room so grow the buffer
255 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
257 *status
= U_MEMORY_ALLOCATION_ERROR
;
261 *status
= U_ZERO_ERROR
; // reset error
263 b1Len
= usprep_prepare(nameprep
, src
, srcLength
, b1
, b1Len
, namePrepOptions
, parseError
, status
);
267 if(U_FAILURE(*status
)){
271 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
277 for( j
=0;j
<b1Len
;j
++){
278 // check if output of usprep_prepare is all ASCII
281 }else if(isLDHChar(b1
[j
])==FALSE
){ // if the char is in ASCII range verify that it is an LDH character
286 if(useSTD3ASCIIRules
== TRUE
){
288 // 3(a) Verify the absence of non-LDH ASCII code points; that is, the
289 // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
290 // 3(b) Verify the absence of leading and trailing hyphen-minus; that
291 // is, the absence of U+002D at the beginning and end of the
293 if( srcIsLDH
== FALSE
/* source at this point should not contain anyLDH characters */
294 || b1
[0] == HYPHEN
|| b1
[b1Len
-1] == HYPHEN
){
295 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
297 /* populate the parseError struct */
299 // failPos is always set the index of failure
300 uprv_syntaxError(b1
,failPos
, b1Len
,parseError
);
301 }else if(b1
[0] == HYPHEN
){
302 // fail position is 0
303 uprv_syntaxError(b1
,0,b1Len
,parseError
);
305 // the last index in the source is always length-1
306 uprv_syntaxError(b1
, (b1Len
>0) ? b1Len
-1 : b1Len
, b1Len
,parseError
);
312 // Step 4: if the source is ASCII then proceed to step 8
314 if(b1Len
<= destCapacity
){
315 uprv_memmove(dest
, b1
, b1Len
* U_SIZEOF_UCHAR
);
322 // step 5 : verify the sequence does not begin with ACE prefix
323 if(!startsWithPrefix(b1
,b1Len
)){
325 //step 6: encode the sequence with punycode
327 // do not preserve the case flags for now!
328 // TODO: Preserve the case while implementing the RFE
329 // caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
330 // uprv_memset(caseFlags,TRUE,b1Len);
332 b2Len
= u_strToPunycode(b1
,b1Len
,b2
,b2Capacity
,caseFlags
, status
);
334 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
335 // redo processing of string
336 /* we do not have enough room so grow the buffer*/
337 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
339 *status
= U_MEMORY_ALLOCATION_ERROR
;
343 *status
= U_ZERO_ERROR
; // reset error
345 b2Len
= u_strToPunycode(b1
,b1Len
,b2
,b2Len
,caseFlags
, status
);
348 if(U_FAILURE(*status
)){
351 // TODO : Reconsider while implementing the case preserve RFE
352 // convert all codepoints to lower case ASCII
353 // toASCIILower(b2,b2Len);
354 reqLength
= b2Len
+ACE_PREFIX_LENGTH
;
356 if(reqLength
> destCapacity
){
357 *status
= U_BUFFER_OVERFLOW_ERROR
;
360 //Step 7: prepend the ACE prefix
361 uprv_memcpy(dest
,ACE_PREFIX
,ACE_PREFIX_LENGTH
* U_SIZEOF_UCHAR
);
362 //Step 6: copy the contents in b2 into dest
363 uprv_memcpy(dest
+ACE_PREFIX_LENGTH
, b2
, b2Len
* U_SIZEOF_UCHAR
);
366 *status
= U_IDNA_ACE_PREFIX_ERROR
;
367 //position of failure is 0
368 uprv_syntaxError(b1
,0,b1Len
,parseError
);
372 // step 8: verify the length of lable
373 if(reqLength
> MAX_LABEL_LENGTH
){
374 *status
= U_IDNA_LABEL_TOO_LONG_ERROR
;
384 uprv_free(caseFlags
);
386 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
390 _internal_toUnicode(const UChar
* src
, int32_t srcLength
,
391 UChar
* dest
, int32_t destCapacity
,
393 UStringPrepProfile
* nameprep
,
394 UParseError
* parseError
,
398 UBool useSTD3ASCIIRules
= (UBool
)((options
& UIDNA_USE_STD3_RULES
) != 0);
399 int32_t namePrepOptions
= ((options
& UIDNA_ALLOW_UNASSIGNED
) != 0) ? USPREP_ALLOW_UNASSIGNED
: 0;
401 UChar b1Stack
[MAX_LABEL_BUFFER_SIZE
], b2Stack
[MAX_LABEL_BUFFER_SIZE
], b3Stack
[MAX_LABEL_BUFFER_SIZE
];
403 //initialize pointers to stack buffers
404 UChar
*b1
= b1Stack
, *b2
= b2Stack
, *b1Prime
=NULL
, *b3
=b3Stack
;
405 int32_t b1Len
, b2Len
, b1PrimeLen
, b3Len
,
406 b1Capacity
= MAX_LABEL_BUFFER_SIZE
,
407 b2Capacity
= MAX_LABEL_BUFFER_SIZE
,
408 b3Capacity
= MAX_LABEL_BUFFER_SIZE
,
412 UBool
* caseFlags
= NULL
;
414 UBool srcIsASCII
= TRUE
;
415 UBool srcIsLDH
= TRUE
;
418 // step 1: find out if all the codepoints in src are ASCII
421 for(;src
[srcLength
]!=0;){
422 if(src
[srcLength
]> 0x7f){
424 }else if(isLDHChar(src
[srcLength
])==FALSE
){
425 // here we do not assemble surrogates
426 // since we know that LDH code points
427 // are in the ASCII range only
433 }else if(srcLength
> 0){
434 for(int32_t j
=0; j
<srcLength
; j
++){
437 }else if(isLDHChar(src
[j
])==FALSE
){
438 // here we do not assemble surrogates
439 // since we know that LDH code points
440 // are in the ASCII range only
449 if(srcIsASCII
== FALSE
){
450 // step 2: process the string
451 b1Len
= usprep_prepare(nameprep
, src
, srcLength
, b1
, b1Capacity
, namePrepOptions
, parseError
, status
);
452 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
453 // redo processing of string
454 /* we do not have enough room so grow the buffer*/
455 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
457 *status
= U_MEMORY_ALLOCATION_ERROR
;
461 *status
= U_ZERO_ERROR
; // reset error
463 b1Len
= usprep_prepare(nameprep
, src
, srcLength
, b1
, b1Len
, namePrepOptions
, parseError
, status
);
466 if(U_FAILURE(*status
)){
471 //just point src to b1
476 //step 3: verify ACE Prefix
477 if(startsWithPrefix(src
,srcLength
)){
479 //step 4: Remove the ACE Prefix
480 b1Prime
= b1
+ ACE_PREFIX_LENGTH
;
481 b1PrimeLen
= b1Len
- ACE_PREFIX_LENGTH
;
483 //step 5: Decode using punycode
484 b2Len
= u_strFromPunycode(b1Prime
, b1PrimeLen
, b2
, b2Capacity
, caseFlags
,status
);
486 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
487 // redo processing of string
488 /* we do not have enough room so grow the buffer*/
489 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
491 *status
= U_MEMORY_ALLOCATION_ERROR
;
495 *status
= U_ZERO_ERROR
; // reset error
497 b2Len
= u_strFromPunycode(b1Prime
, b1PrimeLen
, b2
, b2Len
, caseFlags
, status
);
501 //step 6:Apply toASCII
502 b3Len
= uidna_toASCII(b2
, b2Len
, b3
, b3Capacity
,options
,parseError
, status
);
504 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
505 // redo processing of string
506 /* we do not have enough room so grow the buffer*/
507 b3
= (UChar
*) uprv_malloc(b3Len
* U_SIZEOF_UCHAR
);
509 *status
= U_MEMORY_ALLOCATION_ERROR
;
513 *status
= U_ZERO_ERROR
; // reset error
515 b3Len
= uidna_toASCII(b2
,b2Len
,b3
,b3Len
,options
,parseError
, status
);
520 if(U_FAILURE(*status
)){
525 if(compareCaseInsensitiveASCII(b1
, b1Len
, b3
, b3Len
) !=0){
526 *status
= U_IDNA_VERIFICATION_ERROR
;
530 //step 8: return output of step 5
532 if(b2Len
<= destCapacity
) {
533 uprv_memmove(dest
, b2
, b2Len
* U_SIZEOF_UCHAR
);
536 // verify that STD3 ASCII rules are satisfied
537 if(useSTD3ASCIIRules
== TRUE
){
538 if( srcIsLDH
== FALSE
/* source contains some non-LDH characters */
539 || src
[0] == HYPHEN
|| src
[srcLength
-1] == HYPHEN
){
540 *status
= U_IDNA_STD3_ASCII_RULES_ERROR
;
542 /* populate the parseError struct */
544 // failPos is always set the index of failure
545 uprv_syntaxError(src
,failPos
, srcLength
,parseError
);
546 }else if(src
[0] == HYPHEN
){
547 // fail position is 0
548 uprv_syntaxError(src
,0,srcLength
,parseError
);
550 // the last index in the source is always length-1
551 uprv_syntaxError(src
, (srcLength
>0) ? srcLength
-1 : srcLength
, srcLength
,parseError
);
557 //copy the source to destination
558 if(srcLength
<= destCapacity
){
559 uprv_memmove(dest
,src
,srcLength
* U_SIZEOF_UCHAR
);
561 reqLength
= srcLength
;
566 if(b1
!= b1Stack
&& b1
!=src
){
572 uprv_free(caseFlags
);
575 // The RFC states that
577 // ToUnicode never fails. If any step fails, then the original input
578 // is returned immediately in that step.
580 // So if any step fails lets copy source to destination
581 if(U_FAILURE(*status
)){
582 //copy the source to destination
583 if(dest
&& srcLength
<= destCapacity
){
584 if(srcLength
== -1) {
585 uprv_memmove(dest
,src
,u_strlen(src
)* U_SIZEOF_UCHAR
);
587 uprv_memmove(dest
,src
,srcLength
* U_SIZEOF_UCHAR
);
590 reqLength
= srcLength
;
593 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
596 U_CAPI
int32_t U_EXPORT2
597 uidna_toASCII(const UChar
* src
, int32_t srcLength
,
598 UChar
* dest
, int32_t destCapacity
,
600 UParseError
* parseError
,
603 if(status
== NULL
|| U_FAILURE(*status
)){
606 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
607 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
611 UStringPrepProfile
* nameprep
= usprep_open(NULL
,DATA_FILE_NAME
, status
);
613 if(U_FAILURE(*status
)){
617 int32_t retLen
= _internal_toASCII(src
, srcLength
, dest
, destCapacity
, options
, nameprep
, parseError
, status
);
619 /* close the profile*/
620 usprep_close(nameprep
);
625 U_CAPI
int32_t U_EXPORT2
626 uidna_toUnicode(const UChar
* src
, int32_t srcLength
,
627 UChar
* dest
, int32_t destCapacity
,
629 UParseError
* parseError
,
632 if(status
== NULL
|| U_FAILURE(*status
)){
635 if( (src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
636 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
640 UStringPrepProfile
* nameprep
= usprep_open(NULL
, DATA_FILE_NAME
, status
);
642 if(U_FAILURE(*status
)){
646 int32_t retLen
= _internal_toUnicode(src
, srcLength
, dest
, destCapacity
, options
, nameprep
, parseError
, status
);
648 usprep_close(nameprep
);
654 U_CAPI
int32_t U_EXPORT2
655 uidna_IDNToASCII( const UChar
*src
, int32_t srcLength
,
656 UChar
* dest
, int32_t destCapacity
,
658 UParseError
*parseError
,
661 if(status
== NULL
|| U_FAILURE(*status
)){
664 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
665 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
669 int32_t reqLength
= 0;
671 UStringPrepProfile
* nameprep
= usprep_open(NULL
, DATA_FILE_NAME
, status
);
673 if(U_FAILURE(*status
)){
677 //initialize pointers
678 UChar
*delimiter
= (UChar
*)src
;
679 UChar
*labelStart
= (UChar
*)src
;
680 UChar
*currentDest
= (UChar
*) dest
;
681 int32_t remainingLen
= srcLength
;
682 int32_t remainingDestCapacity
= destCapacity
;
683 int32_t labelLen
= 0, labelReqLength
= 0;
689 labelLen
= getNextSeparator(labelStart
,remainingLen
, &delimiter
,&done
);
691 if(!(labelLen
==0 && done
)){// make sure this is not a root label separator.
693 labelReqLength
= _internal_toASCII( labelStart
, labelLen
,
694 currentDest
, remainingDestCapacity
,
698 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
700 *status
= U_ZERO_ERROR
; // reset error
701 remainingDestCapacity
= 0;
706 if(U_FAILURE(*status
)){
710 reqLength
+=labelReqLength
;
711 // adjust the destination pointer
712 if(labelReqLength
< remainingDestCapacity
){
713 currentDest
= currentDest
+ labelReqLength
;
714 remainingDestCapacity
-= labelReqLength
;
716 // should never occur
717 remainingDestCapacity
= 0;
723 // add the label separator
724 if(remainingDestCapacity
> 0){
725 *currentDest
++ = FULL_STOP
;
726 remainingDestCapacity
--;
730 labelStart
= delimiter
;
731 if(remainingLen
>0 ){
732 remainingLen
= (int32_t)(srcLength
- (delimiter
- src
));
737 usprep_close(nameprep
);
739 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
742 U_CAPI
int32_t U_EXPORT2
743 uidna_IDNToUnicode( const UChar
* src
, int32_t srcLength
,
744 UChar
* dest
, int32_t destCapacity
,
746 UParseError
* parseError
,
749 if(status
== NULL
|| U_FAILURE(*status
)){
752 if((src
==NULL
) || (srcLength
< -1) || (destCapacity
<0) || (!dest
&& destCapacity
> 0)){
753 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
757 int32_t reqLength
= 0;
759 UStringPrepProfile
* nameprep
= usprep_open(NULL
, DATA_FILE_NAME
, status
);
761 if(U_FAILURE(*status
)){
765 //initialize pointers
766 UChar
*delimiter
= (UChar
*)src
;
767 UChar
*labelStart
= (UChar
*)src
;
768 UChar
*currentDest
= (UChar
*) dest
;
769 int32_t remainingLen
= srcLength
;
770 int32_t remainingDestCapacity
= destCapacity
;
771 int32_t labelLen
= 0, labelReqLength
= 0;
777 labelLen
= getNextSeparator(labelStart
,remainingLen
, &delimiter
,&done
);
779 if(labelLen
==0 && done
==FALSE
){
780 *status
= U_IDNA_ZERO_LENGTH_LABEL_ERROR
;
782 labelReqLength
= _internal_toUnicode(labelStart
, labelLen
,
783 currentDest
, remainingDestCapacity
,
787 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
789 *status
= U_ZERO_ERROR
; // reset error
790 remainingDestCapacity
= 0;
794 if(U_FAILURE(*status
)){
798 reqLength
+=labelReqLength
;
799 // adjust the destination pointer
800 if(labelReqLength
< remainingDestCapacity
){
801 currentDest
= currentDest
+ labelReqLength
;
802 remainingDestCapacity
-= labelReqLength
;
804 // should never occur
805 remainingDestCapacity
= 0;
812 // add the label separator
813 if(remainingDestCapacity
> 0){
814 *currentDest
++ = FULL_STOP
;
815 remainingDestCapacity
--;
819 labelStart
= delimiter
;
820 if(remainingLen
>0 ){
821 remainingLen
= (int32_t)(srcLength
- (delimiter
- src
));
826 usprep_close(nameprep
);
828 return u_terminateUChars(dest
, destCapacity
, reqLength
, status
);
831 U_CAPI
int32_t U_EXPORT2
832 uidna_compare( const UChar
*s1
, int32_t length1
,
833 const UChar
*s2
, int32_t length2
,
837 if(status
== NULL
|| U_FAILURE(*status
)){
841 UChar b1Stack
[MAX_IDN_BUFFER_SIZE
], b2Stack
[MAX_IDN_BUFFER_SIZE
];
842 UChar
*b1
= b1Stack
, *b2
= b2Stack
;
843 int32_t b1Len
, b2Len
, b1Capacity
= MAX_IDN_BUFFER_SIZE
, b2Capacity
= MAX_IDN_BUFFER_SIZE
;
846 UParseError parseError
;
848 b1Len
= uidna_IDNToASCII(s1
, length1
, b1
, b1Capacity
, options
, &parseError
, status
);
849 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
850 // redo processing of string
851 b1
= (UChar
*) uprv_malloc(b1Len
* U_SIZEOF_UCHAR
);
853 *status
= U_MEMORY_ALLOCATION_ERROR
;
857 *status
= U_ZERO_ERROR
; // reset error
859 b1Len
= uidna_IDNToASCII(s1
,length1
,b1
,b1Len
, options
, &parseError
, status
);
863 b2Len
= uidna_IDNToASCII(s2
,length2
, b2
,b2Capacity
, options
, &parseError
, status
);
864 if(*status
== U_BUFFER_OVERFLOW_ERROR
){
865 // redo processing of string
866 b2
= (UChar
*) uprv_malloc(b2Len
* U_SIZEOF_UCHAR
);
868 *status
= U_MEMORY_ALLOCATION_ERROR
;
872 *status
= U_ZERO_ERROR
; // reset error
874 b2Len
= uidna_IDNToASCII(s2
, length2
, b2
, b2Len
, options
, &parseError
, status
);
877 // when toASCII is applied all label separators are replaced with FULL_STOP
878 result
= compareCaseInsensitiveASCII(b1
,b1Len
,b2
,b2Len
);
892 #endif /* #if !UCONFIG_NO_IDNA */