• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
_Latin1ToUnicodeWithOffsets(UConverterToUnicodeArgs * pArgs,UErrorCode * pErrorCode)36 _Latin1ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
37                             UErrorCode *pErrorCode) {
38     const uint8_t *source;
39     UChar *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 UChar: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!=NULL) {
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!=NULL) {
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
_Latin1GetNextUChar(UConverterToUnicodeArgs * pArgs,UErrorCode * pErrorCode)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
_Latin1FromUnicodeWithOffsets(UConverterFromUnicodeArgs * pArgs,UErrorCode * pErrorCode)137 _Latin1FromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs,
138                               UErrorCode *pErrorCode) {
139     UConverter *cnv;
140     const UChar *source, *sourceLimit;
141     uint8_t *target, *oldTarget;
142     int32_t targetCapacity, length;
143     int32_t *offsets;
144 
145     UChar32 cp;
146     UChar 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 UChar: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         UChar 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!=NULL) {
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                 UChar 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!=NULL) {
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
ucnv_Latin1FromUTF8(UConverterFromUnicodeArgs * pFromUArgs,UConverterToUnicodeArgs * pToUArgs,UErrorCode * pErrorCode)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     c=(UChar32)utf8->toUnicodeStatus;
344     if(c!=0 && source<sourceLimit) {
345         if(targetCapacity==0) {
346             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
347             return;
348         } else if(c>=0xc2 && c<=0xc3 && (t1=(uint8_t)(*source-0x80)) <= 0x3f) {
349             ++source;
350             *target++=(uint8_t)(((c&3)<<6)|t1);
351             --targetCapacity;
352 
353             utf8->toUnicodeStatus=0;
354             utf8->toULength=0;
355         } else {
356             /* complicated, illegal or unmappable input: fall back to the pivoting implementation */
357             *pErrorCode=U_USING_DEFAULT_WARNING;
358             return;
359         }
360     }
361 
362     /*
363      * Make sure that the last byte sequence before sourceLimit is complete
364      * or runs into a lead byte.
365      * In the conversion loop compare source with sourceLimit only once
366      * per multi-byte character.
367      * For Latin-1, adjust sourceLimit only for 1 trail byte because
368      * the conversion loop handles at most 2-byte sequences.
369      */
370     if(source<sourceLimit && U8_IS_LEAD(*(sourceLimit-1))) {
371         --sourceLimit;
372     }
373 
374     /* conversion loop */
375     while(source<sourceLimit) {
376         if(targetCapacity>0) {
377             b=*source++;
378             if(U8_IS_SINGLE(b)) {
379                 /* convert ASCII */
380                 *target++=(uint8_t)b;
381                 --targetCapacity;
382             } else if( /* handle U+0080..U+00FF inline */
383                        b>=0xc2 && b<=0xc3 &&
384                        (t1=(uint8_t)(*source-0x80)) <= 0x3f
385             ) {
386                 ++source;
387                 *target++=(uint8_t)(((b&3)<<6)|t1);
388                 --targetCapacity;
389             } else {
390                 /* complicated, illegal or unmappable input: fall back to the pivoting implementation */
391                 pToUArgs->source=(char *)(source-1);
392                 pFromUArgs->target=(char *)target;
393                 *pErrorCode=U_USING_DEFAULT_WARNING;
394                 return;
395             }
396         } else {
397             /* target is full */
398             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
399             break;
400         }
401     }
402 
403     /*
404      * The sourceLimit may have been adjusted before the conversion loop
405      * to stop before a truncated sequence.
406      * If so, then collect the truncated sequence now.
407      * For Latin-1, there is at most exactly one lead byte because of the
408      * smaller sourceLimit adjustment logic.
409      */
410     if(U_SUCCESS(*pErrorCode) && source<(sourceLimit=(uint8_t *)pToUArgs->sourceLimit)) {
411         utf8->toUnicodeStatus=utf8->toUBytes[0]=b=*source++;
412         utf8->toULength=1;
413         utf8->mode=U8_COUNT_BYTES(b);
414     }
415 
416     /* write back the updated pointers */
417     pToUArgs->source=(char *)source;
418     pFromUArgs->target=(char *)target;
419 }
420 
421 static void U_CALLCONV
_Latin1GetUnicodeSet(const UConverter * cnv,const USetAdder * sa,UConverterUnicodeSet which,UErrorCode * pErrorCode)422 _Latin1GetUnicodeSet(const UConverter *cnv,
423                      const USetAdder *sa,
424                      UConverterUnicodeSet which,
425                      UErrorCode *pErrorCode) {
426     (void)cnv;
427     (void)which;
428     (void)pErrorCode;
429     sa->addRange(sa->set, 0, 0xff);
430 }
431 U_CDECL_END
432 
433 
434 static const UConverterImpl _Latin1Impl={
435     UCNV_LATIN_1,
436 
437     NULL,
438     NULL,
439 
440     NULL,
441     NULL,
442     NULL,
443 
444     _Latin1ToUnicodeWithOffsets,
445     _Latin1ToUnicodeWithOffsets,
446     _Latin1FromUnicodeWithOffsets,
447     _Latin1FromUnicodeWithOffsets,
448     _Latin1GetNextUChar,
449 
450     NULL,
451     NULL,
452     NULL,
453     NULL,
454     _Latin1GetUnicodeSet,
455 
456     NULL,
457     ucnv_Latin1FromUTF8
458 };
459 
460 static const UConverterStaticData _Latin1StaticData={
461     sizeof(UConverterStaticData),
462     "ISO-8859-1",
463     819, UCNV_IBM, UCNV_LATIN_1, 1, 1,
464     { 0x1a, 0, 0, 0 }, 1, FALSE, FALSE,
465     0,
466     0,
467     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
468 };
469 
470 const UConverterSharedData _Latin1Data=
471         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_Latin1StaticData, &_Latin1Impl);
472 
473 /* US-ASCII ----------------------------------------------------------------- */
474 
475 U_CDECL_BEGIN
476 /* This is a table-less version of ucnv_MBCSSingleToBMPWithOffsets(). */
477 static void U_CALLCONV
_ASCIIToUnicodeWithOffsets(UConverterToUnicodeArgs * pArgs,UErrorCode * pErrorCode)478 _ASCIIToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
479                            UErrorCode *pErrorCode) {
480     const uint8_t *source, *sourceLimit;
481     UChar *target, *oldTarget;
482     int32_t targetCapacity, length;
483     int32_t *offsets;
484 
485     int32_t sourceIndex;
486 
487     uint8_t c;
488 
489     /* set up the local pointers */
490     source=(const uint8_t *)pArgs->source;
491     sourceLimit=(const uint8_t *)pArgs->sourceLimit;
492     target=oldTarget=pArgs->target;
493     targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
494     offsets=pArgs->offsets;
495 
496     /* sourceIndex=-1 if the current character began in the previous buffer */
497     sourceIndex=0;
498 
499     /*
500      * since the conversion here is 1:1 UChar:uint8_t, we need only one counter
501      * for the minimum of the sourceLength and targetCapacity
502      */
503     length=(int32_t)(sourceLimit-source);
504     if(length<targetCapacity) {
505         targetCapacity=length;
506     }
507 
508     if(targetCapacity>=8) {
509         /* This loop is unrolled for speed and improved pipelining. */
510         int32_t count, loops;
511         UChar oredChars;
512 
513         loops=count=targetCapacity>>3;
514         do {
515             oredChars=target[0]=source[0];
516             oredChars|=target[1]=source[1];
517             oredChars|=target[2]=source[2];
518             oredChars|=target[3]=source[3];
519             oredChars|=target[4]=source[4];
520             oredChars|=target[5]=source[5];
521             oredChars|=target[6]=source[6];
522             oredChars|=target[7]=source[7];
523 
524             /* were all 16 entries really valid? */
525             if(oredChars>0x7f) {
526                 /* no, return to the first of these 16 */
527                 break;
528             }
529             source+=8;
530             target+=8;
531         } while(--count>0);
532         count=loops-count;
533         targetCapacity-=count*8;
534 
535         if(offsets!=NULL) {
536             oldTarget+=count*8;
537             while(count>0) {
538                 offsets[0]=sourceIndex++;
539                 offsets[1]=sourceIndex++;
540                 offsets[2]=sourceIndex++;
541                 offsets[3]=sourceIndex++;
542                 offsets[4]=sourceIndex++;
543                 offsets[5]=sourceIndex++;
544                 offsets[6]=sourceIndex++;
545                 offsets[7]=sourceIndex++;
546                 offsets+=8;
547                 --count;
548             }
549         }
550     }
551 
552     /* conversion loop */
553     c=0;
554     while(targetCapacity>0 && (c=*source++)<=0x7f) {
555         *target++=c;
556         --targetCapacity;
557     }
558 
559     if(c>0x7f) {
560         /* callback(illegal); copy the current bytes to toUBytes[] */
561         UConverter *cnv=pArgs->converter;
562         cnv->toUBytes[0]=c;
563         cnv->toULength=1;
564         *pErrorCode=U_ILLEGAL_CHAR_FOUND;
565     } else if(source<sourceLimit && target>=pArgs->targetLimit) {
566         /* target is full */
567         *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
568     }
569 
570     /* set offsets since the start */
571     if(offsets!=NULL) {
572         size_t count=target-oldTarget;
573         while(count>0) {
574             *offsets++=sourceIndex++;
575             --count;
576         }
577     }
578 
579     /* write back the updated pointers */
580     pArgs->source=(const char *)source;
581     pArgs->target=target;
582     pArgs->offsets=offsets;
583 }
584 
585 /* This is a table-less version of ucnv_MBCSSingleGetNextUChar(). */
586 static UChar32 U_CALLCONV
_ASCIIGetNextUChar(UConverterToUnicodeArgs * pArgs,UErrorCode * pErrorCode)587 _ASCIIGetNextUChar(UConverterToUnicodeArgs *pArgs,
588                    UErrorCode *pErrorCode) {
589     const uint8_t *source;
590     uint8_t b;
591 
592     source=(const uint8_t *)pArgs->source;
593     if(source<(const uint8_t *)pArgs->sourceLimit) {
594         b=*source++;
595         pArgs->source=(const char *)source;
596         if(b<=0x7f) {
597             return b;
598         } else {
599             UConverter *cnv=pArgs->converter;
600             cnv->toUBytes[0]=b;
601             cnv->toULength=1;
602             *pErrorCode=U_ILLEGAL_CHAR_FOUND;
603             return 0xffff;
604         }
605     }
606 
607     /* no output because of empty input */
608     *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
609     return 0xffff;
610 }
611 
612 /* "Convert" UTF-8 to US-ASCII: Validate and copy. */
613 static void U_CALLCONV
ucnv_ASCIIFromUTF8(UConverterFromUnicodeArgs * pFromUArgs,UConverterToUnicodeArgs * pToUArgs,UErrorCode * pErrorCode)614 ucnv_ASCIIFromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
615                    UConverterToUnicodeArgs *pToUArgs,
616                    UErrorCode *pErrorCode) {
617     const uint8_t *source, *sourceLimit;
618     uint8_t *target;
619     int32_t targetCapacity, length;
620 
621     uint8_t c;
622 
623     if(pToUArgs->converter->toUnicodeStatus!=0) {
624         /* no handling of partial UTF-8 characters here, fall back to pivoting */
625         *pErrorCode=U_USING_DEFAULT_WARNING;
626         return;
627     }
628 
629     /* set up the local pointers */
630     source=(const uint8_t *)pToUArgs->source;
631     sourceLimit=(const uint8_t *)pToUArgs->sourceLimit;
632     target=(uint8_t *)pFromUArgs->target;
633     targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
634 
635     /*
636      * since the conversion here is 1:1 uint8_t:uint8_t, we need only one counter
637      * for the minimum of the sourceLength and targetCapacity
638      */
639     length=(int32_t)(sourceLimit-source);
640     if(length<targetCapacity) {
641         targetCapacity=length;
642     }
643 
644     /* unroll the loop with the most common case */
645     if(targetCapacity>=16) {
646         int32_t count, loops;
647         uint8_t oredChars;
648 
649         loops=count=targetCapacity>>4;
650         do {
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             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 
668             /* were all 16 entries really valid? */
669             if(oredChars>0x7f) {
670                 /* no, return to the first of these 16 */
671                 source-=16;
672                 target-=16;
673                 break;
674             }
675         } while(--count>0);
676         count=loops-count;
677         targetCapacity-=16*count;
678     }
679 
680     /* conversion loop */
681     c=0;
682     while(targetCapacity>0 && (c=*source)<=0x7f) {
683         ++source;
684         *target++=c;
685         --targetCapacity;
686     }
687 
688     if(c>0x7f) {
689         /* non-ASCII character, handle in standard converter */
690         *pErrorCode=U_USING_DEFAULT_WARNING;
691     } else if(source<sourceLimit && target>=(const uint8_t *)pFromUArgs->targetLimit) {
692         /* target is full */
693         *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
694     }
695 
696     /* write back the updated pointers */
697     pToUArgs->source=(const char *)source;
698     pFromUArgs->target=(char *)target;
699 }
700 
701 static void U_CALLCONV
_ASCIIGetUnicodeSet(const UConverter * cnv,const USetAdder * sa,UConverterUnicodeSet which,UErrorCode * pErrorCode)702 _ASCIIGetUnicodeSet(const UConverter *cnv,
703                     const USetAdder *sa,
704                     UConverterUnicodeSet which,
705                     UErrorCode *pErrorCode) {
706     (void)cnv;
707     (void)which;
708     (void)pErrorCode;
709     sa->addRange(sa->set, 0, 0x7f);
710 }
711 U_CDECL_END
712 
713 static const UConverterImpl _ASCIIImpl={
714     UCNV_US_ASCII,
715 
716     NULL,
717     NULL,
718 
719     NULL,
720     NULL,
721     NULL,
722 
723     _ASCIIToUnicodeWithOffsets,
724     _ASCIIToUnicodeWithOffsets,
725     _Latin1FromUnicodeWithOffsets,
726     _Latin1FromUnicodeWithOffsets,
727     _ASCIIGetNextUChar,
728 
729     NULL,
730     NULL,
731     NULL,
732     NULL,
733     _ASCIIGetUnicodeSet,
734 
735     NULL,
736     ucnv_ASCIIFromUTF8
737 };
738 
739 static const UConverterStaticData _ASCIIStaticData={
740     sizeof(UConverterStaticData),
741     "US-ASCII",
742     367, UCNV_IBM, UCNV_US_ASCII, 1, 1,
743     { 0x1a, 0, 0, 0 }, 1, FALSE, FALSE,
744     0,
745     0,
746     { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
747 };
748 
749 const UConverterSharedData _ASCIIData=
750         UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ASCIIStaticData, &_ASCIIImpl);
751 
752 #endif
753