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