Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/common/punycode.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
*******************************************************************************
5
*
6
*   Copyright (C) 2002-2011, International Business Machines
7
*   Corporation and others.  All Rights Reserved.
8
*
9
*******************************************************************************
10
*   file name:  punycode.cpp
11
*   encoding:   UTF-8
12
*   tab size:   8 (not used)
13
*   indentation:4
14
*
15
*   created on: 2002jan31
16
*   created by: Markus W. Scherer
17
*/
18
19
20
/* This ICU code derived from: */
21
/*
22
punycode.c 0.4.0 (2001-Nov-17-Sat)
23
http://www.cs.berkeley.edu/~amc/idn/
24
Adam M. Costello
25
http://www.nicemice.net/amc/
26
27
Disclaimer and license
28
29
    Regarding this entire document or any portion of it (including
30
    the pseudocode and C code), the author makes no guarantees and
31
    is not responsible for any damage resulting from its use.  The
32
    author grants irrevocable permission to anyone to use, modify,
33
    and distribute it in any way that does not diminish the rights
34
    of anyone else to use, modify, and distribute it, provided that
35
    redistributed derivative works do not contain misleading author or
36
    version information.  Derivative works need not be licensed under
37
    similar terms.
38
*/
39
/*
40
 * ICU modifications:
41
 * - ICU data types and coding conventions
42
 * - ICU string buffer handling with implicit source lengths
43
 *   and destination preflighting
44
 * - UTF-16 handling
45
 */
46
47
#include "unicode/utypes.h"
48
49
#if !UCONFIG_NO_IDNA
50
51
#include "unicode/ustring.h"
52
#include "unicode/utf.h"
53
#include "unicode/utf16.h"
54
#include "ustr_imp.h"
55
#include "cstring.h"
56
#include "cmemory.h"
57
#include "punycode.h"
58
#include "uassert.h"
59
60
61
/* Punycode ----------------------------------------------------------------- */
62
63
/* Punycode parameters for Bootstring */
64
98.6k
#define BASE            36
65
74.7k
#define TMIN            1
66
48.5k
#define TMAX            26
67
13.1k
#define SKEW            38
68
7.16k
#define DAMP            700
69
7.16k
#define INITIAL_BIAS    72
70
7.16k
#define INITIAL_N       0x80
71
72
/* "Basic" Unicode/ASCII code points */
73
44.9k
#define _HYPHEN         0X2d
74
44.9k
#define DELIMITER       _HYPHEN
75
76
0
#define _ZERO_          0X30
77
#define _NINE           0x39
78
79
0
#define _SMALL_A        0X61
80
0
#define _SMALL_Z        0X7a
81
82
0
#define _CAPITAL_A      0X41
83
0
#define _CAPITAL_Z      0X5a
84
85
20.8k
#define IS_BASIC(c) ((c)<0x80)
86
0
#define IS_BASIC_UPPERCASE(c) (_CAPITAL_A<=(c) && (c)<=_CAPITAL_Z)
87
88
/**
89
 * digitToBasic() returns the basic code point whose value
90
 * (when used for representing integers) is d, which must be in the
91
 * range 0 to BASE-1. The lowercase form is used unless the uppercase flag is
92
 * nonzero, in which case the uppercase form is used.
93
 */
94
static inline char
95
0
digitToBasic(int32_t digit, UBool uppercase) {
96
0
    /*  0..25 map to ASCII a..z or A..Z */
97
0
    /* 26..35 map to ASCII 0..9         */
98
0
    if(digit<26) {
99
0
        if(uppercase) {
100
0
            return (char)(_CAPITAL_A+digit);
101
0
        } else {
102
0
            return (char)(_SMALL_A+digit);
103
0
        }
104
0
    } else {
105
0
        return (char)((_ZERO_-26)+digit);
106
0
    }
107
0
}
108
109
/**
110
 * basicToDigit[] contains the numeric value of a basic code
111
 * point (for use in representing integers) in the range 0 to
112
 * BASE-1, or -1 if b is does not represent a value.
113
 */
114
static const int8_t
115
basicToDigit[256]={
116
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
117
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
118
119
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
120
    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
121
122
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
123
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
124
125
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
126
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
127
128
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
129
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
130
131
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
132
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
133
134
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
135
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
136
137
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
138
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
139
};
140
141
static inline char
142
0
asciiCaseMap(char b, UBool uppercase) {
143
0
    if(uppercase) {
144
0
        if(_SMALL_A<=b && b<=_SMALL_Z) {
145
0
            b-=(_SMALL_A-_CAPITAL_A);
146
0
        }
147
0
    } else {
148
0
        if(_CAPITAL_A<=b && b<=_CAPITAL_Z) {
149
0
            b+=(_SMALL_A-_CAPITAL_A);
150
0
        }
151
0
    }
152
0
    return b;
153
0
}
154
155
/* Punycode-specific Bootstring code ---------------------------------------- */
156
157
/*
158
 * The following code omits the {parts} of the pseudo-algorithm in the spec
159
 * that are not used with the Punycode parameter set.
160
 */
161
162
/* Bias adaptation function. */
163
static int32_t
164
13.1k
adaptBias(int32_t delta, int32_t length, UBool firstTime) {
165
13.1k
    int32_t count;
166
13.1k
167
13.1k
    if(firstTime) {
168
7.16k
        delta/=DAMP;
169
7.16k
    } else {
170
6.02k
        delta/=2;
171
6.02k
    }
172
13.1k
173
13.1k
    delta+=delta/length;
174
14.3k
    for(count=0; delta>((BASE-TMIN)*TMAX)/2; count+=BASE) {
175
1.13k
        delta/=(BASE-TMIN);
176
1.13k
    }
177
13.1k
178
13.1k
    return count+(((BASE-TMIN+1)*delta)/(delta+SKEW));
179
13.1k
}
180
181
0
#define MAX_CP_COUNT    200
182
183
U_CFUNC int32_t
184
u_strToPunycode(const UChar *src, int32_t srcLength,
185
                UChar *dest, int32_t destCapacity,
186
                const UBool *caseFlags,
187
0
                UErrorCode *pErrorCode) {
188
0
189
0
    int32_t cpBuffer[MAX_CP_COUNT];
190
0
    int32_t n, delta, handledCPCount, basicLength, destLength, bias, j, m, q, k, t, srcCPCount;
191
0
    UChar c, c2;
192
0
193
0
    /* argument checking */
194
0
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
195
0
        return 0;
196
0
    }
197
0
198
0
    if(src==NULL || srcLength<-1 || (dest==NULL && destCapacity!=0)) {
199
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
200
0
        return 0;
201
0
    }
202
0
203
0
    /*
204
0
     * Handle the basic code points and
205
0
     * convert extended ones to UTF-32 in cpBuffer (caseFlag in sign bit):
206
0
     */
207
0
    srcCPCount=destLength=0;
208
0
    if(srcLength==-1) {
209
0
        /* NUL-terminated input */
210
0
        for(j=0; /* no condition */; ++j) {
211
0
            if((c=src[j])==0) {
212
0
                break;
213
0
            }
214
0
            if(srcCPCount==MAX_CP_COUNT) {
215
0
                /* too many input code points */
216
0
                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
217
0
                return 0;
218
0
            }
219
0
            if(IS_BASIC(c)) {
220
0
                cpBuffer[srcCPCount++]=0;
221
0
                if(destLength<destCapacity) {
222
0
                    dest[destLength]=
223
0
                        caseFlags!=NULL ?
224
0
                            asciiCaseMap((char)c, caseFlags[j]) :
225
0
                            (char)c;
226
0
                }
227
0
                ++destLength;
228
0
            } else {
229
0
                n=(caseFlags!=NULL && caseFlags[j])<<31L;
230
0
                if(U16_IS_SINGLE(c)) {
231
0
                    n|=c;
232
0
                } else if(U16_IS_LEAD(c) && U16_IS_TRAIL(c2=src[j+1])) {
233
0
                    ++j;
234
0
                    n|=(int32_t)U16_GET_SUPPLEMENTARY(c, c2);
235
0
                } else {
236
0
                    /* error: unmatched surrogate */
237
0
                    *pErrorCode=U_INVALID_CHAR_FOUND;
238
0
                    return 0;
239
0
                }
240
0
                cpBuffer[srcCPCount++]=n;
241
0
            }
242
0
        }
243
0
    } else {
244
0
        /* length-specified input */
245
0
        for(j=0; j<srcLength; ++j) {
246
0
            if(srcCPCount==MAX_CP_COUNT) {
247
0
                /* too many input code points */
248
0
                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
249
0
                return 0;
250
0
            }
251
0
            c=src[j];
252
0
            if(IS_BASIC(c)) {
253
0
                cpBuffer[srcCPCount++]=0;
254
0
                if(destLength<destCapacity) {
255
0
                    dest[destLength]=
256
0
                        caseFlags!=NULL ?
257
0
                            asciiCaseMap((char)c, caseFlags[j]) :
258
0
                            (char)c;
259
0
                }
260
0
                ++destLength;
261
0
            } else {
262
0
                n=(caseFlags!=NULL && caseFlags[j])<<31L;
263
0
                if(U16_IS_SINGLE(c)) {
264
0
                    n|=c;
265
0
                } else if(U16_IS_LEAD(c) && (j+1)<srcLength && U16_IS_TRAIL(c2=src[j+1])) {
266
0
                    ++j;
267
0
                    n|=(int32_t)U16_GET_SUPPLEMENTARY(c, c2);
268
0
                } else {
269
0
                    /* error: unmatched surrogate */
270
0
                    *pErrorCode=U_INVALID_CHAR_FOUND;
271
0
                    return 0;
272
0
                }
273
0
                cpBuffer[srcCPCount++]=n;
274
0
            }
275
0
        }
276
0
    }
277
0
278
0
    /* Finish the basic string - if it is not empty - with a delimiter. */
279
0
    basicLength=destLength;
280
0
    if(basicLength>0) {
281
0
        if(destLength<destCapacity) {
282
0
            dest[destLength]=DELIMITER;
283
0
        }
284
0
        ++destLength;
285
0
    }
286
0
287
0
    /*
288
0
     * handledCPCount is the number of code points that have been handled
289
0
     * basicLength is the number of basic code points
290
0
     * destLength is the number of chars that have been output
291
0
     */
292
0
293
0
    /* Initialize the state: */
294
0
    n=INITIAL_N;
295
0
    delta=0;
296
0
    bias=INITIAL_BIAS;
297
0
298
0
    /* Main encoding loop: */
299
0
    for(handledCPCount=basicLength; handledCPCount<srcCPCount; /* no op */) {
300
0
        /*
301
0
         * All non-basic code points < n have been handled already.
302
0
         * Find the next larger one:
303
0
         */
304
0
        for(m=0x7fffffff, j=0; j<srcCPCount; ++j) {
305
0
            q=cpBuffer[j]&0x7fffffff; /* remove case flag from the sign bit */
306
0
            if(n<=q && q<m) {
307
0
                m=q;
308
0
            }
309
0
        }
310
0
311
0
        /*
312
0
         * Increase delta enough to advance the decoder's
313
0
         * <n,i> state to <m,0>, but guard against overflow:
314
0
         */
315
0
        if(m-n>(0x7fffffff-MAX_CP_COUNT-delta)/(handledCPCount+1)) {
316
0
            *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
317
0
            return 0;
318
0
        }
319
0
        delta+=(m-n)*(handledCPCount+1);
320
0
        n=m;
321
0
322
0
        /* Encode a sequence of same code points n */
323
0
        for(j=0; j<srcCPCount; ++j) {
324
0
            q=cpBuffer[j]&0x7fffffff; /* remove case flag from the sign bit */
325
0
            if(q<n) {
326
0
                ++delta;
327
0
            } else if(q==n) {
328
0
                /* Represent delta as a generalized variable-length integer: */
329
0
                for(q=delta, k=BASE; /* no condition */; k+=BASE) {
330
0
331
0
                    /** RAM: comment out the old code for conformance with draft-ietf-idn-punycode-03.txt
332
0
333
0
                    t=k-bias;
334
0
                    if(t<TMIN) {
335
0
                        t=TMIN;
336
0
                    } else if(t>TMAX) {
337
0
                        t=TMAX;
338
0
                    }
339
0
                    */
340
0
341
0
                    t=k-bias;
342
0
                    if(t<TMIN) {
343
0
                        t=TMIN;
344
0
                    } else if(k>=(bias+TMAX)) {
345
0
                        t=TMAX;
346
0
                    }
347
0
348
0
                    if(q<t) {
349
0
                        break;
350
0
                    }
351
0
352
0
                    if(destLength<destCapacity) {
353
0
                        dest[destLength]=digitToBasic(t+(q-t)%(BASE-t), 0);
354
0
                    }
355
0
                    ++destLength;
356
0
                    q=(q-t)/(BASE-t);
357
0
                }
358
0
359
0
                if(destLength<destCapacity) {
360
0
                    dest[destLength]=digitToBasic(q, (UBool)(cpBuffer[j]<0));
361
0
                }
362
0
                ++destLength;
363
0
                bias=adaptBias(delta, handledCPCount+1, (UBool)(handledCPCount==basicLength));
364
0
                delta=0;
365
0
                ++handledCPCount;
366
0
            }
367
0
        }
368
0
369
0
        ++delta;
370
0
        ++n;
371
0
    }
372
0
373
0
    return u_terminateUChars(dest, destCapacity, destLength, pErrorCode);
374
0
}
375
376
U_CFUNC int32_t
377
u_strFromPunycode(const UChar *src, int32_t srcLength,
378
                  UChar *dest, int32_t destCapacity,
379
                  UBool *caseFlags,
380
7.72k
                  UErrorCode *pErrorCode) {
381
7.72k
    int32_t n, destLength, i, bias, basicLength, j, in, oldi, w, k, digit, t,
382
7.72k
            destCPCount, firstSupplementaryIndex, cpLength;
383
7.72k
    UChar b;
384
7.72k
385
7.72k
    /* argument checking */
386
7.72k
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
387
0
        return 0;
388
0
    }
389
7.72k
390
7.72k
    if(src==NULL || srcLength<-1 || (dest==NULL && destCapacity!=0)) {
391
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
392
0
        return 0;
393
0
    }
394
7.72k
395
7.72k
    if(srcLength==-1) {
396
0
        srcLength=u_strlen(src);
397
0
    }
398
7.72k
399
7.72k
    /*
400
7.72k
     * Handle the basic code points:
401
7.72k
     * Let basicLength be the number of input code points
402
7.72k
     * before the last delimiter, or 0 if there is none,
403
7.72k
     * then copy the first basicLength code points to the output.
404
7.72k
     *
405
7.72k
     * The two following loops iterate backward.
406
7.72k
     */
407
47.5k
    for(j=srcLength; j>0;) {
408
44.9k
        if(src[--j]==DELIMITER) {
409
5.13k
            break;
410
5.13k
        }
411
44.9k
    }
412
7.72k
    destLength=basicLength=destCPCount=j;
413
7.72k
    U_ASSERT(destLength>=0);
414
7.72k
415
27.9k
    while(j>0) {
416
20.8k
        b=src[--j];
417
20.8k
        if(!IS_BASIC(b)) {
418
568
            *pErrorCode=U_INVALID_CHAR_FOUND;
419
568
            return 0;
420
568
        }
421
20.2k
422
20.2k
        if(j<destCapacity) {
423
20.1k
            dest[j]=(UChar)b;
424
20.1k
425
20.1k
            if(caseFlags!=NULL) {
426
0
                caseFlags[j]=IS_BASIC_UPPERCASE(b);
427
0
            }
428
20.1k
        }
429
20.2k
    }
430
7.72k
431
7.72k
    /* Initialize the state: */
432
7.72k
    n=INITIAL_N;
433
7.16k
    i=0;
434
7.16k
    bias=INITIAL_BIAS;
435
7.16k
    firstSupplementaryIndex=1000000000;
436
7.16k
437
7.16k
    /*
438
7.16k
     * Main decoding loop:
439
7.16k
     * Start just after the last delimiter if any
440
7.16k
     * basic code points were copied; start at the beginning otherwise.
441
7.16k
     */
442
20.3k
    for(in=basicLength>0 ? basicLength+1 : 0; in<srcLength; /* no op */) {
443
13.1k
        /*
444
13.1k
         * in is the index of the next character to be consumed, and
445
13.1k
         * destCPCount is the number of code points in the output array.
446
13.1k
         *
447
13.1k
         * Decode a generalized variable-length integer into delta,
448
13.1k
         * which gets added to i.  The overflow checking is easier
449
13.1k
         * if we increase i as we go, then subtract off its starting
450
13.1k
         * value at the end to obtain delta.
451
13.1k
         */
452
31.7k
        for(oldi=i, w=1, k=BASE; /* no condition */; k+=BASE) {
453
31.7k
            if(in>=srcLength) {
454
0
                *pErrorCode=U_ILLEGAL_CHAR_FOUND;
455
0
                return 0;
456
0
            }
457
31.7k
458
31.7k
            digit=basicToDigit[(uint8_t)src[in++]];
459
31.7k
            if(digit<0) {
460
0
                *pErrorCode=U_INVALID_CHAR_FOUND;
461
0
                return 0;
462
0
            }
463
31.7k
            if(digit>(0x7fffffff-i)/w) {
464
0
                /* integer overflow */
465
0
                *pErrorCode=U_ILLEGAL_CHAR_FOUND;
466
0
                return 0;
467
0
            }
468
31.7k
469
31.7k
            i+=digit*w;
470
31.7k
            /** RAM: comment out the old code for conformance with draft-ietf-idn-punycode-03.txt  
471
31.7k
            t=k-bias;
472
31.7k
            if(t<TMIN) {
473
31.7k
                t=TMIN;
474
31.7k
            } else if(t>TMAX) {
475
31.7k
                t=TMAX;
476
31.7k
            }
477
31.7k
            */
478
31.7k
            t=k-bias;
479
31.7k
            if(t<TMIN) {
480
14.4k
                t=TMIN;
481
17.3k
            } else if(k>=(bias+TMAX)) {
482
16.9k
                t=TMAX;
483
16.9k
            }
484
31.7k
            if(digit<t) {
485
13.1k
                break;
486
13.1k
            }
487
18.5k
488
18.5k
            if(w>0x7fffffff/(BASE-t)) {
489
0
                /* integer overflow */
490
0
                *pErrorCode=U_ILLEGAL_CHAR_FOUND;
491
0
                return 0;
492
0
            }
493
18.5k
            w*=BASE-t;
494
18.5k
        }
495
13.1k
496
13.1k
        /*
497
13.1k
         * Modification from sample code:
498
13.1k
         * Increments destCPCount here,
499
13.1k
         * where needed instead of in for() loop tail.
500
13.1k
         */
501
13.1k
        ++destCPCount;
502
13.1k
        bias=adaptBias(i-oldi, destCPCount, (UBool)(oldi==0));
503
13.1k
504
13.1k
        /*
505
13.1k
         * i was supposed to wrap around from (incremented) destCPCount to 0,
506
13.1k
         * incrementing n each time, so we'll fix that now:
507
13.1k
         */
508
13.1k
        if(i/destCPCount>(0x7fffffff-n)) {
509
0
            /* integer overflow */
510
0
            *pErrorCode=U_ILLEGAL_CHAR_FOUND;
511
0
            return 0;
512
0
        }
513
13.1k
514
13.1k
        n+=i/destCPCount;
515
13.1k
        i%=destCPCount;
516
13.1k
        /* not needed for Punycode: */
517
13.1k
        /* if (decode_digit(n) <= BASE) return punycode_invalid_input; */
518
13.1k
519
13.1k
        if(n>0x10ffff || U_IS_SURROGATE(n)) {
520
0
            /* Unicode code point overflow */
521
0
            *pErrorCode=U_ILLEGAL_CHAR_FOUND;
522
0
            return 0;
523
0
        }
524
13.1k
525
13.1k
        /* Insert n at position i of the output: */
526
13.1k
        cpLength=U16_LENGTH(n);
527
13.1k
        if(dest!=NULL && ((destLength+cpLength)<=destCapacity)) {
528
13.0k
            int32_t codeUnitIndex;
529
13.0k
530
13.0k
            /*
531
13.0k
             * Handle indexes when supplementary code points are present.
532
13.0k
             *
533
13.0k
             * In almost all cases, there will be only BMP code points before i
534
13.0k
             * and even in the entire string.
535
13.0k
             * This is handled with the same efficiency as with UTF-32.
536
13.0k
             *
537
13.0k
             * Only the rare cases with supplementary code points are handled
538
13.0k
             * more slowly - but not too bad since this is an insertion anyway.
539
13.0k
             */
540
13.0k
            if(i<=firstSupplementaryIndex) {
541
13.0k
                codeUnitIndex=i;
542
13.0k
                if(cpLength>1) {
543
34
                    firstSupplementaryIndex=codeUnitIndex;
544
12.9k
                } else {
545
12.9k
                    ++firstSupplementaryIndex;
546
12.9k
                }
547
13.0k
            } else {
548
0
                codeUnitIndex=firstSupplementaryIndex;
549
0
                U16_FWD_N(dest, codeUnitIndex, destLength, i-codeUnitIndex);
550
0
            }
551
13.0k
552
13.0k
            /* use the UChar index codeUnitIndex instead of the code point index i */
553
13.0k
            if(codeUnitIndex<destLength) {
554
3.74k
                uprv_memmove(dest+codeUnitIndex+cpLength,
555
3.74k
                             dest+codeUnitIndex,
556
3.74k
                             (destLength-codeUnitIndex)*U_SIZEOF_UCHAR);
557
3.74k
                if(caseFlags!=NULL) {
558
0
                    uprv_memmove(caseFlags+codeUnitIndex+cpLength,
559
0
                                 caseFlags+codeUnitIndex,
560
0
                                 destLength-codeUnitIndex);
561
0
                }
562
3.74k
            }
563
13.0k
            if(cpLength==1) {
564
12.9k
                /* BMP, insert one code unit */
565
12.9k
                dest[codeUnitIndex]=(UChar)n;
566
12.9k
            } else {
567
34
                /* supplementary character, insert two code units */
568
34
                dest[codeUnitIndex]=U16_LEAD(n);
569
34
                dest[codeUnitIndex+1]=U16_TRAIL(n);
570
34
            }
571
13.0k
            if(caseFlags!=NULL) {
572
0
                /* Case of last character determines uppercase flag: */
573
0
                caseFlags[codeUnitIndex]=IS_BASIC_UPPERCASE(src[in-1]);
574
0
                if(cpLength==2) {
575
0
                    caseFlags[codeUnitIndex+1]=FALSE;
576
0
                }
577
0
            }
578
13.0k
        }
579
13.1k
        destLength+=cpLength;
580
13.1k
        U_ASSERT(destLength>=0);
581
13.1k
        ++i;
582
13.1k
    }
583
7.16k
584
7.16k
    return u_terminateUChars(dest, destCapacity, destLength, pErrorCode);
585
7.16k
}
586
587
/* ### check notes on overflow handling - only necessary if not IDNA? are these Punycode functions to be public? */
588
589
#endif /* #if !UCONFIG_NO_IDNA */