1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *******************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   Copyright (C) 2003-2009, International Business Machines
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   Corporation and others.  All Rights Reserved.
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *******************************************************************************
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   file name:  uidna.cpp
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   encoding:   US-ASCII
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   tab size:   8 (not used)
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   indentation:4
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   created on: 2003feb1
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   created by: Ram Viswanadha
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_IDNA
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uidna.h"
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ustring.h"
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/usprep.h"
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "punycode.h"
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ustr_imp.h"
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h"
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h"
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "sprpimpl.h"
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* it is official IDNA ACE Prefix is "xn--" */
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar ACE_PREFIX[] ={ 0x0078,0x006E,0x002d,0x002d } ;
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define ACE_PREFIX_LENGTH 4
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MAX_LABEL_LENGTH 63
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* The Max length of the labels should not be more than MAX_LABEL_LENGTH */
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MAX_LABEL_BUFFER_SIZE 100
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MAX_DOMAIN_NAME_LENGTH 255
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* The Max length of the domain names should not be more than MAX_DOMAIN_NAME_LENGTH */
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MAX_IDN_BUFFER_SIZE   MAX_DOMAIN_NAME_LENGTH+1
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define LOWER_CASE_DELTA 0x0020
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define HYPHEN           0x002D
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FULL_STOP        0x002E
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define CAPITAL_A        0x0041
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define CAPITAL_Z        0x005A
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)inline static UChar
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)toASCIILower(UChar ch){
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(CAPITAL_A <= ch && ch <= CAPITAL_Z){
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return ch + LOWER_CASE_DELTA;
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return ch;
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)inline static UBool
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)startsWithPrefix(const UChar* src , int32_t srcLength){
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool startsWithPrefix = TRUE;
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength < ACE_PREFIX_LENGTH){
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(int8_t i=0; i< ACE_PREFIX_LENGTH; i++){
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(toASCIILower(src[i]) != ACE_PREFIX[i]){
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            startsWithPrefix = FALSE;
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return startsWithPrefix;
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)inline static int32_t
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)compareCaseInsensitiveASCII(const UChar* s1, int32_t s1Len,
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            const UChar* s2, int32_t s2Len){
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t minLength;
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t lengthResult;
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // are we comparing different lengths?
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(s1Len != s2Len) {
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(s1Len < s2Len) {
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            minLength = s1Len;
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            lengthResult = -1;
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            minLength = s2Len;
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            lengthResult = 1;
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // ok the lengths are equal
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        minLength = s1Len;
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        lengthResult = 0;
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar c1,c2;
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t rc;
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(int32_t i =0;/* no condition */;i++) {
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* If we reach the ends of both strings then they match */
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(i == minLength) {
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return lengthResult;
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c1 = s1[i];
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c2 = s2[i];
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Case-insensitive comparison */
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(c1!=c2) {
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            rc=(int32_t)toASCIILower(c1)-(int32_t)toASCIILower(c2);
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(rc!=0) {
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                lengthResult=rc;
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return lengthResult;
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Ascertain if the given code point is a label separator as
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * defined by the IDNA RFC
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param ch The code point to be ascertained
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @return true if the char is a label separator
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @stable ICU 2.8
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static inline UBool isLabelSeparator(UChar ch){
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    switch(ch){
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case 0x002e:
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case 0x3002:
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case 0xFF0E:
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case 0xFF61:
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return TRUE;
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        default:
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return FALSE;
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// returns the length of the label excluding the separator
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// if *limit == separator then the length returned does not include
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// the separtor.
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static inline int32_t
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)getNextSeparator(UChar *src, int32_t srcLength,
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 UChar **limit, UBool *done){
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength == -1){
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t i;
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(i=0 ; ;i++){
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(src[i] == 0){
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *limit = src + i; // point to null
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *done = TRUE;
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return i;
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(isLabelSeparator(src[i])){
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *limit = src + (i+1); // go past the delimiter
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return i;
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }else{
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t i;
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(i=0;i<srcLength;i++){
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(isLabelSeparator(src[i])){
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *limit = src + (i+1); // go past the delimiter
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return i;
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // we have not found the delimiter
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // if(i==srcLength)
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *limit = src+srcLength;
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *done = TRUE;
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return i;
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static inline UBool isLDHChar(UChar ch){
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // high runner case
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(ch>0x007A){
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //[\\u002D \\u0030-\\u0039 \\u0041-\\u005A \\u0061-\\u007A]
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if( (ch==0x002D) ||
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (0x0030 <= ch && ch <= 0x0039) ||
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (0x0041 <= ch && ch <= 0x005A) ||
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (0x0061 <= ch && ch <= 0x007A)
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)      ){
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return TRUE;
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return FALSE;
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)_internal_toASCII(const UChar* src, int32_t srcLength,
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  UChar* dest, int32_t destCapacity,
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  int32_t options,
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  UStringPrepProfile* nameprep,
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  UParseError* parseError,
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  UErrorCode* status)
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too.
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE];
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //initialize pointers to stack buffers
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar  *b1 = b1Stack, *b2 = b2Stack;
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t b1Len=0, b2Len,
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1Capacity = MAX_LABEL_BUFFER_SIZE,
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b2Capacity = MAX_LABEL_BUFFER_SIZE ,
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            reqLength=0;
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0;
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool* caseFlags = NULL;
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // the source contains all ascii codepoints
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool srcIsASCII  = TRUE;
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // assume the source contains all LDH codepoints
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool srcIsLDH = TRUE;
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t j=0;
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //get the options
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0);
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t failPos = -1;
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength == -1){
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcLength = u_strlen(src);
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength > b1Capacity){
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1 = (UChar*) uprv_malloc(srcLength * U_SIZEOF_UCHAR);
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b1==NULL){
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_MEMORY_ALLOCATION_ERROR;
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Capacity = srcLength;
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // step 1
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for( j=0;j<srcLength;j++){
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(src[j] > 0x7F){
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcIsASCII = FALSE;
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1[b1Len++] = src[j];
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // step 2 is performed only if the source contains non ASCII
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcIsASCII == FALSE){
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // step 2
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*status == U_BUFFER_OVERFLOW_ERROR){
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // redo processing of string
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // we do not have enough room so grow the buffer
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(b1 != b1Stack){
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uprv_free(b1);
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(b1==NULL){
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_MEMORY_ALLOCATION_ERROR;
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_ZERO_ERROR; // reset error
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // error bail out
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto CLEANUP;
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b1Len == 0){
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR;
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto CLEANUP;
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // for step 3 & 4
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcIsASCII = TRUE;
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for( j=0;j<b1Len;j++){
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // check if output of usprep_prepare is all ASCII
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b1[j] > 0x7F){
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcIsASCII = FALSE;
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }else if(isLDHChar(b1[j])==FALSE){  // if the char is in ASCII range verify that it is an LDH character
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcIsLDH = FALSE;
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            failPos = j;
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(useSTD3ASCIIRules == TRUE){
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // verify 3a and 3b
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // 3(a) Verify the absence of non-LDH ASCII code points; that is, the
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //  absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // 3(b) Verify the absence of leading and trailing hyphen-minus; that
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //  is, the absence of U+002D at the beginning and end of the
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //  sequence.
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if( srcIsLDH == FALSE /* source at this point should not contain anyLDH characters */
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            || b1[0] ==  HYPHEN || b1[b1Len-1] == HYPHEN){
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_IDNA_STD3_ASCII_RULES_ERROR;
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* populate the parseError struct */
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(srcIsLDH==FALSE){
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // failPos is always set the index of failure
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uprv_syntaxError(b1,failPos, b1Len,parseError);
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }else if(b1[0] == HYPHEN){
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // fail position is 0
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uprv_syntaxError(b1,0,b1Len,parseError);
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }else{
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // the last index in the source is always length-1
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uprv_syntaxError(b1, (b1Len>0) ? b1Len-1 : b1Len, b1Len,parseError);
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Step 4: if the source is ASCII then proceed to step 8
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcIsASCII){
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b1Len <= destCapacity){
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memmove(dest, b1, b1Len * U_SIZEOF_UCHAR);
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            reqLength = b1Len;
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }else{
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            reqLength = b1Len;
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }else{
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // step 5 : verify the sequence does not begin with ACE prefix
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(!startsWithPrefix(b1,b1Len)){
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            //step 6: encode the sequence with punycode
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // do not preserve the case flags for now!
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // TODO: Preserve the case while implementing the RFE
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // uprv_memset(caseFlags,TRUE,b1Len);
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b2Len = u_strToPunycode(b1,b1Len,b2,b2Capacity,caseFlags, status);
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*status == U_BUFFER_OVERFLOW_ERROR){
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // redo processing of string
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* we do not have enough room so grow the buffer*/
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(b2 == NULL){
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    *status = U_MEMORY_ALLOCATION_ERROR;
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    goto CLEANUP;
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_ZERO_ERROR; // reset error
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                b2Len = u_strToPunycode(b1,b1Len,b2,b2Len,caseFlags, status);
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            //error bail out
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(U_FAILURE(*status)){
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // TODO : Reconsider while implementing the case preserve RFE
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // convert all codepoints to lower case ASCII
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // toASCIILower(b2,b2Len);
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            reqLength = b2Len+ACE_PREFIX_LENGTH;
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(reqLength > destCapacity){
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_BUFFER_OVERFLOW_ERROR;
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            //Step 7: prepend the ACE prefix
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memcpy(dest,ACE_PREFIX,ACE_PREFIX_LENGTH * U_SIZEOF_UCHAR);
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            //Step 6: copy the contents in b2 into dest
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memcpy(dest+ACE_PREFIX_LENGTH, b2, b2Len * U_SIZEOF_UCHAR);
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }else{
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_IDNA_ACE_PREFIX_ERROR;
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            //position of failure is 0
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_syntaxError(b1,0,b1Len,parseError);
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // step 8: verify the length of label
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(reqLength > MAX_LABEL_LENGTH){
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_IDNA_LABEL_TOO_LONG_ERROR;
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CLEANUP:
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b1 != b1Stack){
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b1);
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b2 != b2Stack){
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b2);
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(caseFlags);
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_terminateUChars(dest, destCapacity, reqLength, status);
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)_internal_toUnicode(const UChar* src, int32_t srcLength,
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UChar* dest, int32_t destCapacity,
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    int32_t options,
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UStringPrepProfile* nameprep,
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UParseError* parseError,
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UErrorCode* status)
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //get the options
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0);
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0;
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too.
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE], b3Stack[MAX_LABEL_BUFFER_SIZE];
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //initialize pointers to stack buffers
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar  *b1 = b1Stack, *b2 = b2Stack, *b1Prime=NULL, *b3=b3Stack;
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t b1Len, b2Len, b1PrimeLen, b3Len,
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1Capacity = MAX_LABEL_BUFFER_SIZE,
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b2Capacity = MAX_LABEL_BUFFER_SIZE,
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b3Capacity = MAX_LABEL_BUFFER_SIZE,
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            reqLength=0;
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    b1Len = 0;
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool* caseFlags = NULL;
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool srcIsASCII = TRUE;
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*UBool srcIsLDH = TRUE;
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t failPos =0;*/
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // step 1: find out if all the codepoints in src are ASCII
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength==-1){
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcLength = 0;
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(;src[srcLength]!=0;){
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(src[srcLength]> 0x7f){
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                srcIsASCII = FALSE;
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }/*else if(isLDHChar(src[srcLength])==FALSE){
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // here we do not assemble surrogates
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // since we know that LDH code points
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // are in the ASCII range only
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                srcIsLDH = FALSE;
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                failPos = srcLength;
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }*/
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcLength++;
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }else if(srcLength > 0){
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(int32_t j=0; j<srcLength; j++){
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(src[j]> 0x7f){
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                srcIsASCII = FALSE;
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }/*else if(isLDHChar(src[j])==FALSE){
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // here we do not assemble surrogates
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // since we know that LDH code points
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // are in the ASCII range only
447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                srcIsLDH = FALSE;
448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                failPos = j;
449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }*/
450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }else{
452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcIsASCII == FALSE){
456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // step 2: process the string
457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*status == U_BUFFER_OVERFLOW_ERROR){
459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // redo processing of string
460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* we do not have enough room so grow the buffer*/
461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(b1==NULL){
463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_MEMORY_ALLOCATION_ERROR;
464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_ZERO_ERROR; // reset error
468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //bail out on error
472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_FAILURE(*status)){
473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }else{
476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //just point src to b1
478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1 = (UChar*) src;
479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Len = srcLength;
480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // The RFC states that
483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // <quote>
484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // ToUnicode never fails. If any step fails, then the original input
485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // is returned immediately in that step.
486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // </quote>
487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //step 3: verify ACE Prefix
489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(startsWithPrefix(b1,b1Len)){
490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //step 4: Remove the ACE Prefix
492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Prime = b1 + ACE_PREFIX_LENGTH;
493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1PrimeLen  = b1Len - ACE_PREFIX_LENGTH;
494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //step 5: Decode using punycode
496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Capacity, caseFlags,status);
497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*status == U_BUFFER_OVERFLOW_ERROR){
499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // redo processing of string
500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* we do not have enough room so grow the buffer*/
501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(b2==NULL){
503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_MEMORY_ALLOCATION_ERROR;
504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_ZERO_ERROR; // reset error
508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b2Len =  u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Len, caseFlags, status);
510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //step 6:Apply toASCII
514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b3Len = uidna_toASCII(b2, b2Len, b3, b3Capacity, options, parseError, status);
515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*status == U_BUFFER_OVERFLOW_ERROR){
517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // redo processing of string
518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* we do not have enough room so grow the buffer*/
519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b3 = (UChar*) uprv_malloc(b3Len * U_SIZEOF_UCHAR);
520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(b3==NULL){
521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_MEMORY_ALLOCATION_ERROR;
522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_ZERO_ERROR; // reset error
526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            b3Len =  uidna_toASCII(b2,b2Len,b3,b3Len,options,parseError, status);
528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //bail out on error
531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_FAILURE(*status)){
532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //step 7: verify
536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(compareCaseInsensitiveASCII(b1, b1Len, b3, b3Len) !=0){
537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Cause the original to be returned.
538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_IDNA_VERIFICATION_ERROR;
539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //step 8: return output of step 5
543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength = b2Len;
544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b2Len <= destCapacity) {
545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memmove(dest, b2, b2Len * U_SIZEOF_UCHAR);
546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else{
549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // See the start of this if statement for why this is commented out.
550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // verify that STD3 ASCII rules are satisfied
551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*if(useSTD3ASCIIRules == TRUE){
552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if( srcIsLDH == FALSE // source contains some non-LDH characters
553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                || src[0] ==  HYPHEN || src[srcLength-1] == HYPHEN){
554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_IDNA_STD3_ASCII_RULES_ERROR;
555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // populate the parseError struct
557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(srcIsLDH==FALSE){
558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // failPos is always set the index of failure
559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    uprv_syntaxError(src,failPos, srcLength,parseError);
560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }else if(src[0] == HYPHEN){
561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // fail position is 0
562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    uprv_syntaxError(src,0,srcLength,parseError);
563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }else{
564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // the last index in the source is always length-1
565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    uprv_syntaxError(src, (srcLength>0) ? srcLength-1 : srcLength, srcLength,parseError);
566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto CLEANUP;
569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }*/
571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // just return the source
572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //copy the source to destination
573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(srcLength <= destCapacity){
574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR);
575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength = srcLength;
577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CLEANUP:
581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b1 != b1Stack && b1!=src){
583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b1);
584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b2 != b2Stack){
586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b2);
587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(caseFlags);
589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // The RFC states that
591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // <quote>
592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // ToUnicode never fails. If any step fails, then the original input
593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // is returned immediately in that step.
594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // </quote>
595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // So if any step fails lets copy source to destination
596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        //copy the source to destination
598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(dest && srcLength <= destCapacity){
599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // srcLength should have already been set earlier.
600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U_ASSERT(srcLength >= 0);
601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memmove(dest,src,srcLength * U_SIZEOF_UCHAR);
602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength = srcLength;
604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ZERO_ERROR;
605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_terminateUChars(dest, destCapacity, reqLength, status);
608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uidna_toASCII(const UChar* src, int32_t srcLength,
612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UChar* dest, int32_t destCapacity,
613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              int32_t options,
614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UParseError* parseError,
615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UErrorCode* status){
616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(status == NULL || U_FAILURE(*status)){
618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ILLEGAL_ARGUMENT_ERROR;
622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return -1;
629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t retLen = _internal_toASCII(src, srcLength, dest, destCapacity, options, nameprep, parseError, status);
632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* close the profile*/
634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    usprep_close(nameprep);
635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return retLen;
637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uidna_toUnicode(const UChar* src, int32_t srcLength,
641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UChar* dest, int32_t destCapacity,
642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                int32_t options,
643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UParseError* parseError,
644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UErrorCode* status){
645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(status == NULL || U_FAILURE(*status)){
647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if( (src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ILLEGAL_ARGUMENT_ERROR;
651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return -1;
658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t retLen = _internal_toUnicode(src, srcLength, dest, destCapacity, options, nameprep, parseError, status);
661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    usprep_close(nameprep);
663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return retLen;
665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uidna_IDNToASCII(  const UChar *src, int32_t srcLength,
670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UChar* dest, int32_t destCapacity,
671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   int32_t options,
672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UParseError *parseError,
673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UErrorCode *status){
674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(status == NULL || U_FAILURE(*status)){
676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ILLEGAL_ARGUMENT_ERROR;
680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t reqLength = 0;
684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //initialize pointers
692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *delimiter = (UChar*)src;
693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *labelStart = (UChar*)src;
694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *currentDest = (UChar*) dest;
695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t remainingLen = srcLength;
696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t remainingDestCapacity = destCapacity;
697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t labelLen = 0, labelReqLength = 0;
698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool done = FALSE;
699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(;;){
702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done);
704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelReqLength = 0;
705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(!(labelLen==0 && done)){// make sure this is not a root label separator.
706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            labelReqLength = _internal_toASCII( labelStart, labelLen,
708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                currentDest, remainingDestCapacity,
709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                options, nameprep,
710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                parseError, status);
711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*status == U_BUFFER_OVERFLOW_ERROR){
713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *status = U_ZERO_ERROR; // reset error
715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                remainingDestCapacity = 0;
716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_FAILURE(*status)){
721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength +=labelReqLength;
725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // adjust the destination pointer
726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(labelReqLength < remainingDestCapacity){
727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            currentDest = currentDest + labelReqLength;
728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity -= labelReqLength;
729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }else{
730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // should never occur
731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity = 0;
732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(done == TRUE){
735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // add the label separator
739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(remainingDestCapacity > 0){
740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *currentDest++ = FULL_STOP;
741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity--;
742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength++;
744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelStart = delimiter;
746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(remainingLen >0 ){
747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingLen = (int32_t)(srcLength - (delimiter - src));
748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(reqLength > MAX_DOMAIN_NAME_LENGTH){
753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR;
754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    usprep_close(nameprep);
757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_terminateUChars(dest, destCapacity, reqLength, status);
759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uidna_IDNToUnicode(  const UChar* src, int32_t srcLength,
763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     UChar* dest, int32_t destCapacity,
764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     int32_t options,
765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     UParseError* parseError,
766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     UErrorCode* status){
767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(status == NULL || U_FAILURE(*status)){
769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ILLEGAL_ARGUMENT_ERROR;
773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t reqLength = 0;
777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*status)){
781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //initialize pointers
785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *delimiter = (UChar*)src;
786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *labelStart = (UChar*)src;
787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *currentDest = (UChar*) dest;
788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t remainingLen = srcLength;
789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t remainingDestCapacity = destCapacity;
790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t labelLen = 0, labelReqLength = 0;
791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool done = FALSE;
792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(;;){
794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done);
796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // The RFC states that
798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // <quote>
799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // ToUnicode never fails. If any step fails, then the original input
800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // is returned immediately in that step.
801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // </quote>
802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // _internal_toUnicode will copy the label.
803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*if(labelLen==0 && done==FALSE){
804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR;
805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }*/
807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelReqLength = _internal_toUnicode(labelStart, labelLen,
809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                             currentDest, remainingDestCapacity,
810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                             options, nameprep,
811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                             parseError, status);
812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*status == U_BUFFER_OVERFLOW_ERROR){
814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_ZERO_ERROR; // reset error
815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity = 0;
816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_FAILURE(*status)){
819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength +=labelReqLength;
823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // adjust the destination pointer
824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(labelReqLength < remainingDestCapacity){
825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            currentDest = currentDest + labelReqLength;
826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity -= labelReqLength;
827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }else{
828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // should never occur
829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity = 0;
830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(done == TRUE){
833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // add the label separator
837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Unlike the ToASCII operation we don't normalize the label separators
838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(remainingDestCapacity > 0){
839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *currentDest++ = *(labelStart + labelLen);
840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingDestCapacity--;
841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        reqLength++;
843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        labelStart = delimiter;
845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(remainingLen >0 ){
846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            remainingLen = (int32_t)(srcLength - (delimiter - src));
847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(reqLength > MAX_DOMAIN_NAME_LENGTH){
852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR;
853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    usprep_close(nameprep);
856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_terminateUChars(dest, destCapacity, reqLength, status);
858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uidna_compare(  const UChar *s1, int32_t length1,
862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                const UChar *s2, int32_t length2,
863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                int32_t options,
864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UErrorCode* status){
865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(status == NULL || U_FAILURE(*status)){
867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return -1;
868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar b1Stack[MAX_IDN_BUFFER_SIZE], b2Stack[MAX_IDN_BUFFER_SIZE];
871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *b1 = b1Stack, *b2 = b2Stack;
872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t b1Len, b2Len, b1Capacity = MAX_IDN_BUFFER_SIZE, b2Capacity = MAX_IDN_BUFFER_SIZE;
873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t result=-1;
874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UParseError parseError;
876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    b1Len = uidna_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, status);
878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(*status == U_BUFFER_OVERFLOW_ERROR){
879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // redo processing of string
880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b1==NULL){
882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_MEMORY_ALLOCATION_ERROR;
883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ZERO_ERROR; // reset error
887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b1Len = uidna_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, status);
889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    b2Len = uidna_IDNToASCII(s2,length2, b2,b2Capacity, options, &parseError, status);
893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(*status == U_BUFFER_OVERFLOW_ERROR){
894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // redo processing of string
895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(b2==NULL){
897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *status = U_MEMORY_ALLOCATION_ERROR;
898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto CLEANUP;
899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_ZERO_ERROR; // reset error
902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        b2Len = uidna_IDNToASCII(s2, length2, b2, b2Len, options, &parseError, status);
904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // when toASCII is applied all label separators are replaced with FULL_STOP
907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len);
908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CLEANUP:
910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b1 != b1Stack){
911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b1);
912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(b2 != b2Stack){
915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(b2);
916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_IDNA */
922