1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru**********************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Copyright (C) 2000-2006, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru**********************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  ucnv_cb.c:
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  External APIs for the ICU's codeset conversion library
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  Helena Shih
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Modification History:
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   Date        Name        Description
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   7/28/2000   srl         Implementation
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @name Character Conversion C API
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_CONVERSION
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv_cb.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_bld.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_cnv.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* need to update the offsets when the target moves. */
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Note: Recursion may occur in the cb functions, be sure to update the offsets correctly
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruif you don't use ucnv_cbXXX functions.  Make sure you don't use the same callback within
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruthe same call stack if the complexity arises. */
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_cbFromUWriteBytes (UConverterFromUnicodeArgs *args,
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const char* source,
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       int32_t length,
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       int32_t offsetIndex,
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       UErrorCode * err)
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_fromUWriteBytes(
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args->converter,
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source, length,
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &args->target, args->targetLimit,
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &args->offsets, offsetIndex,
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        err);
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_cbFromUWriteUChars(UConverterFromUnicodeArgs *args,
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             const UChar** source,
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             const UChar*  sourceLimit,
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             int32_t offsetIndex,
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode * err)
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    This is a fun one.  Recursion can occur - we're basically going to
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    just retry shoving data through the same converter. Note, if you got
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    here through some kind of invalid sequence, you maybe should emit a
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    reset sequence of some kind and/or call ucnv_reset().  Since this
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    IS an actual conversion, take care that you've changed the callback
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    or the data, or you'll get an infinite loop.
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Please set the err value to something reasonable before calling
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    into this.
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *oldTarget;
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err))
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    oldTarget = args->target;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_fromUnicode(args->converter,
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &args->target,
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args->targetLimit,
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source,
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit,
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        NULL, /* no offsets */
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        FALSE, /* no flush */
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        err);
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(args->offsets)
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (args->target != oldTarget)  /* if it moved at all.. */
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *(args->offsets)++ = offsetIndex;
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            oldTarget++;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Note, if you did something like used a Stop subcallback, things would get interesting.
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    In fact, here's where we want to return the partially consumed in-source!
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(*err == U_BUFFER_OVERFLOW_ERROR)
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* && (*source < sourceLimit && args->target >= args->targetLimit)
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    -- S. Hrcek */
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Overflowed the target.  Now, we'll write into the charErrorBuffer.
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        It's a fixed size. If we overflow it... Hmm */
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char *newTarget;
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *newTargetLimit;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode err2 = U_ZERO_ERROR;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int8_t errBuffLen;
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errBuffLen  = args->converter->charErrorBufferLength;
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* start the new target at the first free slot in the errbuff.. */
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        newTarget = (char *)(args->converter->charErrorBuffer + errBuffLen);
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        newTargetLimit = (char *)(args->converter->charErrorBuffer +
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sizeof(args->converter->charErrorBuffer));
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(newTarget >= newTargetLimit)
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_INTERNAL_PROGRAM_ERROR;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* We're going to tell the converter that the errbuff len is empty.
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        This prevents the existing errbuff from being 'flushed' out onto
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        itself.  If the errbuff is needed by the converter this time,
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        we're hosed - we're out of space! */
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args->converter->charErrorBufferLength = 0;
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_fromUnicode(args->converter,
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         &newTarget,
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         newTargetLimit,
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         source,
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         sourceLimit,
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         NULL,
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         FALSE,
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         &err2);
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* We can go ahead and overwrite the  length here. We know just how
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        to recalculate it. */
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args->converter->charErrorBufferLength = (int8_t)(
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            newTarget - (char*)args->converter->charErrorBuffer);
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((newTarget >= newTargetLimit) || (err2 == U_BUFFER_OVERFLOW_ERROR))
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* now we're REALLY in trouble.
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Internal program error - callback shouldn't have written this much
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            data!
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_INTERNAL_PROGRAM_ERROR;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*else {*/
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* sub errs could be invalid/truncated/illegal chars or w/e.
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            These might want to be passed on up.. But the problem is, we already
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            need to pass U_BUFFER_OVERFLOW_ERROR. That has to override these
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            other errs.. */
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_FAILURE(err2))
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ??
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*}*/
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_cbFromUWriteSub (UConverterFromUnicodeArgs *args,
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           int32_t offsetIndex,
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UErrorCode * err)
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *converter;
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length;
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter = args->converter;
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    length = converter->subCharLen;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length == 0) {
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length < 0) {
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Write/convert the substitution string. Its real length is -length.
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Unlike the escape callback, we need not change the converter's
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * callback function because ucnv_setSubstString() verified that
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * the string can be converted, so we will not get a conversion error
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * and will not recurse.
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * At worst we should get a U_BUFFER_OVERFLOW_ERROR.
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UChar *source = (const UChar *)converter->subChars;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_cbFromUWriteUChars(args, &source, source - length, offsetIndex, err);
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(converter->sharedData->impl->writeSub!=NULL) {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->sharedData->impl->writeSub(args, offsetIndex, err);
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(converter->subChar1!=0 && (uint16_t)converter->invalidUCharBuffer[0]<=(uint16_t)0xffu) {
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        TODO: Is this untestable because the MBCS converter has a writeSub function to call
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        and the other converters don't use subChar1?
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        */
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_cbFromUWriteBytes(args,
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               (const char *)&converter->subChar1, 1,
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               offsetIndex, err);
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_cbFromUWriteBytes(args,
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               (const char *)converter->subChars, length,
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               offsetIndex, err);
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_cbToUWriteUChars (UConverterToUnicodeArgs *args,
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const UChar* source,
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t length,
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t offsetIndex,
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode * err)
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_toUWriteUChars(
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args->converter,
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source, length,
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &args->target, args->targetLimit,
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &args->offsets, offsetIndex,
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        err);
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_cbToUWriteSub (UConverterToUnicodeArgs *args,
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         int32_t offsetIndex,
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       UErrorCode * err)
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const UChar kSubstituteChar1 = 0x1A, kSubstituteChar = 0xFFFD;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* could optimize this case, just one uchar */
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(args->converter->invalidCharLength == 1 && args->converter->subChar1 != 0) {
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_cbToUWriteUChars(args, &kSubstituteChar1, 1, offsetIndex, err);
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_cbToUWriteUChars(args, &kSubstituteChar, 1, offsetIndex, err);
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
260