1/*
2**********************************************************************
3*   Copyright (C) 2000-2012, International Business Machines
4*   Corporation and others.  All Rights Reserved.
5**********************************************************************
6*   file name:  ucnvlat1.cpp
7*   encoding:   US-ASCII
8*   tab size:   8 (not used)
9*   indentation:4
10*
11*   created on: 2000feb07
12*   created by: Markus W. Scherer
13*/
14
15#include "unicode/utypes.h"
16
17#if !UCONFIG_NO_CONVERSION
18
19#include "unicode/ucnv.h"
20#include "unicode/uset.h"
21#include "unicode/utf8.h"
22#include "ucnv_bld.h"
23#include "ucnv_cnv.h"
24
25/* control optimizations according to the platform */
26#define LATIN1_UNROLL_FROM_UNICODE 1
27
28/* ISO 8859-1 --------------------------------------------------------------- */
29
30/* This is a table-less and callback-less version of ucnv_MBCSSingleToBMPWithOffsets(). */
31static void
32_Latin1ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
33                            UErrorCode *pErrorCode) {
34    const uint8_t *source;
35    UChar *target;
36    int32_t targetCapacity, length;
37    int32_t *offsets;
38
39    int32_t sourceIndex;
40
41    /* set up the local pointers */
42    source=(const uint8_t *)pArgs->source;
43    target=pArgs->target;
44    targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
45    offsets=pArgs->offsets;
46
47    sourceIndex=0;
48
49    /*
50     * since the conversion here is 1:1 UChar:uint8_t, we need only one counter
51     * for the minimum of the sourceLength and targetCapacity
52     */
53    length=(int32_t)((const uint8_t *)pArgs->sourceLimit-source);
54    if(length<=targetCapacity) {
55        targetCapacity=length;
56    } else {
57        /* target will be full */
58        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
59        length=targetCapacity;
60    }
61
62    if(targetCapacity>=8) {
63        /* This loop is unrolled for speed and improved pipelining. */
64        int32_t count, loops;
65
66        loops=count=targetCapacity>>3;
67        length=targetCapacity&=0x7;
68        do {
69            target[0]=source[0];
70            target[1]=source[1];
71            target[2]=source[2];
72            target[3]=source[3];
73            target[4]=source[4];
74            target[5]=source[5];
75            target[6]=source[6];
76            target[7]=source[7];
77            target+=8;
78            source+=8;
79        } while(--count>0);
80
81        if(offsets!=NULL) {
82            do {
83                offsets[0]=sourceIndex++;
84                offsets[1]=sourceIndex++;
85                offsets[2]=sourceIndex++;
86                offsets[3]=sourceIndex++;
87                offsets[4]=sourceIndex++;
88                offsets[5]=sourceIndex++;
89                offsets[6]=sourceIndex++;
90                offsets[7]=sourceIndex++;
91                offsets+=8;
92            } while(--loops>0);
93        }
94    }
95
96    /* conversion loop */
97    while(targetCapacity>0) {
98        *target++=*source++;
99        --targetCapacity;
100    }
101
102    /* write back the updated pointers */
103    pArgs->source=(const char *)source;
104    pArgs->target=target;
105
106    /* set offsets */
107    if(offsets!=NULL) {
108        while(length>0) {
109            *offsets++=sourceIndex++;
110            --length;
111        }
112        pArgs->offsets=offsets;
113    }
114}
115
116/* This is a table-less and callback-less version of ucnv_MBCSSingleGetNextUChar(). */
117static UChar32
118_Latin1GetNextUChar(UConverterToUnicodeArgs *pArgs,
119                    UErrorCode *pErrorCode) {
120    const uint8_t *source=(const uint8_t *)pArgs->source;
121    if(source<(const uint8_t *)pArgs->sourceLimit) {
122        pArgs->source=(const char *)(source+1);
123        return *source;
124    }
125
126    /* no output because of empty input */
127    *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
128    return 0xffff;
129}
130
131/* This is a table-less version of ucnv_MBCSSingleFromBMPWithOffsets(). */
132static void
133_Latin1FromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
134                              UErrorCode *pErrorCode) {
135    UConverter *cnv;
136    const UChar *source, *sourceLimit;
137    uint8_t *target, *oldTarget;
138    int32_t targetCapacity, length;
139    int32_t *offsets;
140
141    UChar32 cp;
142    UChar c, max;
143
144    int32_t sourceIndex;
145
146    /* set up the local pointers */
147    cnv=pArgs->converter;
148    source=pArgs->source;
149    sourceLimit=pArgs->sourceLimit;
150    target=oldTarget=(uint8_t *)pArgs->target;
151    targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
152    offsets=pArgs->offsets;
153
154    if(cnv->sharedData==&_Latin1Data) {
155        max=0xff; /* Latin-1 */
156    } else {
157        max=0x7f; /* US-ASCII */
158    }
159
160    /* get the converter state from UConverter */
161    cp=cnv->fromUChar32;
162
163    /* sourceIndex=-1 if the current character began in the previous buffer */
164    sourceIndex= cp==0 ? 0 : -1;
165
166    /*
167     * since the conversion here is 1:1 UChar:uint8_t, we need only one counter
168     * for the minimum of the sourceLength and targetCapacity
169     */
170    length=(int32_t)(sourceLimit-source);
171    if(length<targetCapacity) {
172        targetCapacity=length;
173    }
174
175    /* conversion loop */
176    if(cp!=0 && targetCapacity>0) {
177        goto getTrail;
178    }
179
180#if LATIN1_UNROLL_FROM_UNICODE
181    /* unroll the loop with the most common case */
182    if(targetCapacity>=16) {
183        int32_t count, loops;
184        UChar u, oredChars;
185
186        loops=count=targetCapacity>>4;
187        do {
188            oredChars=u=*source++;
189            *target++=(uint8_t)u;
190            oredChars|=u=*source++;
191            *target++=(uint8_t)u;
192            oredChars|=u=*source++;
193            *target++=(uint8_t)u;
194            oredChars|=u=*source++;
195            *target++=(uint8_t)u;
196            oredChars|=u=*source++;
197            *target++=(uint8_t)u;
198            oredChars|=u=*source++;
199            *target++=(uint8_t)u;
200            oredChars|=u=*source++;
201            *target++=(uint8_t)u;
202            oredChars|=u=*source++;
203            *target++=(uint8_t)u;
204            oredChars|=u=*source++;
205            *target++=(uint8_t)u;
206            oredChars|=u=*source++;
207            *target++=(uint8_t)u;
208            oredChars|=u=*source++;
209            *target++=(uint8_t)u;
210            oredChars|=u=*source++;
211            *target++=(uint8_t)u;
212            oredChars|=u=*source++;
213            *target++=(uint8_t)u;
214            oredChars|=u=*source++;
215            *target++=(uint8_t)u;
216            oredChars|=u=*source++;
217            *target++=(uint8_t)u;
218            oredChars|=u=*source++;
219            *target++=(uint8_t)u;
220
221            /* were all 16 entries really valid? */
222            if(oredChars>max) {
223                /* no, return to the first of these 16 */
224                source-=16;
225                target-=16;
226                break;
227            }
228        } while(--count>0);
229        count=loops-count;
230        targetCapacity-=16*count;
231
232        if(offsets!=NULL) {
233            oldTarget+=16*count;
234            while(count>0) {
235                *offsets++=sourceIndex++;
236                *offsets++=sourceIndex++;
237                *offsets++=sourceIndex++;
238                *offsets++=sourceIndex++;
239                *offsets++=sourceIndex++;
240                *offsets++=sourceIndex++;
241                *offsets++=sourceIndex++;
242                *offsets++=sourceIndex++;
243                *offsets++=sourceIndex++;
244                *offsets++=sourceIndex++;
245                *offsets++=sourceIndex++;
246                *offsets++=sourceIndex++;
247                *offsets++=sourceIndex++;
248                *offsets++=sourceIndex++;
249                *offsets++=sourceIndex++;
250                *offsets++=sourceIndex++;
251                --count;
252            }
253        }
254    }
255#endif
256
257    /* conversion loop */
258    c=0;
259    while(targetCapacity>0 && (c=*source++)<=max) {
260        /* convert the Unicode code point */
261        *target++=(uint8_t)c;
262        --targetCapacity;
263    }
264
265    if(c>max) {
266        cp=c;
267        if(!U_IS_SURROGATE(cp)) {
268            /* callback(unassigned) */
269        } else if(U_IS_SURROGATE_LEAD(cp)) {
270getTrail:
271            if(source<sourceLimit) {
272                /* test the following code unit */
273                UChar trail=*source;
274                if(U16_IS_TRAIL(trail)) {
275                    ++source;
276                    cp=U16_GET_SUPPLEMENTARY(cp, trail);
277                    /* this codepage does not map supplementary code points */
278                    /* callback(unassigned) */
279                } else {
280                    /* this is an unmatched lead code unit (1st surrogate) */
281                    /* callback(illegal) */
282                }
283            } else {
284                /* no more input */
285                cnv->fromUChar32=cp;
286                goto noMoreInput;
287            }
288        } else {
289            /* this is an unmatched trail code unit (2nd surrogate) */
290            /* callback(illegal) */
291        }
292
293        *pErrorCode= U_IS_SURROGATE(cp) ? U_ILLEGAL_CHAR_FOUND : U_INVALID_CHAR_FOUND;
294        cnv->fromUChar32=cp;
295    }
296noMoreInput:
297
298    /* set offsets since the start */
299    if(offsets!=NULL) {
300        size_t count=target-oldTarget;
301        while(count>0) {
302            *offsets++=sourceIndex++;
303            --count;
304        }
305    }
306
307    if(U_SUCCESS(*pErrorCode) && source<sourceLimit && target>=(uint8_t *)pArgs->targetLimit) {
308        /* target is full */
309        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
310    }
311
312    /* write back the updated pointers */
313    pArgs->source=source;
314    pArgs->target=(char *)target;
315    pArgs->offsets=offsets;
316}
317
318/* Convert UTF-8 to Latin-1. Adapted from ucnv_SBCSFromUTF8(). */
319static void
320ucnv_Latin1FromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
321                    UConverterToUnicodeArgs *pToUArgs,
322                    UErrorCode *pErrorCode) {
323    UConverter *utf8;
324    const uint8_t *source, *sourceLimit;
325    uint8_t *target;
326    int32_t targetCapacity;
327
328    UChar32 c;
329    uint8_t b, t1;
330
331    /* set up the local pointers */
332    utf8=pToUArgs->converter;
333    source=(uint8_t *)pToUArgs->source;
334    sourceLimit=(uint8_t *)pToUArgs->sourceLimit;
335    target=(uint8_t *)pFromUArgs->target;
336    targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
337
338    /* get the converter state from the UTF-8 UConverter */
339    c=(UChar32)utf8->toUnicodeStatus;
340    if(c!=0 && source<sourceLimit) {
341        if(targetCapacity==0) {
342            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
343            return;
344        } else if(c>=0xc2 && c<=0xc3 && (t1=(uint8_t)(*source-0x80)) <= 0x3f) {
345            ++source;
346            *target++=(uint8_t)(((c&3)<<6)|t1);
347            --targetCapacity;
348
349            utf8->toUnicodeStatus=0;
350            utf8->toULength=0;
351        } else {
352            /* complicated, illegal or unmappable input: fall back to the pivoting implementation */
353            *pErrorCode=U_USING_DEFAULT_WARNING;
354            return;
355        }
356    }
357
358    /*
359     * Make sure that the last byte sequence before sourceLimit is complete
360     * or runs into a lead byte.
361     * In the conversion loop compare source with sourceLimit only once
362     * per multi-byte character.
363     * For Latin-1, adjust sourceLimit only for 1 trail byte because
364     * the conversion loop handles at most 2-byte sequences.
365     */
366    if(source<sourceLimit && U8_IS_LEAD(*(sourceLimit-1))) {
367        --sourceLimit;
368    }
369
370    /* conversion loop */
371    while(source<sourceLimit) {
372        if(targetCapacity>0) {
373            b=*source++;
374            if((int8_t)b>=0) {
375                /* convert ASCII */
376                *target++=(uint8_t)b;
377                --targetCapacity;
378            } else if( /* handle U+0080..U+00FF inline */
379                       b>=0xc2 && b<=0xc3 &&
380                       (t1=(uint8_t)(*source-0x80)) <= 0x3f
381            ) {
382                ++source;
383                *target++=(uint8_t)(((b&3)<<6)|t1);
384                --targetCapacity;
385            } else {
386                /* complicated, illegal or unmappable input: fall back to the pivoting implementation */
387                pToUArgs->source=(char *)(source-1);
388                pFromUArgs->target=(char *)target;
389                *pErrorCode=U_USING_DEFAULT_WARNING;
390                return;
391            }
392        } else {
393            /* target is full */
394            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
395            break;
396        }
397    }
398
399    /*
400     * The sourceLimit may have been adjusted before the conversion loop
401     * to stop before a truncated sequence.
402     * If so, then collect the truncated sequence now.
403     * For Latin-1, there is at most exactly one lead byte because of the
404     * smaller sourceLimit adjustment logic.
405     */
406    if(U_SUCCESS(*pErrorCode) && source<(sourceLimit=(uint8_t *)pToUArgs->sourceLimit)) {
407        utf8->toUnicodeStatus=utf8->toUBytes[0]=b=*source++;
408        utf8->toULength=1;
409        utf8->mode=U8_COUNT_TRAIL_BYTES(b)+1;
410    }
411
412    /* write back the updated pointers */
413    pToUArgs->source=(char *)source;
414    pFromUArgs->target=(char *)target;
415}
416
417static void
418_Latin1GetUnicodeSet(const UConverter *cnv,
419                     const USetAdder *sa,
420                     UConverterUnicodeSet which,
421                     UErrorCode *pErrorCode) {
422    sa->addRange(sa->set, 0, 0xff);
423}
424
425static const UConverterImpl _Latin1Impl={
426    UCNV_LATIN_1,
427
428    NULL,
429    NULL,
430
431    NULL,
432    NULL,
433    NULL,
434
435    _Latin1ToUnicodeWithOffsets,
436    _Latin1ToUnicodeWithOffsets,
437    _Latin1FromUnicodeWithOffsets,
438    _Latin1FromUnicodeWithOffsets,
439    _Latin1GetNextUChar,
440
441    NULL,
442    NULL,
443    NULL,
444    NULL,
445    _Latin1GetUnicodeSet,
446
447    NULL,
448    ucnv_Latin1FromUTF8
449};
450
451static const UConverterStaticData _Latin1StaticData={
452    sizeof(UConverterStaticData),
453    "ISO-8859-1",
454    819, UCNV_IBM, UCNV_LATIN_1, 1, 1,
455    { 0x1a, 0, 0, 0 }, 1, FALSE, FALSE,
456    0,
457    0,
458    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
459};
460
461const UConverterSharedData _Latin1Data={
462    sizeof(UConverterSharedData), ~((uint32_t) 0),
463    NULL, NULL, &_Latin1StaticData, FALSE, &_Latin1Impl,
464    0
465};
466
467/* US-ASCII ----------------------------------------------------------------- */
468
469/* This is a table-less version of ucnv_MBCSSingleToBMPWithOffsets(). */
470static void
471_ASCIIToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
472                           UErrorCode *pErrorCode) {
473    const uint8_t *source, *sourceLimit;
474    UChar *target, *oldTarget;
475    int32_t targetCapacity, length;
476    int32_t *offsets;
477
478    int32_t sourceIndex;
479
480    uint8_t c;
481
482    /* set up the local pointers */
483    source=(const uint8_t *)pArgs->source;
484    sourceLimit=(const uint8_t *)pArgs->sourceLimit;
485    target=oldTarget=pArgs->target;
486    targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
487    offsets=pArgs->offsets;
488
489    /* sourceIndex=-1 if the current character began in the previous buffer */
490    sourceIndex=0;
491
492    /*
493     * since the conversion here is 1:1 UChar:uint8_t, we need only one counter
494     * for the minimum of the sourceLength and targetCapacity
495     */
496    length=(int32_t)(sourceLimit-source);
497    if(length<targetCapacity) {
498        targetCapacity=length;
499    }
500
501    if(targetCapacity>=8) {
502        /* This loop is unrolled for speed and improved pipelining. */
503        int32_t count, loops;
504        UChar oredChars;
505
506        loops=count=targetCapacity>>3;
507        do {
508            oredChars=target[0]=source[0];
509            oredChars|=target[1]=source[1];
510            oredChars|=target[2]=source[2];
511            oredChars|=target[3]=source[3];
512            oredChars|=target[4]=source[4];
513            oredChars|=target[5]=source[5];
514            oredChars|=target[6]=source[6];
515            oredChars|=target[7]=source[7];
516
517            /* were all 16 entries really valid? */
518            if(oredChars>0x7f) {
519                /* no, return to the first of these 16 */
520                break;
521            }
522            source+=8;
523            target+=8;
524        } while(--count>0);
525        count=loops-count;
526        targetCapacity-=count*8;
527
528        if(offsets!=NULL) {
529            oldTarget+=count*8;
530            while(count>0) {
531                offsets[0]=sourceIndex++;
532                offsets[1]=sourceIndex++;
533                offsets[2]=sourceIndex++;
534                offsets[3]=sourceIndex++;
535                offsets[4]=sourceIndex++;
536                offsets[5]=sourceIndex++;
537                offsets[6]=sourceIndex++;
538                offsets[7]=sourceIndex++;
539                offsets+=8;
540                --count;
541            }
542        }
543    }
544
545    /* conversion loop */
546    c=0;
547    while(targetCapacity>0 && (c=*source++)<=0x7f) {
548        *target++=c;
549        --targetCapacity;
550    }
551
552    if(c>0x7f) {
553        /* callback(illegal); copy the current bytes to toUBytes[] */
554        UConverter *cnv=pArgs->converter;
555        cnv->toUBytes[0]=c;
556        cnv->toULength=1;
557        *pErrorCode=U_ILLEGAL_CHAR_FOUND;
558    } else if(source<sourceLimit && target>=pArgs->targetLimit) {
559        /* target is full */
560        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
561    }
562
563    /* set offsets since the start */
564    if(offsets!=NULL) {
565        size_t count=target-oldTarget;
566        while(count>0) {
567            *offsets++=sourceIndex++;
568            --count;
569        }
570    }
571
572    /* write back the updated pointers */
573    pArgs->source=(const char *)source;
574    pArgs->target=target;
575    pArgs->offsets=offsets;
576}
577
578/* This is a table-less version of ucnv_MBCSSingleGetNextUChar(). */
579static UChar32
580_ASCIIGetNextUChar(UConverterToUnicodeArgs *pArgs,
581                   UErrorCode *pErrorCode) {
582    const uint8_t *source;
583    uint8_t b;
584
585    source=(const uint8_t *)pArgs->source;
586    if(source<(const uint8_t *)pArgs->sourceLimit) {
587        b=*source++;
588        pArgs->source=(const char *)source;
589        if(b<=0x7f) {
590            return b;
591        } else {
592            UConverter *cnv=pArgs->converter;
593            cnv->toUBytes[0]=b;
594            cnv->toULength=1;
595            *pErrorCode=U_ILLEGAL_CHAR_FOUND;
596            return 0xffff;
597        }
598    }
599
600    /* no output because of empty input */
601    *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
602    return 0xffff;
603}
604
605/* "Convert" UTF-8 to US-ASCII: Validate and copy. */
606static void
607ucnv_ASCIIFromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
608                   UConverterToUnicodeArgs *pToUArgs,
609                   UErrorCode *pErrorCode) {
610    const uint8_t *source, *sourceLimit;
611    uint8_t *target;
612    int32_t targetCapacity, length;
613
614    uint8_t c;
615
616    if(pToUArgs->converter->toUnicodeStatus!=0) {
617        /* no handling of partial UTF-8 characters here, fall back to pivoting */
618        *pErrorCode=U_USING_DEFAULT_WARNING;
619        return;
620    }
621
622    /* set up the local pointers */
623    source=(const uint8_t *)pToUArgs->source;
624    sourceLimit=(const uint8_t *)pToUArgs->sourceLimit;
625    target=(uint8_t *)pFromUArgs->target;
626    targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
627
628    /*
629     * since the conversion here is 1:1 uint8_t:uint8_t, we need only one counter
630     * for the minimum of the sourceLength and targetCapacity
631     */
632    length=(int32_t)(sourceLimit-source);
633    if(length<targetCapacity) {
634        targetCapacity=length;
635    }
636
637    /* unroll the loop with the most common case */
638    if(targetCapacity>=16) {
639        int32_t count, loops;
640        uint8_t oredChars;
641
642        loops=count=targetCapacity>>4;
643        do {
644            oredChars=*target++=*source++;
645            oredChars|=*target++=*source++;
646            oredChars|=*target++=*source++;
647            oredChars|=*target++=*source++;
648            oredChars|=*target++=*source++;
649            oredChars|=*target++=*source++;
650            oredChars|=*target++=*source++;
651            oredChars|=*target++=*source++;
652            oredChars|=*target++=*source++;
653            oredChars|=*target++=*source++;
654            oredChars|=*target++=*source++;
655            oredChars|=*target++=*source++;
656            oredChars|=*target++=*source++;
657            oredChars|=*target++=*source++;
658            oredChars|=*target++=*source++;
659            oredChars|=*target++=*source++;
660
661            /* were all 16 entries really valid? */
662            if(oredChars>0x7f) {
663                /* no, return to the first of these 16 */
664                source-=16;
665                target-=16;
666                break;
667            }
668        } while(--count>0);
669        count=loops-count;
670        targetCapacity-=16*count;
671    }
672
673    /* conversion loop */
674    c=0;
675    while(targetCapacity>0 && (c=*source)<=0x7f) {
676        ++source;
677        *target++=c;
678        --targetCapacity;
679    }
680
681    if(c>0x7f) {
682        /* non-ASCII character, handle in standard converter */
683        *pErrorCode=U_USING_DEFAULT_WARNING;
684    } else if(source<sourceLimit && target>=(const uint8_t *)pFromUArgs->targetLimit) {
685        /* target is full */
686        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
687    }
688
689    /* write back the updated pointers */
690    pToUArgs->source=(const char *)source;
691    pFromUArgs->target=(char *)target;
692}
693
694static void
695_ASCIIGetUnicodeSet(const UConverter *cnv,
696                    const USetAdder *sa,
697                    UConverterUnicodeSet which,
698                    UErrorCode *pErrorCode) {
699    sa->addRange(sa->set, 0, 0x7f);
700}
701
702static const UConverterImpl _ASCIIImpl={
703    UCNV_US_ASCII,
704
705    NULL,
706    NULL,
707
708    NULL,
709    NULL,
710    NULL,
711
712    _ASCIIToUnicodeWithOffsets,
713    _ASCIIToUnicodeWithOffsets,
714    _Latin1FromUnicodeWithOffsets,
715    _Latin1FromUnicodeWithOffsets,
716    _ASCIIGetNextUChar,
717
718    NULL,
719    NULL,
720    NULL,
721    NULL,
722    _ASCIIGetUnicodeSet,
723
724    NULL,
725    ucnv_ASCIIFromUTF8
726};
727
728static const UConverterStaticData _ASCIIStaticData={
729    sizeof(UConverterStaticData),
730    "US-ASCII",
731    367, UCNV_IBM, UCNV_US_ASCII, 1, 1,
732    { 0x1a, 0, 0, 0 }, 1, FALSE, FALSE,
733    0,
734    0,
735    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
736};
737
738const UConverterSharedData _ASCIIData={
739    sizeof(UConverterSharedData), ~((uint32_t) 0),
740    NULL, NULL, &_ASCIIStaticData, FALSE, &_ASCIIImpl,
741    0
742};
743
744#endif
745