Coverage Report

Created: 2024-04-24 06:23

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