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