source: trunk/libtransmission/ConvertUTF.c @ 6795

Last change on this file since 6795 was 6795, checked in by charles, 13 years ago

run libT, cli, daemon, gtk through the source-code formatter "uncrustify" as promised/threatened

File size: 24.5 KB
Line 
1/*
2 * Copyright 2001-2004 Unicode, Inc.
3 *
4 * Disclaimer
5 *
6 * This source code is provided as is by Unicode, Inc. No claims are
7 * made as to fitness for any particular purpose. No warranties of any
8 * kind are expressed or implied. The recipient agrees to determine
9 * applicability of information provided. If this file has been
10 * purchased on magnetic or optical media from Unicode, Inc., the
11 * sole remedy for any claim will be exchange of defective media
12 * within 90 days of receipt.
13 *
14 * Limitations on Rights to Redistribute This Code
15 *
16 * Unicode, Inc. hereby grants the right to freely use the information
17 * supplied in this file in the creation of products supporting the
18 * Unicode Standard, and to make copies of this file in any form
19 * for internal or external distribution as long as this notice
20 * remains attached.
21 */
22
23/* ---------------------------------------------------------------------
24
25    Conversions between UTF32, UTF-16, and UTF-8. Source code file.
26    Author: Mark E. Davis, 1994.
27    Rev History: Rick McGowan, fixes & updates May 2001.
28    Sept 2001: fixed const & error conditions per
29    mods suggested by S. Parent & A. Lillich.
30    June 2002: Tim Dodd added detection and handling of incomplete
31    source sequences, enhanced error detection, added casts
32    to eliminate compiler warnings.
33    July 2003: slight mods to back out aggressive FFFE detection.
34    Jan 2004: updated switches in from-UTF8 conversions.
35    Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
36
37    See the header file "ConvertUTF.h" for complete documentation.
38
39   ------------------------------------------------------------------------ */
40
41
42#include "ConvertUTF.h"
43#ifdef CVTUTF_DEBUG
44 #include <stdio.h>
45#endif
46
47static const int   halfShift  = 10; /* used for shifting by 10 bits */
48
49static const UTF32 halfBase = 0x0010000UL;
50static const UTF32 halfMask = 0x3FFUL;
51
52#define UNI_SUR_HIGH_START  (UTF32)0xD800
53#define UNI_SUR_HIGH_END    (UTF32)0xDBFF
54#define UNI_SUR_LOW_START   (UTF32)0xDC00
55#define UNI_SUR_LOW_END     (UTF32)0xDFFF
56#define false      0
57#define true        1
58
59/* --------------------------------------------------------------------- */
60
61ConversionResult
62ConvertUTF32toUTF16( const UTF32**   sourceStart,
63                     const UTF32*    sourceEnd,
64                     UTF16**         targetStart,
65                     UTF16*          targetEnd,
66                     ConversionFlags flags )
67{
68    ConversionResult result = conversionOK;
69    const UTF32*     source = *sourceStart;
70    UTF16*           target = *targetStart;
71
72    while( source < sourceEnd )
73    {
74        UTF32 ch;
75        if( target >= targetEnd )
76        {
77            result = targetExhausted; break;
78        }
79        ch = *source++;
80        if( ch <= UNI_MAX_BMP ) /* Target is a character <= 0xFFFF */
81        { /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are
82            both reserved values */
83            if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
84            {
85                if( flags == strictConversion )
86                {
87                    --source; /* return to the illegal value itself */
88                    result = sourceIllegal;
89                    break;
90                }
91                else
92                {
93                    *target++ = UNI_REPLACEMENT_CHAR;
94                }
95            }
96            else
97            {
98                *target++ = (UTF16)ch; /* normal case */
99            }
100        }
101        else if( ch > UNI_MAX_LEGAL_UTF32 )
102        {
103            if( flags == strictConversion )
104            {
105                result = sourceIllegal;
106            }
107            else
108            {
109                *target++ = UNI_REPLACEMENT_CHAR;
110            }
111        }
112        else
113        {
114            /* target is a character in range 0xFFFF - 0x10FFFF. */
115            if( target + 1 >= targetEnd )
116            {
117                --source; /* Back up source pointer! */
118                result = targetExhausted; break;
119            }
120            ch -= halfBase;
121            *target++ = (UTF16)( ( ch >> halfShift ) + UNI_SUR_HIGH_START );
122            *target++ = (UTF16)( ( ch & halfMask ) + UNI_SUR_LOW_START );
123        }
124    }
125
126    *sourceStart = source;
127    *targetStart = target;
128    return result;
129}
130
131/* --------------------------------------------------------------------- */
132
133ConversionResult
134ConvertUTF16toUTF32( const UTF16**   sourceStart,
135                     const UTF16*    sourceEnd,
136                     UTF32**         targetStart,
137                     UTF32*          targetEnd,
138                     ConversionFlags flags )
139{
140    ConversionResult result = conversionOK;
141    const UTF16*     source = *sourceStart;
142    UTF32*           target = *targetStart;
143    UTF32            ch, ch2;
144
145    while( source < sourceEnd )
146    {
147        const UTF16* oldSource = source; /*  In case we have to back up because
148                                           of target overflow. */
149        ch = *source++;
150        /* If we have a surrogate pair, convert to UTF32 first. */
151        if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END )
152        {
153            /* If the 16 bits following the high surrogate are in the source
154              buffer... */
155            if( source < sourceEnd )
156            {
157                ch2 = *source;
158                /* If it's a low surrogate, convert to UTF32. */
159                if( ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END )
160                {
161                    ch = ( ( ch - UNI_SUR_HIGH_START ) << halfShift )
162                         + ( ch2 - UNI_SUR_LOW_START ) + halfBase;
163                    ++source;
164                }
165                else if( flags == strictConversion ) /* it's an unpaired high
166                                                       surrogate */
167                {
168                    --source; /* return to the illegal value itself */
169                    result = sourceIllegal;
170                    break;
171                }
172            }
173            else /* We don't have the 16 bits following the high surrogate. */
174            {
175                --source; /* return to the high surrogate */
176                result = sourceExhausted;
177                break;
178            }
179        }
180        else if( flags == strictConversion )
181        {
182            /* UTF-16 surrogate values are illegal in UTF-32 */
183            if( ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END )
184            {
185                --source; /* return to the illegal value itself */
186                result = sourceIllegal;
187                break;
188            }
189        }
190        if( target >= targetEnd )
191        {
192            source = oldSource; /* Back up source pointer! */
193            result = targetExhausted; break;
194        }
195        *target++ = ch;
196    }
197
198    *sourceStart = source;
199    *targetStart = target;
200#ifdef CVTUTF_DEBUG
201    if( result == sourceIllegal )
202    {
203        fprintf( stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n",
204                 ch,
205                 ch2 );
206        fflush( stderr );
207    }
208#endif
209    return result;
210}
211
212/* --------------------------------------------------------------------- */
213
214/*
215 * Index into the table below with the first byte of a UTF-8 sequence to
216 * get the number of trailing bytes that are supposed to follow it.
217 * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
218 * left as-is for anyone who may want to do such conversion, which was
219 * allowed in earlier algorithms.
220 */
221static const char  trailingBytesForUTF8[256] = {
222    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223    0, 0, 0, 0, 0, 0, 0, 0,
224    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225    0, 0, 0, 0, 0, 0, 0, 0,
226    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
227    0, 0, 0, 0, 0, 0, 0, 0,
228    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229    0, 0, 0, 0, 0, 0, 0, 0,
230    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231    0, 0, 0, 0, 0, 0, 0, 0,
232    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233    0, 0, 0, 0, 0, 0, 0, 0,
234    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
235    1, 1, 1, 1, 1, 1, 1, 1,
236    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
237    4, 4, 4, 4, 5, 5, 5, 5
238};
239
240/*
241 * Magic values subtracted from a buffer value during UTF8 conversion.
242 * This table contains as many values as there might be trailing bytes
243 * in a UTF-8 sequence.
244 */
245static const UTF32 offsetsFromUTF8[6] =
246{ 0x00000000UL,                                           0x00003080UL,
247  0x000E2080UL,
248  0x03C82080UL, 0xFA082080UL,
249  0x82082080UL };
250
251/*
252 * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
253 * into the first byte, depending on how many bytes follow.  There are
254 * as many entries in this table as there are UTF-8 sequence types.
255 * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
256 * for *legal* UTF-8 will be 4 or fewer bytes total.
257 */
258static const UTF8  firstByteMark[7] =
259{ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
260
261/* --------------------------------------------------------------------- */
262
263/* The interface converts a whole buffer to avoid function-call overhead.
264 * Constants have been gathered. Loops & conditionals have been removed as
265 * much as possible for efficiency, in favor of drop-through switches.
266 * (See "Note A" at the bottom of the file for equivalent code.)
267 * If your compiler supports it, the "isLegalUTF8" call can be turned
268 * into an inline function.
269 */
270
271/* --------------------------------------------------------------------- */
272
273ConversionResult
274ConvertUTF16toUTF8( const UTF16**   sourceStart,
275                    const UTF16*    sourceEnd,
276                    UTF8**          targetStart,
277                    UTF8*           targetEnd,
278                    ConversionFlags flags )
279{
280    ConversionResult result = conversionOK;
281    const UTF16*     source = *sourceStart;
282    UTF8*            target = *targetStart;
283
284    while( source < sourceEnd )
285    {
286        UTF32          ch;
287        unsigned short bytesToWrite = 0;
288        const UTF32    byteMask = 0xBF;
289        const UTF32    byteMark = 0x80;
290        const UTF16*   oldSource = source; /* In case we have to back up because
291                                             of target overflow. */
292        ch = *source++;
293        /* If we have a surrogate pair, convert to UTF32 first. */
294        if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END )
295        {
296            /* If the 16 bits following the high surrogate are in the source
297              buffer... */
298            if( source < sourceEnd )
299            {
300                UTF32 ch2 = *source;
301                /* If it's a low surrogate, convert to UTF32. */
302                if( ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END )
303                {
304                    ch = ( ( ch - UNI_SUR_HIGH_START ) << halfShift )
305                         + ( ch2 - UNI_SUR_LOW_START ) + halfBase;
306                    ++source;
307                }
308                else if( flags == strictConversion ) /* it's an unpaired high
309                                                       surrogate */
310                {
311                    --source; /* return to the illegal value itself */
312                    result = sourceIllegal;
313                    break;
314                }
315            }
316            else /* We don't have the 16 bits following the high surrogate. */
317            {
318                --source; /* return to the high surrogate */
319                result = sourceExhausted;
320                break;
321            }
322        }
323        else if( flags == strictConversion )
324        {
325            /* UTF-16 surrogate values are illegal in UTF-32 */
326            if( ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END )
327            {
328                --source; /* return to the illegal value itself */
329                result = sourceIllegal;
330                break;
331            }
332        }
333        /* Figure out how many bytes the result will require */
334        if( ch < (UTF32)0x80 )
335        {
336            bytesToWrite = 1;
337        }
338        else if( ch < (UTF32)0x800 )
339        {
340            bytesToWrite = 2;
341        }
342        else if( ch < (UTF32)0x10000 )
343        {
344            bytesToWrite = 3;
345        }
346        else if( ch < (UTF32)0x110000 )
347        {
348            bytesToWrite = 4;
349        }
350        else
351        {
352            bytesToWrite = 3;
353            ch = UNI_REPLACEMENT_CHAR;
354        }
355
356        target += bytesToWrite;
357        if( target > targetEnd )
358        {
359            source = oldSource; /* Back up source pointer! */
360            target -= bytesToWrite; result = targetExhausted; break;
361        }
362        switch( bytesToWrite ) /* note: everything falls through. */
363        {
364            case 4:
365                *--target =
366                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
367
368            case 3:
369                *--target =
370                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
371
372            case 2:
373                *--target =
374                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
375
376            case 1:
377                *--target =  (UTF8)( ch | firstByteMark[bytesToWrite] );
378        }
379        target += bytesToWrite;
380    }
381
382    *sourceStart = source;
383    *targetStart = target;
384    return result;
385}
386
387/* --------------------------------------------------------------------- */
388
389/*
390 * Utility routine to tell whether a sequence of bytes is legal UTF-8.
391 * This must be called with the length pre-determined by the first byte.
392 * If not calling this from ConvertUTF8to*, then the length can be set by:
393 *  length = trailingBytesForUTF8[*source]+1;
394 * and the sequence is illegal right away if there aren't that many bytes
395 * available.
396 * If presented with a length > 4, this returns false.  The Unicode
397 * definition of UTF-8 goes up to 4-byte sequences.
398 */
399
400static Boolean
401isLegalUTF8( const UTF8 *source,
402             int         length )
403{
404    UTF8        a;
405    const UTF8 *srcptr = source + length;
406
407    switch( length )
408    {
409        default:
410            return false;
411
412        /* Everything else falls through when "true"... */
413        case 4:
414            if( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return false;
415
416        case 3:
417            if( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return false;
418
419        case 2:
420            if( ( a = ( *--srcptr ) ) > 0xBF ) return false;
421
422            switch( *source )
423            {
424                /* no fall-through in this inner switch */
425                case 0xE0:
426                    if( a < 0xA0 ) return false;break;
427
428                case 0xED:
429                    if( a > 0x9F ) return false;break;
430
431                case 0xF0:
432                    if( a < 0x90 ) return false;break;
433
434                case 0xF4:
435                    if( a > 0x8F ) return false;break;
436
437                default:
438                    if( a < 0x80 ) return false;
439            }
440
441        case 1:
442            if( *source >= 0x80 && *source < 0xC2 ) return false;
443    }
444    if( *source > 0xF4 ) return false;
445    return true;
446}
447
448/* --------------------------------------------------------------------- */
449
450/*
451 * Exported function to return whether a UTF-8 sequence is legal or not.
452 * This is not used here; it's just exported.
453 */
454Boolean
455isLegalUTF8Sequence( const UTF8 *source,
456                     const UTF8 *sourceEnd )
457{
458    int length = trailingBytesForUTF8[*source] + 1;
459
460    if( source + length > sourceEnd )
461    {
462        return false;
463    }
464    return isLegalUTF8( source, length );
465}
466
467/* --------------------------------------------------------------------- */
468
469ConversionResult
470ConvertUTF8toUTF16( const UTF8**    sourceStart,
471                    const UTF8*     sourceEnd,
472                    UTF16**         targetStart,
473                    UTF16*          targetEnd,
474                    ConversionFlags flags )
475{
476    ConversionResult result = conversionOK;
477    const UTF8*      source = *sourceStart;
478    UTF16*           target = *targetStart;
479
480    while( source < sourceEnd )
481    {
482        UTF32          ch = 0;
483        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
484        if( source + extraBytesToRead >= sourceEnd )
485        {
486            result = sourceExhausted; break;
487        }
488        /* Do this check whether lenient or strict */
489        if( !isLegalUTF8( source, extraBytesToRead + 1 ) )
490        {
491            result = sourceIllegal;
492            break;
493        }
494        /*
495         * The cases all fall through. See "Note A" below.
496         */
497        switch( extraBytesToRead )
498        {
499            case 5:
500                ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
501
502            case 4:
503                ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
504
505            case 3:
506                ch += *source++; ch <<= 6;
507
508            case 2:
509                ch += *source++; ch <<= 6;
510
511            case 1:
512                ch += *source++; ch <<= 6;
513
514            case 0:
515                ch += *source++;
516        }
517        ch -= offsetsFromUTF8[extraBytesToRead];
518
519        if( target >= targetEnd )
520        {
521            source -= ( extraBytesToRead + 1 ); /* Back up source pointer! */
522            result = targetExhausted; break;
523        }
524        if( ch <= UNI_MAX_BMP ) /* Target is a character <= 0xFFFF */
525        { /* UTF-16 surrogate values are illegal in UTF-32 */
526            if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
527            {
528                if( flags == strictConversion )
529                {
530                    source -= ( extraBytesToRead + 1 ); /* return to the illegal
531                                                          value itself */
532                    result = sourceIllegal;
533                    break;
534                }
535                else
536                {
537                    *target++ = UNI_REPLACEMENT_CHAR;
538                }
539            }
540            else
541            {
542                *target++ = (UTF16)ch; /* normal case */
543            }
544        }
545        else if( ch > UNI_MAX_UTF16 )
546        {
547            if( flags == strictConversion )
548            {
549                result = sourceIllegal;
550                source -= ( extraBytesToRead + 1 ); /* return to the start */
551                break; /* Bail out; shouldn't continue */
552            }
553            else
554            {
555                *target++ = UNI_REPLACEMENT_CHAR;
556            }
557        }
558        else
559        {
560            /* target is a character in range 0xFFFF - 0x10FFFF. */
561            if( target + 1 >= targetEnd )
562            {
563                source -= ( extraBytesToRead + 1 ); /* Back up source pointer!
564                                                      */
565                result = targetExhausted; break;
566            }
567            ch -= halfBase;
568            *target++ = (UTF16)( ( ch >> halfShift ) + UNI_SUR_HIGH_START );
569            *target++ = (UTF16)( ( ch & halfMask ) + UNI_SUR_LOW_START );
570        }
571    }
572
573    *sourceStart = source;
574    *targetStart = target;
575    return result;
576}
577
578/* --------------------------------------------------------------------- */
579
580ConversionResult
581ConvertUTF32toUTF8( const UTF32**   sourceStart,
582                    const UTF32*    sourceEnd,
583                    UTF8**          targetStart,
584                    UTF8*           targetEnd,
585                    ConversionFlags flags )
586{
587    ConversionResult result = conversionOK;
588    const UTF32*     source = *sourceStart;
589    UTF8*            target = *targetStart;
590
591    while( source < sourceEnd )
592    {
593        UTF32          ch;
594        unsigned short bytesToWrite = 0;
595        const UTF32    byteMask = 0xBF;
596        const UTF32    byteMark = 0x80;
597        ch = *source++;
598        if( flags == strictConversion )
599        {
600            /* UTF-16 surrogate values are illegal in UTF-32 */
601            if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
602            {
603                --source; /* return to the illegal value itself */
604                result = sourceIllegal;
605                break;
606            }
607        }
608        /*
609         * Figure out how many bytes the result will require. Turn any
610         * illegally large UTF32 things (> Plane 17) into replacement chars.
611         */
612        if( ch < (UTF32)0x80 )
613        {
614            bytesToWrite = 1;
615        }
616        else if( ch < (UTF32)0x800 )
617        {
618            bytesToWrite = 2;
619        }
620        else if( ch < (UTF32)0x10000 )
621        {
622            bytesToWrite = 3;
623        }
624        else if( ch <= UNI_MAX_LEGAL_UTF32 )
625        {
626            bytesToWrite = 4;
627        }
628        else
629        {
630            bytesToWrite = 3;
631            ch = UNI_REPLACEMENT_CHAR;
632            result = sourceIllegal;
633        }
634
635        target += bytesToWrite;
636        if( target > targetEnd )
637        {
638            --source; /* Back up source pointer! */
639            target -= bytesToWrite; result = targetExhausted; break;
640        }
641        switch( bytesToWrite ) /* note: everything falls through. */
642        {
643            case 4:
644                *--target =
645                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
646
647            case 3:
648                *--target =
649                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
650
651            case 2:
652                *--target =
653                    (UTF8)( ( ch | byteMark ) & byteMask ); ch >>= 6;
654
655            case 1:
656                *--target = (UTF8) ( ch | firstByteMark[bytesToWrite] );
657        }
658        target += bytesToWrite;
659    }
660
661    *sourceStart = source;
662    *targetStart = target;
663    return result;
664}
665
666/* --------------------------------------------------------------------- */
667
668ConversionResult
669ConvertUTF8toUTF32( const UTF8**    sourceStart,
670                    const UTF8*     sourceEnd,
671                    UTF32**         targetStart,
672                    UTF32*          targetEnd,
673                    ConversionFlags flags )
674{
675    ConversionResult result = conversionOK;
676    const UTF8*      source = *sourceStart;
677    UTF32*           target = *targetStart;
678
679    while( source < sourceEnd )
680    {
681        UTF32          ch = 0;
682        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
683        if( source + extraBytesToRead >= sourceEnd )
684        {
685            result = sourceExhausted; break;
686        }
687        /* Do this check whether lenient or strict */
688        if( !isLegalUTF8( source, extraBytesToRead + 1 ) )
689        {
690            result = sourceIllegal;
691            break;
692        }
693        /*
694         * The cases all fall through. See "Note A" below.
695         */
696        switch( extraBytesToRead )
697        {
698            case 5:
699                ch += *source++; ch <<= 6;
700
701            case 4:
702                ch += *source++; ch <<= 6;
703
704            case 3:
705                ch += *source++; ch <<= 6;
706
707            case 2:
708                ch += *source++; ch <<= 6;
709
710            case 1:
711                ch += *source++; ch <<= 6;
712
713            case 0:
714                ch += *source++;
715        }
716        ch -= offsetsFromUTF8[extraBytesToRead];
717
718        if( target >= targetEnd )
719        {
720            source -= ( extraBytesToRead + 1 ); /* Back up the source pointer!
721                                                  */
722            result = targetExhausted; break;
723        }
724        if( ch <= UNI_MAX_LEGAL_UTF32 )
725        {
726            /*
727             * UTF-16 surrogate values are illegal in UTF-32, and anything
728             * over Plane 17 (> 0x10FFFF) is illegal.
729             */
730            if( ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END )
731            {
732                if( flags == strictConversion )
733                {
734                    source -= ( extraBytesToRead + 1 ); /* return to the illegal
735                                                          value itself */
736                    result = sourceIllegal;
737                    break;
738                }
739                else
740                {
741                    *target++ = UNI_REPLACEMENT_CHAR;
742                }
743            }
744            else
745            {
746                *target++ = ch;
747            }
748        }
749        else /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
750        {
751            result = sourceIllegal;
752            *target++ = UNI_REPLACEMENT_CHAR;
753        }
754    }
755
756    *sourceStart = source;
757    *targetStart = target;
758    return result;
759}
760
761/* ---------------------------------------------------------------------
762
763    Note A.
764    The fall-through switches in UTF-8 reading code save a
765    temp variable, some decrements & conditionals.  The switches
766    are equivalent to the following loop:
767    {
768        int tmpBytesToRead = extraBytesToRead+1;
769        do {
770        ch += *source++;
771        --tmpBytesToRead;
772        if (tmpBytesToRead) ch <<= 6;
773        } while (tmpBytesToRead > 0);
774    }
775    In UTF-8 writing code, the switches on "bytesToWrite" are
776    similarly unrolled loops.
777
778   --------------------------------------------------------------------- */
Note: See TracBrowser for help on using the repository browser.