tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ucnvlat1.cpp (22301B)


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