1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
459d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 1998-2013, International Business Machines
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  ucnv.c:
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  Implements APIs for the ICU's codeset conversion library;
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  mostly calls through internal functions;
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*  created by Bertrand A. Damiba
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History:
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   04/04/99    helena      Fixed internal header inclusion.
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   05/09/00    helena      Added implementation to handle fallback mappings.
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   06/20/2000  helena      OS/400 port changes; mostly typecast.
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_CONVERSION
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv_err.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uset.h"
30103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf.h"
31103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf16.h"
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "putilimp.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "utracimp.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ustr_imp.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_imp.h"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_cnv.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_bld.h"
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* size of intermediate and preflighting buffers in ucnv_convert() */
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CHUNK_SIZE 1024
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct UAmbiguousConverter {
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *name;
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar variant5c;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} UAmbiguousConverter;
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UAmbiguousConverter ambiguousConverters[]={
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-897_P100-1995", 0xa5 },
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-942_P120-1999", 0xa5 },
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-943_P130-1999", 0xa5 },
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-946_P100-1995", 0xa5 },
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-33722_P120-1999", 0xa5 },
5627f654740f2a26ad62a5c155af9199af9e69b889claireho    { "ibm-1041_P100-1995", 0xa5 },
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*{ "ibm-54191_P100-2006", 0xa5 },*/
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*{ "ibm-62383_P100-2007", 0xa5 },*/
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*{ "ibm-891_P100-1995", 0x20a9 },*/
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-944_P100-1995", 0x20a9 },
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-949_P110-1999", 0x20a9 },
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    { "ibm-1363_P110-1997", 0x20a9 },
6327f654740f2a26ad62a5c155af9199af9e69b889claireho    { "ISO_2022,locale=ko,version=0", 0x20a9 },
6427f654740f2a26ad62a5c155af9199af9e69b889claireho    { "ibm-1088_P100-1995", 0x20a9 }
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Calls through createConverter */
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverter* U_EXPORT2
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_open (const char *name,
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       UErrorCode * err)
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *r;
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (err == NULL || U_FAILURE (*err)) {
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    r =  ucnv_createConverter(NULL, name, err);
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return r;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverter* U_EXPORT2
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_openPackage   (const char *packageName, const char *converterName, UErrorCode * err)
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_createConverterFromPackage(packageName, converterName,  err);
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Extracts the UChar* to a char* and calls through createConverter */
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverter*   U_EXPORT2
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_openU (const UChar * name,
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode * err)
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char asciiName[UCNV_MAX_CONVERTER_NAME_LENGTH];
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (err == NULL || U_FAILURE(*err))
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (name == NULL)
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return ucnv_open (NULL, err);
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (u_strlen(name) >= UCNV_MAX_CONVERTER_NAME_LENGTH)
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_open(u_austrcpy(asciiName, name), err);
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Copy the string that is represented by the UConverterPlatform enum
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param platformString An output buffer
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param platform An enum representing a platform
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the length of the copied string.
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_copyPlatformString(char *platformString, UConverterPlatform pltfrm)
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (pltfrm)
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UCNV_IBM:
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_strcpy(platformString, "ibm-");
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 4;
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case UCNV_UNKNOWN:
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* default to empty string */
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *platformString = 0;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *through createConverter*/
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverter*   U_EXPORT2
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_openCCSID (int32_t codepage,
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UConverterPlatform platform,
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UErrorCode * err)
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char myName[UCNV_MAX_CONVERTER_NAME_LENGTH];
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t myNameLen;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (err == NULL || U_FAILURE (*err))
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* ucnv_copyPlatformString could return "ibm-" or "cp" */
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myNameLen = ucnv_copyPlatformString(myName, platform);
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    T_CString_integerToString(myName + myNameLen, codepage, 10);
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_createConverter(NULL, myName, err);
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Creating a temporary stack-based object that can be used in one thread,
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruand created from a converter that is shared across threads.
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverter* U_EXPORT2
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status)
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *localConverter, *allocatedConverter;
15759d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t stackBufferSize;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t bufferSizeNeeded;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *stackBufferChars = (char *)stackBuffer;
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode cbErr;
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUnicodeArgs toUArgs = {
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sizeof(UConverterToUnicodeArgs),
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            TRUE,
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    };
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterFromUnicodeArgs fromUArgs = {
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sizeof(UConverterFromUnicodeArgs),
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            TRUE,
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL,
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NULL
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    };
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_CLONE);
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (status == NULL || U_FAILURE(*status)){
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(status? *status: U_ILLEGAL_ARGUMENT_ERROR);
18659d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (cnv == NULL) {
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_ILLEGAL_ARGUMENT_ERROR;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*status);
19259d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA3(UTRACE_OPEN_CLOSE, "clone converter %s at %p into stackBuffer %p",
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                    ucnv_getName(cnv, status), cnv, stackBuffer);
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (cnv->sharedData->impl->safeClone != NULL) {
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the custom safeClone function for sizing */
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bufferSizeNeeded = 0;
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->sharedData->impl->safeClone(cnv, NULL, &bufferSizeNeeded, status);
20259d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_FAILURE(*status)) {
20359d709d503bab6e2b61931737e662dd293b40578ccornelius            UTRACE_EXIT_STATUS(*status);
20459d709d503bab6e2b61931737e662dd293b40578ccornelius            return NULL;
20559d709d503bab6e2b61931737e662dd293b40578ccornelius        }
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* inherent sizing */
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bufferSizeNeeded = sizeof(UConverter);
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (pBufferSize == NULL) {
21459d709d503bab6e2b61931737e662dd293b40578ccornelius        stackBufferSize = 1;
21559d709d503bab6e2b61931737e662dd293b40578ccornelius        pBufferSize = &stackBufferSize;
21659d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
21759d709d503bab6e2b61931737e662dd293b40578ccornelius        stackBufferSize = *pBufferSize;
21859d709d503bab6e2b61931737e662dd293b40578ccornelius        if (stackBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
21959d709d503bab6e2b61931737e662dd293b40578ccornelius            *pBufferSize = bufferSizeNeeded;
22059d709d503bab6e2b61931737e662dd293b40578ccornelius            UTRACE_EXIT_VALUE(bufferSizeNeeded);
22159d709d503bab6e2b61931737e662dd293b40578ccornelius            return NULL;
22259d709d503bab6e2b61931737e662dd293b40578ccornelius        }
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Pointers on 64-bit platforms need to be aligned
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * on a 64-bit boundary in memory.
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
23159d709d503bab6e2b61931737e662dd293b40578ccornelius        if(stackBufferSize > offsetUp) {
23259d709d503bab6e2b61931737e662dd293b40578ccornelius            stackBufferSize -= offsetUp;
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            stackBufferChars += offsetUp;
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
23659d709d503bab6e2b61931737e662dd293b40578ccornelius            stackBufferSize = 1;
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    stackBuffer = (void *)stackBufferChars;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Now, see if we must allocate any memory */
24359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL)
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* allocate one here...*/
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter = allocatedConverter = (UConverter *) uprv_malloc (bufferSizeNeeded);
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(localConverter == NULL) {
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UTRACE_EXIT_STATUS(*status);
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
25359d709d503bab6e2b61931737e662dd293b40578ccornelius        *status = U_SAFECLONE_ALLOCATED_WARNING;
25459d709d503bab6e2b61931737e662dd293b40578ccornelius
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* record the fact that memory was allocated */
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pBufferSize = bufferSizeNeeded;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* just use the stack buffer */
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter = (UConverter*) stackBuffer;
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        allocatedConverter = NULL;
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(localConverter, 0, bufferSizeNeeded);
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Copy initial state */
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy(localConverter, cnv, sizeof(UConverter));
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    localConverter->isCopyLocal = localConverter->isExtraLocal = FALSE;
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* copy the substitution string */
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (cnv->subChars == (uint8_t *)cnv->subUChars) {
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter->subChars = (uint8_t *)localConverter->subUChars;
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (localConverter->subChars == NULL) {
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(allocatedConverter);
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UTRACE_EXIT_STATUS(*status);
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(localConverter->subChars, cnv->subChars, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* now either call the safeclone fcn or not */
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (cnv->sharedData->impl->safeClone != NULL) {
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the custom safeClone function */
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter = cnv->sharedData->impl->safeClone(cnv, localConverter, pBufferSize, status);
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(localConverter==NULL || U_FAILURE(*status)) {
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (allocatedConverter != NULL && allocatedConverter->subChars != (uint8_t *)allocatedConverter->subUChars) {
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(allocatedConverter->subChars);
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(allocatedConverter);
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*status);
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* increment refcount of shared data if needed */
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Checking whether it's an algorithic converter is okay
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    in multithreaded applications because the value never changes.
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Don't check referenceCounter for any other value.
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (cnv->sharedData->referenceCounter != ~0) {
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_incrementRefCount(cnv->sharedData);
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(localConverter == (UConverter*)stackBuffer) {
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* we're using user provided data - set to not destroy */
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverter->isCopyLocal = TRUE;
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* allow callback functions to handle any memory allocation */
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.converter = fromUArgs.converter = localConverter;
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cbErr = U_ZERO_ERROR;
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv->fromCharErrorBehaviour(cnv->toUContext, &toUArgs, NULL, 0, UCNV_CLONE, &cbErr);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cbErr = U_ZERO_ERROR;
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv->fromUCharErrorBehaviour(cnv->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLONE, &cbErr);
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(localConverter, *status);
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return localConverter;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Decreases the reference counter in the shared immutable section of the object
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *and frees the mutable part*/
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_close (UConverter * converter)
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_CLOSE);
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter == NULL)
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT();
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA3(UTRACE_OPEN_CLOSE, "close converter %s at %p, isCopyLocal=%b",
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_getName(converter, &errorCode), converter, converter->isCopyLocal);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* In order to speed up the close, only call the callbacks when they have been changed.
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    This performance check will only work when the callbacks are set within a shared library
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    or from user code that statically links this code. */
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* first, notify the callback functions that the converter is closed */
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK) {
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverterToUnicodeArgs toUArgs = {
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sizeof(UConverterToUnicodeArgs),
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                TRUE,
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        };
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        toUArgs.converter = converter;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorCode = U_ZERO_ERROR;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_CLOSE, &errorCode);
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK) {
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverterFromUnicodeArgs fromUArgs = {
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sizeof(UConverterFromUnicodeArgs),
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                TRUE,
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        };
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fromUArgs.converter = converter;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorCode = U_ZERO_ERROR;
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLOSE, &errorCode);
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->sharedData->impl->close != NULL) {
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->sharedData->impl->close(converter);
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->subChars != (uint8_t *)converter->subUChars) {
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(converter->subChars);
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Checking whether it's an algorithic converter is okay
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    in multithreaded applications because the value never changes.
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Don't check referenceCounter for any other value.
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->sharedData->referenceCounter != ~0) {
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_unloadSharedDataIfReady(converter->sharedData);
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!converter->isCopyLocal){
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(converter);
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT();
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*returns a single Name from the list, will return NULL if out of bounds
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char*   U_EXPORT2
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getAvailableName (int32_t n)
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (0 <= n && n <= 0xffff) {
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode err = U_ZERO_ERROR;
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *name = ucnv_bld_getAvailableConverter((uint16_t)n, &err);
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(err)) {
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return name;
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t   U_EXPORT2
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_countAvailable ()
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ucnv_bld_countAvailableConverters(&err);
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void    U_EXPORT2
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getSubstChars (const UConverter * converter,
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    char *mySubChar,
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    int8_t * len,
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    UErrorCode * err)
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->subCharLen <= 0) {
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Unicode string or empty string from ucnv_setSubstString(). */
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *len = 0;
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (*len < converter->subCharLen) /*not enough space in subChars */
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_INDEX_OUTOFBOUNDS_ERROR;
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy (mySubChar, converter->subChars, converter->subCharLen);   /*fills in the subchars */
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *len = converter->subCharLen; /*store # of bytes copied to buffer */
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void    U_EXPORT2
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setSubstChars (UConverter * converter,
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    const char *mySubChar,
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    int8_t len,
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    UErrorCode * err)
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Makes sure that the subChar is within the codepages char length boundaries */
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if ((len > converter->sharedData->staticData->maxBytesPerChar)
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     || (len < converter->sharedData->staticData->minBytesPerChar))
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy (converter->subChars, mySubChar, len); /*copies the subchars */
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->subCharLen = len;  /*sets the new len */
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * There is currently (2001Feb) no separate API to set/get subChar1.
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * In order to always have subChar written after it is explicitly set,
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * we set subChar1 to 0.
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->subChar1 = 0;
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setSubstString(UConverter *cnv,
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    const UChar *s,
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    int32_t length,
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    UErrorCode *err) {
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char chars[UCNV_ERROR_BUFFER_LENGTH];
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *clone;
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t *subChars;
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t cloneSize, length8;
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Let the following functions check all arguments. */
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cloneSize = sizeof(cloneBuffer);
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    clone = ucnv_safeClone(cnv, cloneBuffer, &cloneSize, err);
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_setFromUCallBack(clone, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, err);
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    length8 = ucnv_fromUChars(clone, chars, (int32_t)sizeof(chars), s, length, err);
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_close(clone);
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (cnv->sharedData->impl->writeSub == NULL
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        || (cnv->sharedData->staticData->conversionType == UCNV_MBCS &&
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         ucnv_MBCSGetType(cnv) != UCNV_EBCDIC_STATEFUL)
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The converter is not stateful. Store the charset bytes as a fixed string. */
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        subChars = (uint8_t *)chars;
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * The converter has a non-default writeSub() function, indicating
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * that it is stateful.
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Store the Unicode string for on-the-fly conversion for correct
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * state handling.
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length > UCNV_ERROR_BUFFER_LENGTH) {
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * Should not occur. The converter should output at least one byte
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * per UChar, which means that ucnv_fromUChars() should catch all
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * overflows.
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_BUFFER_OVERFLOW_ERROR;
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        subChars = (uint8_t *)s;
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (length < 0) {
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            length = u_strlen(s);
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length8 = length * U_SIZEOF_UCHAR;
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * For storing the substitution string, select either the small buffer inside
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * UConverter or allocate a subChars buffer.
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (length8 > UCNV_MAX_SUBCHAR_LEN) {
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Use a separate buffer for the string. Outside UConverter to not make it too large. */
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (cnv->subChars == (uint8_t *)cnv->subUChars) {
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Allocate a new buffer for the string. */
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (cnv->subChars == NULL) {
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cnv->subChars = (uint8_t *)cnv->subUChars;
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *err = U_MEMORY_ALLOCATION_ERROR;
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memset(cnv->subChars, 0, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Copy the substitution string into the UConverter or its subChars buffer. */
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (length8 == 0) {
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->subCharLen = 0;
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(cnv->subChars, subChars, length8);
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (subChars == (uint8_t *)chars) {
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->subCharLen = (int8_t)length8;
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else /* subChars == s */ {
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->subCharLen = (int8_t)-length;
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* See comment in ucnv_setSubstChars(). */
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv->subChar1 = 0;
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*resets the internal states of a converter
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *goal : have the same behaviour than a freshly created converter
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void _reset(UConverter *converter, UConverterResetChoice choice,
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UBool callCallback) {
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(converter == NULL) {
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(callCallback) {
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* first, notify the callback functions that the converter is reset */
57985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UErrorCode errorCode;
58085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
58185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(choice<=UCNV_RESET_TO_UNICODE && converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK) {
58285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UConverterToUnicodeArgs toUArgs = {
58385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sizeof(UConverterToUnicodeArgs),
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                TRUE,
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL
59185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            };
59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            toUArgs.converter = converter;
59385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errorCode = U_ZERO_ERROR;
59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_RESET, &errorCode);
59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
59685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(choice!=UCNV_RESET_TO_UNICODE && converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK) {
59785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UConverterFromUnicodeArgs fromUArgs = {
59885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                sizeof(UConverterFromUnicodeArgs),
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                TRUE,
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL
60685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            };
60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fromUArgs.converter = converter;
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errorCode = U_ZERO_ERROR;
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_RESET, &errorCode);
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* now reset the converter itself */
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(choice<=UCNV_RESET_TO_UNICODE) {
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->toUnicodeStatus = converter->sharedData->toUnicodeStatus;
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->mode = 0;
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->toULength = 0;
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->invalidCharLength = converter->UCharErrorBufferLength = 0;
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->preToULength = 0;
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(choice!=UCNV_RESET_TO_UNICODE) {
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->fromUnicodeStatus = 0;
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->fromUChar32 = 0;
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->invalidUCharLength = converter->charErrorBufferLength = 0;
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->preFromUFirstCP = U_SENTINEL;
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->preFromULength = 0;
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converter->sharedData->impl->reset != NULL) {
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the custom reset function */
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converter->sharedData->impl->reset(converter, choice);
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_reset(UConverter *converter)
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _reset(converter, UCNV_RESET_BOTH, TRUE);
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_resetToUnicode(UConverter *converter)
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _reset(converter, UCNV_RESET_TO_UNICODE, TRUE);
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_resetFromUnicode(UConverter *converter)
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _reset(converter, UCNV_RESET_FROM_UNICODE, TRUE);
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int8_t   U_EXPORT2
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getMaxCharSize (const UConverter * converter)
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return converter->maxBytesPerUChar;
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int8_t   U_EXPORT2
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getMinCharSize (const UConverter * converter)
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return converter->sharedData->staticData->minBytesPerChar;
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char*   U_EXPORT2
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getName (const UConverter * converter, UErrorCode * err)
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(converter->sharedData->impl->getName){
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char* temp= converter->sharedData->impl->getName(converter);
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(temp)
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return temp;
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return converter->sharedData->staticData->name;
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getCCSID(const UConverter * converter,
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UErrorCode * err)
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t ccsid;
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -1;
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ccsid = converter->sharedData->staticData->codepage;
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ccsid == 0) {
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Rare case. This is for cases like gb18030,
6918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        which doesn't have an IBM canonical name, but does have an IBM alias. */
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *standardName = ucnv_getStandardName(ucnv_getName(converter, err), "IBM", err);
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(*err) && standardName) {
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const char *ccsidStr = uprv_strchr(standardName, '-');
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ccsidStr) {
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ccsid = (int32_t)atol(ccsidStr+1);  /* +1 to skip '-' */
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ccsid;
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UConverterPlatform   U_EXPORT2
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getPlatform (const UConverter * converter,
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                      UErrorCode * err)
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return UCNV_UNKNOWN;
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (UConverterPlatform)converter->sharedData->staticData->platform;
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_getToUCallBack (const UConverter * converter,
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UConverterToUCallback *action,
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const void **context)
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *action = converter->fromCharErrorBehaviour;
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *context = converter->toUContext;
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_getFromUCallBack (const UConverter * converter,
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UConverterFromUCallback *action,
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const void **context)
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *action = converter->fromUCharErrorBehaviour;
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *context = converter->fromUContext;
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void    U_EXPORT2
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setToUCallBack (UConverter * converter,
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UConverterToUCallback newAction,
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const void* newContext,
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UConverterToUCallback *oldAction,
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const void** oldContext,
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode * err)
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (oldAction) *oldAction = converter->fromCharErrorBehaviour;
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->fromCharErrorBehaviour = newAction;
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (oldContext) *oldContext = converter->toUContext;
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->toUContext = newContext;
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void  U_EXPORT2
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setFromUCallBack (UConverter * converter,
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UConverterFromUCallback newAction,
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const void* newContext,
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UConverterFromUCallback *oldAction,
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const void** oldContext,
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode * err)
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err))
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (oldAction) *oldAction = converter->fromUCharErrorBehaviour;
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->fromUCharErrorBehaviour = newAction;
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (oldContext) *oldContext = converter->fromUContext;
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    converter->fromUContext = newContext;
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru_updateOffsets(int32_t *offsets, int32_t length,
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               int32_t sourceIndex, int32_t errorInputLength) {
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *limit;
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t delta, offset;
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sourceIndex>=0) {
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * adjust each offset by adding the previous sourceIndex
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * minus the length of the input sequence that caused an
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * error, if any
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delta=sourceIndex-errorInputLength;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * set each offset to -1 because this conversion function
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * does not handle offsets
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delta=-1;
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    limit=offsets+length;
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(delta==0) {
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* most common case, nothing to do */
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(delta>0) {
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* add the delta to each offset (but not if the offset is <0) */
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while(offsets<limit) {
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            offset=*offsets;
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(offset>=0) {
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *offsets=offset+delta;
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++offsets;
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else /* delta<0 */ {
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * set each offset to -1 because this conversion function
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * does not handle offsets
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * or the error input sequence started in a previous buffer
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while(offsets<limit) {
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *offsets++=-1;
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_fromUnicode --------------------------------------------------------- */
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Implementation note for m:n conversions
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * While collecting source units to find the longest match for m:n conversion,
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * some source units may need to be stored for a partial match.
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * When a second buffer does not yield a match on all of the previously stored
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * source units, then they must be "replayed", i.e., fed back into the converter.
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The code relies on the fact that replaying will not nest -
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * converting a replay buffer will not result in a replay.
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This is because a replay is necessary only after the _continuation_ of a
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * partial match failed, but a replay buffer is converted as a whole.
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It may result in some of its units being stored again for a partial match,
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * but there will not be a continuation _during_ the replay which could fail.
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It is conceivable that a callback function could call the converter
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * recursively in a way that causes another replay to be stored, but that
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * would be an error in the callback function.
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Such violations will cause assertion failures in a debug build,
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and wrong output, but they will not cause a crash.
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru_fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) {
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterFromUnicode fromUnicode;
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *cnv;
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *s;
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *t;
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *offsets;
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t sourceIndex;
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t errorInputLength;
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool converterSawEndOfInput, calledCallback;
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* variables for m:n conversion */
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar replay[UCNV_EXT_MAX_UCHARS];
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *realSource, *realSourceLimit;
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t realSourceIndex;
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool realFlush;
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv=pArgs->converter;
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=pArgs->source;
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=pArgs->target;
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    offsets=pArgs->offsets;
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the converter implementation function */
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sourceIndex=0;
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(offsets==NULL) {
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fromUnicode=cnv->sharedData->impl->fromUnicode;
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fromUnicode=cnv->sharedData->impl->fromUnicodeWithOffsets;
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(fromUnicode==NULL) {
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is no WithOffsets implementation */
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUnicode=cnv->sharedData->impl->fromUnicode;
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* we will write -1 for each offset */
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceIndex=-1;
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv->preFromULength>=0) {
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* normal mode */
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSource=NULL;
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceLimit=NULL;
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realFlush=FALSE;
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceIndex=0;
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Previous m:n conversion stored source units from a partial match
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * and failed to consume all of them.
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * We need to "replay" them from a temporary buffer and convert them first.
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSource=pArgs->source;
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceLimit=pArgs->sourceLimit;
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realFlush=pArgs->flush;
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceIndex=sourceIndex;
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR);
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->source=replay;
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->sourceLimit=replay-cnv->preFromULength;
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->flush=FALSE;
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceIndex=-1;
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->preFromULength=0;
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * loop for conversion and error handling
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * loop {
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   convert
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   loop {
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     update offsets
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     handle end of input
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     handle errors/call callback
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   }
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * }
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(;;) {
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(*err)) {
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* convert */
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUnicode(pArgs, err);
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * set a flag for whether the converter
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * successfully processed the end of the input
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * need not check cnv->preFromULength==0 because a replay (<0) will cause
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * s<sourceLimit before converterSawEndOfInput is checked
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converterSawEndOfInput=
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (UBool)(U_SUCCESS(*err) &&
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->flush && pArgs->source==pArgs->sourceLimit &&
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cnv->fromUChar32==0);
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* handle error from ucnv_convertEx() */
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converterSawEndOfInput=FALSE;
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no callback called yet for this iteration */
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        calledCallback=FALSE;
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no sourceIndex adjustment for conversion, only for callback output */
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorInputLength=0;
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * loop for offsets and error handling
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * iterates at most 3 times:
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 1. to clean up after the conversion function
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 2. after the callback
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 3. after the callback again if there was truncated input
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;;) {
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* update offsets if we write any */
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(offsets!=NULL) {
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t length=(int32_t)(pArgs->target-t);
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(length>0) {
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    _updateOffsets(offsets, length, sourceIndex, errorInputLength);
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * if a converter handles offsets and updates the offsets
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * pointer at the end, then pArgs->offset should not change
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * here;
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * however, some converters do not handle offsets at all
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (sourceIndex<0) or may not update the offsets pointer
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->offsets=offsets+=length;
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(sourceIndex>=0) {
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceIndex+=(int32_t)(pArgs->source-s);
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(cnv->preFromULength<0) {
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * switch the source to new replay units (cannot occur while replaying)
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * after offset handling and before end-of-input and callback handling
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(realSource==NULL) {
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSource=pArgs->source;
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSourceLimit=pArgs->sourceLimit;
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realFlush=pArgs->flush;
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSourceIndex=sourceIndex;
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR);
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->source=replay;
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->sourceLimit=replay-cnv->preFromULength;
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->flush=FALSE;
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if((sourceIndex+=cnv->preFromULength)<0) {
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        sourceIndex=-1;
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cnv->preFromULength=0;
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* see implementation note before _fromUnicodeWithCallback() */
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    U_ASSERT(realSource==NULL);
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_INTERNAL_PROGRAM_ERROR;
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* update pointers */
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            s=pArgs->source;
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            t=pArgs->target;
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_SUCCESS(*err)) {
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(s<pArgs->sourceLimit) {
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * continue with the conversion loop while there is still input left
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (continue converting by breaking out of only the inner loop)
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(realSource!=NULL) {
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* switch back from replaying to the real source and continue */
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->source=realSource;
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->sourceLimit=realSourceLimit;
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->flush=realFlush;
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceIndex=realSourceIndex;
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSource=NULL;
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(pArgs->flush && cnv->fromUChar32!=0) {
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the entire input stream is consumed
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * and there is a partial, truncated input sequence left
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* inject an error and continue with callback handling */
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_TRUNCATED_CHAR_FOUND;
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    calledCallback=FALSE; /* new error condition */
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* input consumed */
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(pArgs->flush) {
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /*
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * return to the conversion loop once more if the flush
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * flag is set and the conversion function has not
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * successfully processed the end of the input yet
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         *
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * (continue converting by breaking out of only the inner loop)
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         */
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if(!converterSawEndOfInput) {
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /* reset the converter without calling the callback function */
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        _reset(cnv, UCNV_RESET_FROM_UNICODE, FALSE);
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* done successfully */
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* U_FAILURE(*err) */
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UErrorCode e;
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if( calledCallback ||
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (e!=U_INVALID_CHAR_FOUND &&
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_ILLEGAL_CHAR_FOUND &&
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_TRUNCATED_CHAR_FOUND)
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ) {
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the callback did not or cannot resolve the error:
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * set output pointers and return
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the check for buffer overflow is redundant but it is
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * a high-runner case and hopefully documents the intent
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * well
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * if we were replaying, then the replay buffer must be
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * copied back into the UConverter
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * and the real arguments must be restored
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(realSource!=NULL) {
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t length;
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        U_ASSERT(cnv->preFromULength==0);
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        length=(int32_t)(pArgs->sourceLimit-pArgs->source);
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if(length>0) {
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            uprv_memcpy(cnv->preFromU, pArgs->source, length*U_SIZEOF_UCHAR);
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            cnv->preFromULength=(int8_t)-length;
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->source=realSource;
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->sourceLimit=realSourceLimit;
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->flush=realFlush;
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* callback handling */
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UChar32 codePoint;
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* get and write the code point */
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                codePoint=cnv->fromUChar32;
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorInputLength=0;
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                U16_APPEND_UNSAFE(cnv->invalidUCharBuffer, errorInputLength, codePoint);
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cnv->invalidUCharLength=(int8_t)errorInputLength;
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* set the converter state to deal with the next character */
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cnv->fromUChar32=0;
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* call the callback function */
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cnv->fromUCharErrorBehaviour(cnv->fromUContext, pArgs,
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cnv->invalidUCharBuffer, errorInputLength, codePoint,
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err==U_INVALID_CHAR_FOUND ? UCNV_UNASSIGNED : UCNV_ILLEGAL,
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    err);
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * loop back to the offset handling
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * this flag will indicate after offset handling
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * that a callback was called;
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * if the callback did not resolve the error, then we return
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            calledCallback=TRUE;
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Output the fromUnicode overflow buffer.
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Call this function if(cnv->charErrorBufferLength>0).
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return TRUE if overflow
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_outputOverflowFromUnicode(UConverter *cnv,
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               char **target, const char *targetLimit,
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               int32_t **pOffsets,
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               UErrorCode *err) {
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *offsets;
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *overflow, *t;
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, length;
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=*target;
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pOffsets!=NULL) {
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        offsets=*pOffsets;
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        offsets=NULL;
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    overflow=(char *)cnv->charErrorBuffer;
1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    length=cnv->charErrorBufferLength;
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    i=0;
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while(i<length) {
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(t==targetLimit) {
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* the overflow buffer contains too much, keep the rest */
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=0;
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do {
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                overflow[j++]=overflow[i++];
1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } while(i<length);
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->charErrorBufferLength=(int8_t)j;
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *target=t;
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(offsets!=NULL) {
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pOffsets=offsets;
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err=U_BUFFER_OVERFLOW_ERROR;
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy the overflow contents to the target */
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *t++=overflow[i++];
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(offsets!=NULL) {
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *offsets++=-1; /* no source index available for old output */
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* the overflow buffer is completely copied to the target */
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv->charErrorBufferLength=0;
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *target=t;
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(offsets!=NULL) {
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pOffsets=offsets;
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_fromUnicode(UConverter *cnv,
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 char **target, const char *targetLimit,
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 const UChar **source, const UChar *sourceLimit,
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 int32_t *offsets,
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 UBool flush,
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 UErrorCode *err) {
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterFromUnicodeArgs args;
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *s;
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *t;
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check parameters */
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv==NULL || target==NULL || source==NULL) {
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=*source;
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=*target;
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if ((const void *)U_MAX_PTR(sourceLimit) == (const void *)sourceLimit) {
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Prevent code from going into an infinite loop in case we do hit this
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        limit. The limit pointer is expected to be on a UChar * boundary.
1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        This also prevents the next argument check from failing.
1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        */
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit = (const UChar *)(((const char *)sourceLimit) - 1);
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * All these conditions should never happen.
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 1) Make sure that the limits are >= to the address source or target
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 2) Make sure that the buffer sizes do not exceed the number range for
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * int32_t because some functions use the size (in units or bytes)
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * rather than comparing pointers, and because offsets are int32_t values.
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * size_t is guaranteed to be unsigned and large enough for the job.
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Return with an error instead of adjusting the limits because we would
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * not be able to maintain the semantics that either the source must be
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * consumed or the target filled (unless an error occurs).
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * An adjustment would be targetLimit=t+0x7fffffff; for example.
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * to a char * pointer and provide an incomplete UChar code unit.
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (sourceLimit<s || targetLimit<t ||
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ((size_t)(sourceLimit-s)>(size_t)0x3fffffff && sourceLimit>s) ||
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t) ||
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (((const char *)sourceLimit-(const char *)s) & 1) != 0)
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* output the target overflow buffer */
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( cnv->charErrorBufferLength>0 &&
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_outputOverflowFromUnicode(cnv, target, targetLimit, &offsets, err)
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* U_BUFFER_OVERFLOW_ERROR */
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* *target may have moved, therefore stop using t */
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!flush && s==sourceLimit && cnv->preFromULength>=0) {
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* the overflow buffer is emptied and there is no new input: we are done */
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Do not simply return with a buffer overflow error if
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * !flush && t==targetLimit
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * because it is possible that the source will not generate any output.
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * For example, the skip callback may be called;
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * it does not output anything.
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* prepare the converter arguments */
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.converter=cnv;
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.flush=flush;
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.offsets=offsets;
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.source=s;
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.sourceLimit=sourceLimit;
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.target=*target;
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.targetLimit=targetLimit;
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.size=sizeof(args);
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _fromUnicodeWithCallback(&args, err);
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *source=args.source;
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *target=args.target;
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_toUnicode() --------------------------------------------------------- */
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru_toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUnicode toUnicode;
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *cnv;
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *s;
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *t;
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *offsets;
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t sourceIndex;
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t errorInputLength;
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool converterSawEndOfInput, calledCallback;
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* variables for m:n conversion */
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char replay[UCNV_EXT_MAX_BYTES];
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *realSource, *realSourceLimit;
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t realSourceIndex;
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool realFlush;
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv=pArgs->converter;
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=pArgs->source;
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=pArgs->target;
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    offsets=pArgs->offsets;
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the converter implementation function */
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sourceIndex=0;
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(offsets==NULL) {
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        toUnicode=cnv->sharedData->impl->toUnicode;
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        toUnicode=cnv->sharedData->impl->toUnicodeWithOffsets;
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(toUnicode==NULL) {
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is no WithOffsets implementation */
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            toUnicode=cnv->sharedData->impl->toUnicode;
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* we will write -1 for each offset */
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceIndex=-1;
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv->preToULength>=0) {
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* normal mode */
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSource=NULL;
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceLimit=NULL;
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realFlush=FALSE;
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceIndex=0;
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Previous m:n conversion stored source units from a partial match
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * and failed to consume all of them.
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * We need to "replay" them from a temporary buffer and convert them first.
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSource=pArgs->source;
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceLimit=pArgs->sourceLimit;
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realFlush=pArgs->flush;
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        realSourceIndex=sourceIndex;
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(replay, cnv->preToU, -cnv->preToULength);
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->source=replay;
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->sourceLimit=replay-cnv->preToULength;
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pArgs->flush=FALSE;
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceIndex=-1;
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->preToULength=0;
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * loop for conversion and error handling
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * loop {
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   convert
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   loop {
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     update offsets
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     handle end of input
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *     handle errors/call callback
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   }
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * }
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(;;) {
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(*err)) {
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* convert */
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            toUnicode(pArgs, err);
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * set a flag for whether the converter
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * successfully processed the end of the input
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * need not check cnv->preToULength==0 because a replay (<0) will cause
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * s<sourceLimit before converterSawEndOfInput is checked
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converterSawEndOfInput=
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (UBool)(U_SUCCESS(*err) &&
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->flush && pArgs->source==pArgs->sourceLimit &&
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cnv->toULength==0);
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* handle error from getNextUChar() or ucnv_convertEx() */
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converterSawEndOfInput=FALSE;
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no callback called yet for this iteration */
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        calledCallback=FALSE;
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no sourceIndex adjustment for conversion, only for callback output */
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorInputLength=0;
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * loop for offsets and error handling
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * iterates at most 3 times:
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 1. to clean up after the conversion function
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 2. after the callback
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * 3. after the callback again if there was truncated input
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;;) {
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* update offsets if we write any */
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(offsets!=NULL) {
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t length=(int32_t)(pArgs->target-t);
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(length>0) {
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    _updateOffsets(offsets, length, sourceIndex, errorInputLength);
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * if a converter handles offsets and updates the offsets
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * pointer at the end, then pArgs->offset should not change
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * here;
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * however, some converters do not handle offsets at all
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (sourceIndex<0) or may not update the offsets pointer
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->offsets=offsets+=length;
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(sourceIndex>=0) {
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceIndex+=(int32_t)(pArgs->source-s);
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(cnv->preToULength<0) {
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * switch the source to new replay units (cannot occur while replaying)
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * after offset handling and before end-of-input and callback handling
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(realSource==NULL) {
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSource=pArgs->source;
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSourceLimit=pArgs->sourceLimit;
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realFlush=pArgs->flush;
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSourceIndex=sourceIndex;
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    uprv_memcpy(replay, cnv->preToU, -cnv->preToULength);
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->source=replay;
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->sourceLimit=replay-cnv->preToULength;
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->flush=FALSE;
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if((sourceIndex+=cnv->preToULength)<0) {
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        sourceIndex=-1;
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cnv->preToULength=0;
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* see implementation note before _fromUnicodeWithCallback() */
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    U_ASSERT(realSource==NULL);
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_INTERNAL_PROGRAM_ERROR;
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* update pointers */
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            s=pArgs->source;
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            t=pArgs->target;
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_SUCCESS(*err)) {
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(s<pArgs->sourceLimit) {
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * continue with the conversion loop while there is still input left
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (continue converting by breaking out of only the inner loop)
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(realSource!=NULL) {
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* switch back from replaying to the real source and continue */
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->source=realSource;
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->sourceLimit=realSourceLimit;
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pArgs->flush=realFlush;
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceIndex=realSourceIndex;
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    realSource=NULL;
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(pArgs->flush && cnv->toULength>0) {
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the entire input stream is consumed
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * and there is a partial, truncated input sequence left
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* inject an error and continue with callback handling */
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_TRUNCATED_CHAR_FOUND;
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    calledCallback=FALSE; /* new error condition */
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* input consumed */
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(pArgs->flush) {
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /*
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * return to the conversion loop once more if the flush
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * flag is set and the conversion function has not
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * successfully processed the end of the input yet
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         *
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         * (continue converting by breaking out of only the inner loop)
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         */
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if(!converterSawEndOfInput) {
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /* reset the converter without calling the callback function */
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE);
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* done successfully */
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* U_FAILURE(*err) */
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UErrorCode e;
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if( calledCallback ||
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (e!=U_INVALID_CHAR_FOUND &&
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_ILLEGAL_CHAR_FOUND &&
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_TRUNCATED_CHAR_FOUND &&
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_ILLEGAL_ESCAPE_SEQUENCE &&
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     e!=U_UNSUPPORTED_ESCAPE_SEQUENCE)
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ) {
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the callback did not or cannot resolve the error:
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * set output pointers and return
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * the check for buffer overflow is redundant but it is
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * a high-runner case and hopefully documents the intent
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * well
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * if we were replaying, then the replay buffer must be
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * copied back into the UConverter
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * and the real arguments must be restored
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(realSource!=NULL) {
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t length;
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        U_ASSERT(cnv->preToULength==0);
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        length=(int32_t)(pArgs->sourceLimit-pArgs->source);
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if(length>0) {
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            uprv_memcpy(cnv->preToU, pArgs->source, length);
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            cnv->preToULength=(int8_t)-length;
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->source=realSource;
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->sourceLimit=realSourceLimit;
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        pArgs->flush=realFlush;
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* copy toUBytes[] to invalidCharBuffer[] */
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errorInputLength=cnv->invalidCharLength=cnv->toULength;
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(errorInputLength>0) {
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_memcpy(cnv->invalidCharBuffer, cnv->toUBytes, errorInputLength);
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* set the converter state to deal with the next character */
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->toULength=0;
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* call the callback function */
154485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(cnv->toUCallbackReason==UCNV_ILLEGAL && *err==U_INVALID_CHAR_FOUND) {
154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cnv->toUCallbackReason = UCNV_UNASSIGNED;
154685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs,
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cnv->invalidCharBuffer, errorInputLength,
154985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                cnv->toUCallbackReason,
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                err);
155185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            cnv->toUCallbackReason = UCNV_ILLEGAL; /* reset to default value */
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * loop back to the offset handling
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * this flag will indicate after offset handling
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * that a callback was called;
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * if the callback did not resolve the error, then we return
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            calledCallback=TRUE;
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Output the toUnicode overflow buffer.
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Call this function if(cnv->UCharErrorBufferLength>0).
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return TRUE if overflow
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_outputOverflowToUnicode(UConverter *cnv,
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UChar **target, const UChar *targetLimit,
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             int32_t **pOffsets,
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode *err) {
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *offsets;
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *overflow, *t;
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, length;
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=*target;
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pOffsets!=NULL) {
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        offsets=*pOffsets;
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        offsets=NULL;
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    overflow=cnv->UCharErrorBuffer;
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    length=cnv->UCharErrorBufferLength;
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    i=0;
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while(i<length) {
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(t==targetLimit) {
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* the overflow buffer contains too much, keep the rest */
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t j=0;
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do {
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                overflow[j++]=overflow[i++];
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } while(i<length);
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->UCharErrorBufferLength=(int8_t)j;
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *target=t;
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(offsets!=NULL) {
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pOffsets=offsets;
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err=U_BUFFER_OVERFLOW_ERROR;
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy the overflow contents to the target */
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *t++=overflow[i++];
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(offsets!=NULL) {
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *offsets++=-1; /* no source index available for old output */
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* the overflow buffer is completely copied to the target */
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv->UCharErrorBufferLength=0;
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *target=t;
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(offsets!=NULL) {
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pOffsets=offsets;
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_toUnicode(UConverter *cnv,
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UChar **target, const UChar *targetLimit,
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               const char **source, const char *sourceLimit,
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               int32_t *offsets,
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UBool flush,
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UErrorCode *err) {
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUnicodeArgs args;
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *s;
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *t;
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check parameters */
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv==NULL || target==NULL || source==NULL) {
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=*source;
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=*target;
1646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if ((const void *)U_MAX_PTR(targetLimit) == (const void *)targetLimit) {
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Prevent code from going into an infinite loop in case we do hit this
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        limit. The limit pointer is expected to be on a UChar * boundary.
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        This also prevents the next argument check from failing.
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        */
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit = (const UChar *)(((const char *)targetLimit) - 1);
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * All these conditions should never happen.
1658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 1) Make sure that the limits are >= to the address source or target
1660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 2) Make sure that the buffer sizes do not exceed the number range for
1662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * int32_t because some functions use the size (in units or bytes)
1663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * rather than comparing pointers, and because offsets are int32_t values.
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * size_t is guaranteed to be unsigned and large enough for the job.
1666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Return with an error instead of adjusting the limits because we would
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * not be able to maintain the semantics that either the source must be
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * consumed or the target filled (unless an error occurs).
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * An adjustment would be sourceLimit=t+0x7fffffff; for example.
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * to a char * pointer and provide an incomplete UChar code unit.
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (sourceLimit<s || targetLimit<t ||
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s) ||
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ((size_t)(targetLimit-t)>(size_t)0x3fffffff && targetLimit>t) ||
1678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (((const char *)targetLimit-(const char *)t) & 1) != 0
1679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
1680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* output the target overflow buffer */
1685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( cnv->UCharErrorBufferLength>0 &&
1686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_outputOverflowToUnicode(cnv, target, targetLimit, &offsets, err)
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* U_BUFFER_OVERFLOW_ERROR */
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* *target may have moved, therefore stop using t */
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!flush && s==sourceLimit && cnv->preToULength>=0) {
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* the overflow buffer is emptied and there is no new input: we are done */
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Do not simply return with a buffer overflow error if
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * !flush && t==targetLimit
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * because it is possible that the source will not generate any output.
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * For example, the skip callback may be called;
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * it does not output anything.
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* prepare the converter arguments */
1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.converter=cnv;
1708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.flush=flush;
1709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.offsets=offsets;
1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.source=s;
1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.sourceLimit=sourceLimit;
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.target=*target;
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.targetLimit=targetLimit;
1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.size=sizeof(args);
1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _toUnicodeWithCallback(&args, err);
1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *source=args.source;
1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *target=args.target;
1720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_to/fromUChars() ----------------------------------------------------- */
1723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_fromUChars(UConverter *cnv,
1726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                char *dest, int32_t destCapacity,
1727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const UChar *src, int32_t srcLength,
1728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UErrorCode *pErrorCode) {
1729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *srcLimit;
1730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *originalDest, *destLimit;
1731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t destLength;
1732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check arguments */
1734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( cnv==NULL ||
1739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destCapacity<0 || (destCapacity>0 && dest==NULL) ||
1740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLength<-1 || (srcLength!=0 && src==NULL)
1741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
1742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* initialize */
1747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_resetFromUnicode(cnv);
1748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    originalDest=dest;
1749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(srcLength==-1) {
1750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLength=u_strlen(src);
1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(srcLength>0) {
1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLimit=src+srcLength;
1754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLimit=dest+destCapacity;
1755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
1757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
1758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            destLimit=(char *)U_MAX_PTR(dest);
1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* perform the conversion */
1762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
1763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLength=(int32_t)(dest-originalDest);
1764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if an overflow occurs, then get the preflighting length */
1766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            char buffer[1024];
1768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            destLimit=buffer+sizeof(buffer);
1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do {
1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                dest=buffer;
1772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
1773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
1774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                destLength+=(int32_t)(dest-buffer);
1775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLength=0;
1779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return u_terminateChars(originalDest, destCapacity, destLength, pErrorCode);
1782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_toUChars(UConverter *cnv,
1786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UChar *dest, int32_t destCapacity,
1787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              const char *src, int32_t srcLength,
1788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UErrorCode *pErrorCode) {
1789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *srcLimit;
1790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *originalDest, *destLimit;
1791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t destLength;
1792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check arguments */
1794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( cnv==NULL ||
1799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destCapacity<0 || (destCapacity>0 && dest==NULL) ||
1800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLength<-1 || (srcLength!=0 && src==NULL))
1801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* initialize */
1807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_resetToUnicode(cnv);
1808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    originalDest=dest;
1809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(srcLength==-1) {
1810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLength=(int32_t)uprv_strlen(src);
1811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(srcLength>0) {
1813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLimit=src+srcLength;
1814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLimit=dest+destCapacity;
1815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
1817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
1818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            destLimit=(UChar *)U_MAX_PTR(dest);
1819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* perform the conversion */
1822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
1823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLength=(int32_t)(dest-originalDest);
1824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if an overflow occurs, then get the preflighting length */
1826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR)
1827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar buffer[1024];
1829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            destLimit=buffer+sizeof(buffer)/U_SIZEOF_UCHAR;
1831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do {
1832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                dest=buffer;
1833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
1834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
1835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                destLength+=(int32_t)(dest-buffer);
1836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        destLength=0;
1841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return u_terminateUChars(originalDest, destCapacity, destLength, pErrorCode);
1844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_getNextUChar() ------------------------------------------------------ */
1847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2
1849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getNextUChar(UConverter *cnv,
1850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                  const char **source, const char *sourceLimit,
1851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                  UErrorCode *err) {
1852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUnicodeArgs args;
1853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar buffer[U16_MAX_LENGTH];
1854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *s;
1855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar32 c;
1856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, length;
1857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check parameters */
1859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(err==NULL || U_FAILURE(*err)) {
1860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0xffff;
1861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv==NULL || source==NULL) {
1864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0xffff;
1866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=*source;
1869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sourceLimit<s) {
1870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0xffff;
1872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Make sure that the buffer sizes do not exceed the number range for
1876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * int32_t because some functions use the size (in units or bytes)
1877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * rather than comparing pointers, and because offsets are int32_t values.
1878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * size_t is guaranteed to be unsigned and large enough for the job.
1880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Return with an error instead of adjusting the limits because we would
1882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * not be able to maintain the semantics that either the source must be
1883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * consumed or the target filled (unless an error occurs).
1884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * An adjustment would be sourceLimit=t+0x7fffffff; for example.
1885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) {
1887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_ILLEGAL_ARGUMENT_ERROR;
1888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0xffff;
1889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    c=U_SENTINEL;
1892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* flush the target overflow buffer */
1894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnv->UCharErrorBufferLength>0) {
1895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar *overflow;
1896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        overflow=cnv->UCharErrorBuffer;
1898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i=0;
1899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length=cnv->UCharErrorBufferLength;
1900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        U16_NEXT(overflow, i, length, c);
1901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* move the remaining overflow contents up to the beginning */
1903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((cnv->UCharErrorBufferLength=(int8_t)(length-i))>0) {
1904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+i,
1905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR);
1906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(!U16_IS_LEAD(c) || i<length) {
1909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return c;
1910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Continue if the overflow buffer contained only a lead surrogate,
1913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * in case the converter outputs single surrogates from complete
1914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * input sequences.
1915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * flush==TRUE is implied for ucnv_getNextUChar()
1920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
1921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * do not simply return even if s==sourceLimit because the converter may
1922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * not have seen flush==TRUE before
1923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* prepare the converter arguments */
1926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.converter=cnv;
1927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.flush=TRUE;
1928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.offsets=NULL;
1929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.source=s;
1930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.sourceLimit=sourceLimit;
1931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.target=buffer;
1932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.targetLimit=buffer+1;
1933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    args.size=sizeof(args);
1934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(c<0) {
1936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * call the native getNextUChar() implementation if we are
1938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * at a character boundary (toULength==0)
1939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
1940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * unlike with _toUnicode(), getNextUChar() implementations must set
1941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * U_TRUNCATED_CHAR_FOUND for truncated input,
1942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * in addition to setting toULength/toUBytes[]
1943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(cnv->toULength==0 && cnv->sharedData->impl->getNextUChar!=NULL) {
1945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c=cnv->sharedData->impl->getNextUChar(&args, err);
1946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *source=s=args.source;
1947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*err==U_INDEX_OUTOFBOUNDS_ERROR) {
1948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* reset the converter without calling the callback function */
1949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE);
1950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0xffff; /* no output */
1951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(U_SUCCESS(*err) && c>=0) {
1952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return c;
1953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
1954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * else fall through to use _toUnicode() because
1955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *   UCNV_GET_NEXT_UCHAR_USE_TO_U: the native function did not want to handle it after all
1956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *   U_FAILURE: call _toUnicode() for callback handling (do not output c)
1957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
1958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* convert to one UChar in buffer[0], or handle getNextUChar() errors */
1962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        _toUnicodeWithCallback(&args, err);
1963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*err==U_BUFFER_OVERFLOW_ERROR) {
1965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err=U_ZERO_ERROR;
1966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i=0;
1969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length=(int32_t)(args.target-buffer);
1970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* write the lead surrogate from the overflow buffer */
1972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buffer[0]=(UChar)c;
1973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        args.target=buffer+1;
1974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i=0;
1975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length=1;
1976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* buffer contents starts at i and ends before length */
1979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
1981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        c=0xffff; /* no output */
1982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(length==0) {
1983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no input or only state changes */
1984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err=U_INDEX_OUTOFBOUNDS_ERROR;
1985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* no need to reset explicitly because _toUnicodeWithCallback() did it */
1986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        c=0xffff; /* no output */
1987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        c=buffer[0];
1989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        i=1;
1990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(!U16_IS_LEAD(c)) {
1991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* consume c=buffer[0], done */
1992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* got a lead surrogate, see if a trail surrogate follows */
1994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar c2;
1995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(cnv->UCharErrorBufferLength>0) {
1997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* got overflow output from the conversion */
1998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U16_IS_TRAIL(c2=cnv->UCharErrorBuffer[0])) {
1999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* got a trail surrogate, too */
2000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    c=U16_GET_SUPPLEMENTARY(c, c2);
2001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* move the remaining overflow contents up to the beginning */
2003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if((--cnv->UCharErrorBufferLength)>0) {
2004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+1,
2005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR);
2006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
2007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
2008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* c is an unpaired lead surrogate, just return it */
2009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
2010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(args.source<sourceLimit) {
2011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* convert once more, to buffer[1] */
2012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                args.targetLimit=buffer+2;
2013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                _toUnicodeWithCallback(&args, err);
2014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*err==U_BUFFER_OVERFLOW_ERROR) {
2015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_ZERO_ERROR;
2016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
2017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=(int32_t)(args.target-buffer);
2019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_SUCCESS(*err) && length==2 && U16_IS_TRAIL(c2=buffer[1])) {
2020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* got a trail surrogate, too */
2021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    c=U16_GET_SUPPLEMENTARY(c, c2);
2022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    i=2;
2023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
2024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * move leftover output from buffer[i..length[
2030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * into the beginning of the overflow buffer
2031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(i<length) {
2033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* move further overflow back */
2034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t delta=length-i;
2035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((length=cnv->UCharErrorBufferLength)>0) {
2036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memmove(cnv->UCharErrorBuffer+delta, cnv->UCharErrorBuffer,
2037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         length*U_SIZEOF_UCHAR);
2038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->UCharErrorBufferLength=(int8_t)(length+delta);
2040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv->UCharErrorBuffer[0]=buffer[i++];
2042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(delta>1) {
2043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv->UCharErrorBuffer[1]=buffer[i];
2044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *source=args.source;
2048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return c;
2049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_convert() and siblings ---------------------------------------------- */
2052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
2054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_convertEx(UConverter *targetCnv, UConverter *sourceCnv,
2055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               char **target, const char *targetLimit,
2056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               const char **source, const char *sourceLimit,
2057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UChar *pivotStart, UChar **pivotSource,
2058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UChar **pivotTarget, const UChar *pivotLimit,
2059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UBool reset, UBool flush,
2060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               UErrorCode *pErrorCode) {
2061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar pivotBuffer[CHUNK_SIZE];
2062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *myPivotSource;
2063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *myPivotTarget;
2064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *s;
2065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *t;
2066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUnicodeArgs toUArgs;
2068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterFromUnicodeArgs fromUArgs;
2069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterConvert convert;
2070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* error checking */
2072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
2073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
2074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( targetCnv==NULL || sourceCnv==NULL ||
2077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source==NULL || *source==NULL ||
2078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        target==NULL || *target==NULL || targetLimit==NULL
2079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
2080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
2082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=*source;
2085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    t=*target;
2086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if((sourceLimit!=NULL && sourceLimit<s) || targetLimit<t) {
2087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
2089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Make sure that the buffer sizes do not exceed the number range for
2093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * int32_t. See ucnv_toUnicode() for a more detailed comment.
2094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(
2096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (sourceLimit!=NULL && ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) ||
2097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t)
2098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
2099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
2101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pivotStart==NULL) {
2104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(!flush) {
2105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* streaming conversion requires an explicit pivot buffer */
2106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
2108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* use the stack pivot buffer */
2111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        myPivotSource=myPivotTarget=pivotStart=pivotBuffer;
2112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotSource=(UChar **)&myPivotSource;
2113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotTarget=&myPivotTarget;
2114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotLimit=pivotBuffer+CHUNK_SIZE;
2115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(  pivotStart>=pivotLimit ||
2116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pivotSource==NULL || *pivotSource==NULL ||
2117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pivotTarget==NULL || *pivotTarget==NULL ||
2118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pivotLimit==NULL
2119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
2120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
2122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sourceLimit==NULL) {
2125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* get limit of single-byte-NUL-terminated source string */
2126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=uprv_strchr(*source, 0);
2127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(reset) {
2130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_resetToUnicode(sourceCnv);
2131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_resetFromUnicode(targetCnv);
2132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pivotSource=*pivotTarget=pivotStart;
2133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(targetCnv->charErrorBufferLength>0) {
2134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* output the targetCnv overflow buffer */
2135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(ucnv_outputOverflowFromUnicode(targetCnv, target, targetLimit, NULL, pErrorCode)) {
2136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* U_BUFFER_OVERFLOW_ERROR */
2137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
2138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* *target has moved, therefore stop using t */
2140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( !flush &&
2142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetCnv->preFromULength>=0 && *pivotSource==*pivotTarget &&
2143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceCnv->UCharErrorBufferLength==0 && sourceCnv->preToULength>=0 && s==sourceLimit
2144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
2145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* the fromUnicode overflow buffer is emptied and there is no new input: we are done */
2146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
2147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Is direct-UTF-8 conversion available? */
2151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( sourceCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
2152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetCnv->sharedData->impl->fromUTF8!=NULL
2153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
2154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        convert=targetCnv->sharedData->impl->fromUTF8;
2155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if( targetCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
2156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               sourceCnv->sharedData->impl->toUTF8!=NULL
2157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ) {
2158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        convert=sourceCnv->sharedData->impl->toUTF8;
2159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
2160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        convert=NULL;
2161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If direct-UTF-8 conversion is available, then we use a smaller
2165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * pivot buffer for error handling and partial matches
2166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * so that we quickly return to direct conversion.
2167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * 32 is large enough for UCNV_EXT_MAX_UCHARS and UCNV_ERROR_BUFFER_LENGTH.
2169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * We could reduce the pivot buffer size further, at the cost of
2171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * buffer overflows from callbacks.
2172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * The pivot buffer should not be smaller than the maximum number of
2173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * fromUnicode extension table input UChars
2174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * (for m:n conversion, see
2175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * targetCnv->sharedData->mbcs.extIndexes[UCNV_EXT_COUNT_UCHARS])
2176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * or 2 for surrogate pairs.
2177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Too small a buffer can cause thrashing between pivoting and direct
2179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * conversion, with function call overhead outweighing the benefits
2180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * of direct conversion.
2181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(convert!=NULL && (pivotLimit-pivotStart)>32) {
2183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotLimit=pivotStart+32;
2184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* prepare the converter arguments */
2187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.converter=targetCnv;
2188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.flush=FALSE;
2189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.offsets=NULL;
2190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.target=*target;
2191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.targetLimit=targetLimit;
2192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fromUArgs.size=sizeof(fromUArgs);
2193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.converter=sourceCnv;
2195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.flush=flush;
2196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.offsets=NULL;
2197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.source=s;
2198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.sourceLimit=sourceLimit;
2199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.targetLimit=pivotLimit;
2200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toUArgs.size=sizeof(toUArgs);
2201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * TODO: Consider separating this function into two functions,
2204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * extracting exactly the conversion loop,
2205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * for readability and to reduce the set of visible variables.
2206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * Otherwise stop using s and t from here on.
2208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    s=t=NULL;
2210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * conversion loop
2213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * The sequence of steps in the loop may appear backward,
2215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * but the principle is simple:
2216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * In the chain of
2217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   source - sourceCnv overflow - pivot - targetCnv overflow - target
2218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * empty out later buffers before refilling them from earlier ones.
2219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
2220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * The targetCnv overflow buffer is flushed out only once before the loop.
2221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(;;) {
2223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * if(pivot not empty or error or replay or flush fromUnicode) {
2225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *   fromUnicode(pivot -> target);
2226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * }
2227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
2228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * For pivoting conversion; and for direct conversion for
2229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * error callback handling and flushing the replay buffer.
2230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( *pivotSource<*pivotTarget ||
2232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            U_FAILURE(*pErrorCode) ||
2233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetCnv->preFromULength<0 ||
2234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUArgs.flush
2235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
2236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUArgs.source=*pivotSource;
2237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUArgs.sourceLimit=*pivotTarget;
2238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            _fromUnicodeWithCallback(&fromUArgs, pErrorCode);
2239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_FAILURE(*pErrorCode)) {
2240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* target overflow, or conversion error */
2241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pivotSource=(UChar *)fromUArgs.source;
2242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
2243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
2246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * _fromUnicodeWithCallback() must have consumed the pivot contents
2247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * (*pivotSource==*pivotTarget) since it returned with U_SUCCESS()
2248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
2249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The pivot buffer is empty; reset it so we start at pivotStart. */
2252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pivotSource=*pivotTarget=pivotStart;
2253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * if(sourceCnv overflow buffer not empty) {
2256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *     move(sourceCnv overflow buffer -> pivot);
2257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *     continue;
2258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * }
2259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* output the sourceCnv overflow buffer */
2261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(sourceCnv->UCharErrorBufferLength>0) {
2262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(ucnv_outputOverflowToUnicode(sourceCnv, pivotTarget, pivotLimit, NULL, pErrorCode)) {
2263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* U_BUFFER_OVERFLOW_ERROR */
2264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
2265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
2267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * check for end of input and break if done
2271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
2272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Checking both flush and fromUArgs.flush ensures that the converters
2273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * have been called with the flush flag set if the ucnv_convertEx()
2274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * caller set it.
2275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( toUArgs.source==sourceLimit &&
2277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceCnv->preToULength>=0 && sourceCnv->toULength==0 &&
2278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (!flush || fromUArgs.flush)
2279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
2280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* done successfully */
2281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
2282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * use direct conversion if available
2286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * but not if continuing a partial match
2287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * or flushing the toUnicode replay buffer
2288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(convert!=NULL && targetCnv->preFromUFirstCP<0 && sourceCnv->preToULength==0) {
2290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*pErrorCode==U_USING_DEFAULT_WARNING) {
2291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* remove a warning that may be set by this function */
2292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
2293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            convert(&fromUArgs, &toUArgs, pErrorCode);
2295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
2296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
2297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(U_FAILURE(*pErrorCode)) {
2298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(sourceCnv->toULength>0) {
2299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
2300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * Fall through to calling _toUnicodeWithCallback()
2301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * for callback handling.
2302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *
2303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * The pivot buffer will be reset with
2304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     *   *pivotSource=*pivotTarget=pivotStart;
2305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * which indicates a toUnicode error to the caller
2306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (*pivotSource==pivotStart shows no pivot UChars consumed).
2307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
2308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
2309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
2310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * Indicate a fromUnicode error to the caller
2311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * (*pivotSource>pivotStart shows some pivot UChars consumed).
2312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
2313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pivotSource=*pivotTarget=pivotStart+1;
2314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /*
2315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * Loop around to calling _fromUnicodeWithCallbacks()
2316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     * for callback handling.
2317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     */
2318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
2319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
2320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(*pErrorCode==U_USING_DEFAULT_WARNING) {
2321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
2322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * No error, but the implementation requested to temporarily
2323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * fall back to pivoting.
2324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
2325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
2326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
2327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * The following else branches are almost identical to the end-of-input
2328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * handling in _toUnicodeWithCallback().
2329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * Avoid calling it just for the end of input.
2330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
2331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(flush && sourceCnv->toULength>0) { /* flush==toUArgs.flush */
2332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
2333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * the entire input stream is consumed
2334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * and there is a partial, truncated input sequence left
2335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
2336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* inject an error and continue with callback handling */
2338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_TRUNCATED_CHAR_FOUND;
2339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
2340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* input consumed */
2341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(flush) {
2342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* reset the converters without calling the callback functions */
2343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    _reset(sourceCnv, UCNV_RESET_TO_UNICODE, FALSE);
2344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    _reset(targetCnv, UCNV_RESET_FROM_UNICODE, FALSE);
2345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
2346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* done successfully */
2348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
2349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * toUnicode(source -> pivot);
2354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
2355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * For pivoting conversion; and for direct conversion for
2356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * error callback handling, continuing partial matches
2357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * and flushing the replay buffer.
2358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
2359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * The pivot buffer is empty and reset.
2360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        toUArgs.target=pivotStart; /* ==*pivotTarget */
2362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* toUArgs.targetLimit=pivotLimit; already set before the loop */
2363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        _toUnicodeWithCallback(&toUArgs, pErrorCode);
2364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pivotTarget=toUArgs.target;
2365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
2366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* pivot overflow: continue with the conversion loop */
2367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_ZERO_ERROR;
2368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(U_FAILURE(*pErrorCode) || (!flush && *pivotTarget==pivotStart)) {
2369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* conversion error, or there was nothing left to convert */
2370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
2371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
2373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * else:
2374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * _toUnicodeWithCallback() wrote into the pivot buffer,
2375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * continue with fromUnicode conversion.
2376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *
2377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * Set the fromUnicode flush flag if we flush and if toUnicode has
2378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * processed the end of the input.
2379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
2380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( flush && toUArgs.source==sourceLimit &&
2381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceCnv->preToULength>=0 &&
2382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceCnv->UCharErrorBufferLength==0
2383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
2384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fromUArgs.flush=TRUE;
2385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * The conversion loop is exited when one of the following is true:
2390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * - the entire source text has been converted successfully to the target buffer
2391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * - a target buffer overflow occurred
2392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * - a conversion error occurred
2393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *source=toUArgs.source;
2396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *target=fromUArgs.target;
2397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* terminate the target buffer if possible */
2399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(flush && U_SUCCESS(*pErrorCode)) {
2400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*target!=targetLimit) {
2401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            **target=0;
2402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
2403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
2404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
2405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
2406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_STRING_NOT_TERMINATED_WARNING;
2407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
2408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
2410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* internal implementation of ucnv_convert() etc. with preflighting */
2412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
2413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_internalConvert(UConverter *outConverter, UConverter *inConverter,
2414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     char *target, int32_t targetCapacity,
2415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     const char *source, int32_t sourceLength,
2416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UErrorCode *pErrorCode) {
2417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar pivotBuffer[CHUNK_SIZE];
2418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *pivot, *pivot2;
2419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *myTarget;
2421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *sourceLimit;
2422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *targetLimit;
2423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t targetLength=0;
2424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set up */
2426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sourceLength<0) {
2427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=uprv_strchr(source, 0);
2428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
2429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=source+sourceLength;
2430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* if there is no input data, we're done */
2433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(source==sourceLimit) {
2434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return u_terminateChars(target, targetCapacity, 0, pErrorCode);
2435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pivot=pivot2=pivotBuffer;
2438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myTarget=target;
2439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    targetLength=0;
2440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(targetCapacity>0) {
2442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* perform real conversion */
2443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=target+targetCapacity;
2444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_convertEx(outConverter, inConverter,
2445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       &myTarget, targetLimit,
2446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       &source, sourceLimit,
2447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE,
2448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       FALSE,
2449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       TRUE,
2450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       pErrorCode);
2451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLength=(int32_t)(myTarget-target);
2452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
2453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
2455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If the output buffer is exhausted (or we are only "preflighting"), we need to stop writing
2456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * to it but continue the conversion in order to store in targetCapacity
2457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * the number of bytes that was required.
2458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
2459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR || targetCapacity==0)
2460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
2461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char targetBuffer[CHUNK_SIZE];
2462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=targetBuffer+CHUNK_SIZE;
2464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        do {
2465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_ZERO_ERROR;
2466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            myTarget=targetBuffer;
2467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_convertEx(outConverter, inConverter,
2468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &myTarget, targetLimit,
2469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &source, sourceLimit,
2470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE,
2471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           FALSE,
2472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           TRUE,
2473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           pErrorCode);
2474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetLength+=(int32_t)(myTarget-