16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 1998-2013, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*  ucnv.c:
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*  Implements APIs for the ICU's codeset conversion library;
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*  mostly calls through internal functions;
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*  created by Bertrand A. Damiba
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Modification History:
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Date        Name        Description
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   04/04/99    helena      Fixed internal header inclusion.
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   05/09/00    helena      Added implementation to handle fallback mappings.
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   06/20/2000  helena      OS/400 port changes; mostly typecast.
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_CONVERSION
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ucnv.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ucnv_err.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uset.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf.h"
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "putilimp.h"
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "utracimp.h"
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ustr_imp.h"
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_imp.h"
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_cnv.h"
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucnv_bld.h"
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* size of intermediate and preflighting buffers in ucnv_convert() */
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define CHUNK_SIZE 1024
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct UAmbiguousConverter {
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *name;
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar variant5c;
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} UAmbiguousConverter;
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UAmbiguousConverter ambiguousConverters[]={
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-897_P100-1995", 0xa5 },
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-942_P120-1999", 0xa5 },
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-943_P130-1999", 0xa5 },
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-946_P100-1995", 0xa5 },
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-33722_P120-1999", 0xa5 },
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-1041_P100-1995", 0xa5 },
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*{ "ibm-54191_P100-2006", 0xa5 },*/
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*{ "ibm-62383_P100-2007", 0xa5 },*/
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*{ "ibm-891_P100-1995", 0x20a9 },*/
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-944_P100-1995", 0x20a9 },
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-949_P110-1999", 0x20a9 },
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-1363_P110-1997", 0x20a9 },
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ISO_2022,locale=ko,version=0", 0x20a9 },
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "ibm-1088_P100-1995", 0x20a9 }
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*Calls through createConverter */
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverter* U_EXPORT2
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_open (const char *name,
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       UErrorCode * err)
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverter *r;
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (err == NULL || U_FAILURE (*err)) {
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    r =  ucnv_createConverter(NULL, name, err);
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return r;
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverter* U_EXPORT2
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_openPackage   (const char *packageName, const char *converterName, UErrorCode * err)
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ucnv_createConverterFromPackage(packageName, converterName,  err);
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*Extracts the UChar* to a char* and calls through createConverter */
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverter*   U_EXPORT2
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_openU (const UChar * name,
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode * err)
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char asciiName[UCNV_MAX_CONVERTER_NAME_LENGTH];
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (err == NULL || U_FAILURE(*err))
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (name == NULL)
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return ucnv_open (NULL, err);
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (u_strlen(name) >= UCNV_MAX_CONVERTER_NAME_LENGTH)
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err = U_ILLEGAL_ARGUMENT_ERROR;
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ucnv_open(u_austrcpy(asciiName, name), err);
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* Copy the string that is represented by the UConverterPlatform enum
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param platformString An output buffer
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @param platform An enum representing a platform
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return the length of the copied string.
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_copyPlatformString(char *platformString, UConverterPlatform pltfrm)
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch (pltfrm)
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCNV_IBM:
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_strcpy(platformString, "ibm-");
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 4;
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCNV_UNKNOWN:
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* default to empty string */
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *platformString = 0;
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0;
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *through createConverter*/
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverter*   U_EXPORT2
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_openCCSID (int32_t codepage,
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UConverterPlatform platform,
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode * err)
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char myName[UCNV_MAX_CONVERTER_NAME_LENGTH];
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t myNameLen;
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (err == NULL || U_FAILURE (*err))
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* ucnv_copyPlatformString could return "ibm-" or "cp" */
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    myNameLen = ucnv_copyPlatformString(myName, platform);
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    T_CString_integerToString(myName + myNameLen, codepage, 10);
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ucnv_createConverter(NULL, myName, err);
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* Creating a temporary stack-based object that can be used in one thread,
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.organd created from a converter that is shared across threads.
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverter* U_EXPORT2
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status)
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverter *localConverter, *allocatedConverter;
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t stackBufferSize;
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t bufferSizeNeeded;
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *stackBufferChars = (char *)stackBuffer;
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode cbErr;
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterToUnicodeArgs toUArgs = {
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sizeof(UConverterToUnicodeArgs),
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            TRUE,
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    };
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterFromUnicodeArgs fromUArgs = {
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sizeof(UConverterFromUnicodeArgs),
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            TRUE,
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL,
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NULL
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    };
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_ENTRY_OC(UTRACE_UCNV_CLONE);
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (status == NULL || U_FAILURE(*status)){
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UTRACE_EXIT_STATUS(status? *status: U_ILLEGAL_ARGUMENT_ERROR);
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv == NULL) {
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *status = U_ILLEGAL_ARGUMENT_ERROR;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UTRACE_EXIT_STATUS(*status);
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_DATA3(UTRACE_OPEN_CLOSE, "clone converter %s at %p into stackBuffer %p",
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    ucnv_getName(cnv, status), cnv, stackBuffer);
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv->sharedData->impl->safeClone != NULL) {
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* call the custom safeClone function for sizing */
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bufferSizeNeeded = 0;
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->sharedData->impl->safeClone(cnv, NULL, &bufferSizeNeeded, status);
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_FAILURE(*status)) {
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UTRACE_EXIT_STATUS(*status);
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    else
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* inherent sizing */
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bufferSizeNeeded = sizeof(UConverter);
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (pBufferSize == NULL) {
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        stackBufferSize = 1;
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pBufferSize = &stackBufferSize;
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        stackBufferSize = *pBufferSize;
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (stackBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pBufferSize = bufferSizeNeeded;
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UTRACE_EXIT_VALUE(bufferSizeNeeded);
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Pointers on 64-bit platforms need to be aligned
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * on a 64-bit boundary in memory.
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(stackBufferSize > offsetUp) {
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stackBufferSize -= offsetUp;
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stackBufferChars += offsetUp;
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stackBufferSize = 1;
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stackBuffer = (void *)stackBufferChars;
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Now, see if we must allocate any memory */
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL)
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* allocate one here...*/
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter = allocatedConverter = (UConverter *) uprv_malloc (bufferSizeNeeded);
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(localConverter == NULL) {
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *status = U_MEMORY_ALLOCATION_ERROR;
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UTRACE_EXIT_STATUS(*status);
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *status = U_SAFECLONE_ALLOCATED_WARNING;
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* record the fact that memory was allocated */
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pBufferSize = bufferSizeNeeded;
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* just use the stack buffer */
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter = (UConverter*) stackBuffer;
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        allocatedConverter = NULL;
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(localConverter, 0, bufferSizeNeeded);
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Copy initial state */
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memcpy(localConverter, cnv, sizeof(UConverter));
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    localConverter->isCopyLocal = localConverter->isExtraLocal = FALSE;
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* copy the substitution string */
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv->subChars == (uint8_t *)cnv->subUChars) {
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter->subChars = (uint8_t *)localConverter->subUChars;
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (localConverter->subChars == NULL) {
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(allocatedConverter);
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UTRACE_EXIT_STATUS(*status);
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(localConverter->subChars, cnv->subChars, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* now either call the safeclone fcn or not */
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv->sharedData->impl->safeClone != NULL) {
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* call the custom safeClone function */
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter = cnv->sharedData->impl->safeClone(cnv, localConverter, pBufferSize, status);
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(localConverter==NULL || U_FAILURE(*status)) {
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (allocatedConverter != NULL && allocatedConverter->subChars != (uint8_t *)allocatedConverter->subUChars) {
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(allocatedConverter->subChars);
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(allocatedConverter);
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UTRACE_EXIT_STATUS(*status);
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* increment refcount of shared data if needed */
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Checking whether it's an algorithic converter is okay
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    in multithreaded applications because the value never changes.
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Don't check referenceCounter for any other value.
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    */
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv->sharedData->referenceCounter != ~0) {
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_incrementRefCount(cnv->sharedData);
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(localConverter == (UConverter*)stackBuffer) {
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* we're using user provided data - set to not destroy */
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localConverter->isCopyLocal = TRUE;
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* allow callback functions to handle any memory allocation */
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.converter = fromUArgs.converter = localConverter;
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cbErr = U_ZERO_ERROR;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv->fromCharErrorBehaviour(cnv->toUContext, &toUArgs, NULL, 0, UCNV_CLONE, &cbErr);
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cbErr = U_ZERO_ERROR;
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv->fromUCharErrorBehaviour(cnv->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLONE, &cbErr);
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_EXIT_PTR_STATUS(localConverter, *status);
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return localConverter;
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*Decreases the reference counter in the shared immutable section of the object
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *and frees the mutable part*/
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void  U_EXPORT2
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_close (UConverter * converter)
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode = U_ZERO_ERROR;
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_ENTRY_OC(UTRACE_UCNV_CLOSE);
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter == NULL)
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UTRACE_EXIT();
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_DATA3(UTRACE_OPEN_CLOSE, "close converter %s at %p, isCopyLocal=%b",
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_getName(converter, &errorCode), converter, converter->isCopyLocal);
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* In order to speed up the close, only call the callbacks when they have been changed.
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    This performance check will only work when the callbacks are set within a shared library
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    or from user code that statically links this code. */
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* first, notify the callback functions that the converter is closed */
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK) {
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UConverterToUnicodeArgs toUArgs = {
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sizeof(UConverterToUnicodeArgs),
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                TRUE,
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        };
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUArgs.converter = converter;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode = U_ZERO_ERROR;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_CLOSE, &errorCode);
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK) {
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UConverterFromUnicodeArgs fromUArgs = {
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sizeof(UConverterFromUnicodeArgs),
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                TRUE,
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        };
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fromUArgs.converter = converter;
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode = U_ZERO_ERROR;
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLOSE, &errorCode);
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->sharedData->impl->close != NULL) {
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->sharedData->impl->close(converter);
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->subChars != (uint8_t *)converter->subUChars) {
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(converter->subChars);
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Checking whether it's an algorithic converter is okay
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    in multithreaded applications because the value never changes.
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Don't check referenceCounter for any other value.
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    */
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->sharedData->referenceCounter != ~0) {
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_unloadSharedDataIfReady(converter->sharedData);
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!converter->isCopyLocal){
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(converter);
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UTRACE_EXIT();
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*returns a single Name from the list, will return NULL if out of bounds
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const char*   U_EXPORT2
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getAvailableName (int32_t n)
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (0 <= n && n <= 0xffff) {
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode err = U_ZERO_ERROR;
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *name = ucnv_bld_getAvailableConverter((uint16_t)n, &err);
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(err)) {
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return name;
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t   U_EXPORT2
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_countAvailable ()
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode err = U_ZERO_ERROR;
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ucnv_bld_countAvailableConverters(&err);
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void    U_EXPORT2
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getSubstChars (const UConverter * converter,
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    char *mySubChar,
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int8_t * len,
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    UErrorCode * err)
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->subCharLen <= 0) {
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* Unicode string or empty string from ucnv_setSubstString(). */
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *len = 0;
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (*len < converter->subCharLen) /*not enough space in subChars */
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err = U_INDEX_OUTOFBOUNDS_ERROR;
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memcpy (mySubChar, converter->subChars, converter->subCharLen);   /*fills in the subchars */
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *len = converter->subCharLen; /*store # of bytes copied to buffer */
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void    U_EXPORT2
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_setSubstChars (UConverter * converter,
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    const char *mySubChar,
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int8_t len,
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    UErrorCode * err)
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*Makes sure that the subChar is within the codepages char length boundaries */
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if ((len > converter->sharedData->staticData->maxBytesPerChar)
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     || (len < converter->sharedData->staticData->minBytesPerChar))
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err = U_ILLEGAL_ARGUMENT_ERROR;
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memcpy (converter->subChars, mySubChar, len); /*copies the subchars */
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->subCharLen = len;  /*sets the new len */
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * There is currently (2001Feb) no separate API to set/get subChar1.
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * In order to always have subChar written after it is explicitly set,
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * we set subChar1 to 0.
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    */
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->subChar1 = 0;
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return;
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_setSubstString(UConverter *cnv,
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    const UChar *s,
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t length,
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    UErrorCode *err) {
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char chars[UCNV_ERROR_BUFFER_LENGTH];
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverter *clone;
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t *subChars;
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t cloneSize, length8;
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Let the following functions check all arguments. */
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cloneSize = sizeof(cloneBuffer);
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    clone = ucnv_safeClone(cnv, cloneBuffer, &cloneSize, err);
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_setFromUCallBack(clone, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, err);
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length8 = ucnv_fromUChars(clone, chars, (int32_t)sizeof(chars), s, length, err);
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_close(clone);
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(*err)) {
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cnv->sharedData->impl->writeSub == NULL
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_LEGACY_CONVERSION
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        || (cnv->sharedData->staticData->conversionType == UCNV_MBCS &&
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         ucnv_MBCSGetType(cnv) != UCNV_EBCDIC_STATEFUL)
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* The converter is not stateful. Store the charset bytes as a fixed string. */
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        subChars = (uint8_t *)chars;
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * The converter has a non-default writeSub() function, indicating
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * that it is stateful.
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Store the Unicode string for on-the-fly conversion for correct
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * state handling.
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (length > UCNV_ERROR_BUFFER_LENGTH) {
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * Should not occur. The converter should output at least one byte
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * per UChar, which means that ucnv_fromUChars() should catch all
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * overflows.
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *err = U_BUFFER_OVERFLOW_ERROR;
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        subChars = (uint8_t *)s;
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (length < 0) {
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length = u_strlen(s);
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length8 = length * U_SIZEOF_UCHAR;
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * For storing the substitution string, select either the small buffer inside
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * UConverter or allocate a subChars buffer.
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (length8 > UCNV_MAX_SUBCHAR_LEN) {
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* Use a separate buffer for the string. Outside UConverter to not make it too large. */
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (cnv->subChars == (uint8_t *)cnv->subUChars) {
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* Allocate a new buffer for the string. */
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (cnv->subChars == NULL) {
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->subChars = (uint8_t *)cnv->subUChars;
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *err = U_MEMORY_ALLOCATION_ERROR;
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memset(cnv->subChars, 0, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Copy the substitution string into the UConverter or its subChars buffer. */
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (length8 == 0) {
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->subCharLen = 0;
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(cnv->subChars, subChars, length8);
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (subChars == (uint8_t *)chars) {
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->subCharLen = (int8_t)length8;
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else /* subChars == s */ {
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->subCharLen = (int8_t)-length;
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* See comment in ucnv_setSubstChars(). */
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv->subChar1 = 0;
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*resets the internal states of a converter
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *goal : have the same behaviour than a freshly created converter
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void _reset(UConverter *converter, UConverterResetChoice choice,
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   UBool callCallback) {
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(converter == NULL) {
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(callCallback) {
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* first, notify the callback functions that the converter is reset */
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode errorCode;
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(choice<=UCNV_RESET_TO_UNICODE && converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK) {
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UConverterToUnicodeArgs toUArgs = {
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                sizeof(UConverterToUnicodeArgs),
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                TRUE,
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            };
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUArgs.converter = converter;
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode = U_ZERO_ERROR;
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_RESET, &errorCode);
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(choice!=UCNV_RESET_TO_UNICODE && converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK) {
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UConverterFromUnicodeArgs fromUArgs = {
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                sizeof(UConverterFromUnicodeArgs),
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                TRUE,
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL,
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                NULL
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            };
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUArgs.converter = converter;
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode = U_ZERO_ERROR;
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_RESET, &errorCode);
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* now reset the converter itself */
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(choice<=UCNV_RESET_TO_UNICODE) {
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->toUnicodeStatus = converter->sharedData->toUnicodeStatus;
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->mode = 0;
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->toULength = 0;
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->invalidCharLength = converter->UCharErrorBufferLength = 0;
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->preToULength = 0;
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(choice!=UCNV_RESET_TO_UNICODE) {
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->fromUnicodeStatus = 0;
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->fromUChar32 = 0;
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->invalidUCharLength = converter->charErrorBufferLength = 0;
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->preFromUFirstCP = U_SENTINEL;
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->preFromULength = 0;
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (converter->sharedData->impl->reset != NULL) {
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* call the custom reset function */
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        converter->sharedData->impl->reset(converter, choice);
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void  U_EXPORT2
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_reset(UConverter *converter)
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _reset(converter, UCNV_RESET_BOTH, TRUE);
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void  U_EXPORT2
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_resetToUnicode(UConverter *converter)
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _reset(converter, UCNV_RESET_TO_UNICODE, TRUE);
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void  U_EXPORT2
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_resetFromUnicode(UConverter *converter)
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _reset(converter, UCNV_RESET_FROM_UNICODE, TRUE);
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int8_t   U_EXPORT2
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getMaxCharSize (const UConverter * converter)
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return converter->maxBytesPerUChar;
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int8_t   U_EXPORT2
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getMinCharSize (const UConverter * converter)
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return converter->sharedData->staticData->minBytesPerChar;
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const char*   U_EXPORT2
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getName (const UConverter * converter, UErrorCode * err)
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(converter->sharedData->impl->getName){
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char* temp= converter->sharedData->impl->getName(converter);
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(temp)
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return temp;
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return converter->sharedData->staticData->name;
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getCCSID(const UConverter * converter,
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UErrorCode * err)
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t ccsid;
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return -1;
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ccsid = converter->sharedData->staticData->codepage;
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ccsid == 0) {
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* Rare case. This is for cases like gb18030,
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        which doesn't have an IBM canonical name, but does have an IBM alias. */
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *standardName = ucnv_getStandardName(ucnv_getName(converter, err), "IBM", err);
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(*err) && standardName) {
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const char *ccsidStr = uprv_strchr(standardName, '-');
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ccsidStr) {
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ccsid = (int32_t)atol(ccsidStr+1);  /* +1 to skip '-' */
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ccsid;
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UConverterPlatform   U_EXPORT2
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getPlatform (const UConverter * converter,
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                      UErrorCode * err)
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UCNV_UNKNOWN;
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UConverterPlatform)converter->sharedData->staticData->platform;
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_getToUCallBack (const UConverter * converter,
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UConverterToUCallback *action,
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         const void **context)
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *action = converter->fromCharErrorBehaviour;
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *context = converter->toUContext;
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_getFromUCallBack (const UConverter * converter,
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           UConverterFromUCallback *action,
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           const void **context)
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *action = converter->fromUCharErrorBehaviour;
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *context = converter->fromUContext;
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void    U_EXPORT2
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_setToUCallBack (UConverter * converter,
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UConverterToUCallback newAction,
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const void* newContext,
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UConverterToUCallback *oldAction,
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const void** oldContext,
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UErrorCode * err)
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (oldAction) *oldAction = converter->fromCharErrorBehaviour;
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->fromCharErrorBehaviour = newAction;
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (oldContext) *oldContext = converter->toUContext;
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->toUContext = newContext;
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void  U_EXPORT2
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_setFromUCallBack (UConverter * converter,
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UConverterFromUCallback newAction,
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const void* newContext,
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UConverterFromUCallback *oldAction,
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            const void** oldContext,
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UErrorCode * err)
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE (*err))
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (oldAction) *oldAction = converter->fromUCharErrorBehaviour;
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->fromUCharErrorBehaviour = newAction;
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (oldContext) *oldContext = converter->fromUContext;
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    converter->fromUContext = newContext;
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_updateOffsets(int32_t *offsets, int32_t length,
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               int32_t sourceIndex, int32_t errorInputLength) {
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *limit;
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t delta, offset;
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(sourceIndex>=0) {
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * adjust each offset by adding the previous sourceIndex
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * minus the length of the input sequence that caused an
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * error, if any
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delta=sourceIndex-errorInputLength;
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * set each offset to -1 because this conversion function
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * does not handle offsets
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delta=-1;
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=offsets+length;
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(delta==0) {
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* most common case, nothing to do */
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(delta>0) {
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* add the delta to each offset (but not if the offset is <0) */
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(offsets<limit) {
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            offset=*offsets;
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offset>=0) {
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *offsets=offset+delta;
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++offsets;
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* delta<0 */ {
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * set each offset to -1 because this conversion function
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * does not handle offsets
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * or the error input sequence started in a previous buffer
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(offsets<limit) {
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *offsets++=-1;
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ucnv_fromUnicode --------------------------------------------------------- */
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Implementation note for m:n conversions
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * While collecting source units to find the longest match for m:n conversion,
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * some source units may need to be stored for a partial match.
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * When a second buffer does not yield a match on all of the previously stored
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * source units, then they must be "replayed", i.e., fed back into the converter.
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The code relies on the fact that replaying will not nest -
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * converting a replay buffer will not result in a replay.
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * This is because a replay is necessary only after the _continuation_ of a
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * partial match failed, but a replay buffer is converted as a whole.
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It may result in some of its units being stored again for a partial match,
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * but there will not be a continuation _during_ the replay which could fail.
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It is conceivable that a callback function could call the converter
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * recursively in a way that causes another replay to be stored, but that
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * would be an error in the callback function.
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Such violations will cause assertion failures in a debug build,
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and wrong output, but they will not cause a crash.
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) {
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterFromUnicode fromUnicode;
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverter *cnv;
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s;
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *t;
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *offsets;
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t sourceIndex;
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t errorInputLength;
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool converterSawEndOfInput, calledCallback;
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* variables for m:n conversion */
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar replay[UCNV_EXT_MAX_UCHARS];
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *realSource, *realSourceLimit;
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t realSourceIndex;
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool realFlush;
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv=pArgs->converter;
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=pArgs->source;
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=pArgs->target;
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    offsets=pArgs->offsets;
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* get the converter implementation function */
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    sourceIndex=0;
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(offsets==NULL) {
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fromUnicode=cnv->sharedData->impl->fromUnicode;
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fromUnicode=cnv->sharedData->impl->fromUnicodeWithOffsets;
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(fromUnicode==NULL) {
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* there is no WithOffsets implementation */
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUnicode=cnv->sharedData->impl->fromUnicode;
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* we will write -1 for each offset */
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceIndex=-1;
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv->preFromULength>=0) {
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* normal mode */
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSource=NULL;
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceLimit=NULL;
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realFlush=FALSE;
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceIndex=0;
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Previous m:n conversion stored source units from a partial match
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * and failed to consume all of them.
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We need to "replay" them from a temporary buffer and convert them first.
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSource=pArgs->source;
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceLimit=pArgs->sourceLimit;
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realFlush=pArgs->flush;
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceIndex=sourceIndex;
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR);
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->source=replay;
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->sourceLimit=replay-cnv->preFromULength;
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->flush=FALSE;
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceIndex=-1;
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preFromULength=0;
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * loop for conversion and error handling
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * loop {
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   convert
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   loop {
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     update offsets
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     handle end of input
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     handle errors/call callback
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   }
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * }
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_SUCCESS(*err)) {
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* convert */
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUnicode(pArgs, err);
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * set a flag for whether the converter
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * successfully processed the end of the input
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * need not check cnv->preFromULength==0 because a replay (<0) will cause
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * s<sourceLimit before converterSawEndOfInput is checked
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converterSawEndOfInput=
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (UBool)(U_SUCCESS(*err) &&
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->flush && pArgs->source==pArgs->sourceLimit &&
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        cnv->fromUChar32==0);
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* handle error from ucnv_convertEx() */
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converterSawEndOfInput=FALSE;
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no callback called yet for this iteration */
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        calledCallback=FALSE;
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no sourceIndex adjustment for conversion, only for callback output */
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorInputLength=0;
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * loop for offsets and error handling
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * iterates at most 3 times:
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 1. to clean up after the conversion function
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 2. after the callback
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 3. after the callback again if there was truncated input
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(;;) {
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* update offsets if we write any */
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offsets!=NULL) {
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t length=(int32_t)(pArgs->target-t);
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(length>0) {
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    _updateOffsets(offsets, length, sourceIndex, errorInputLength);
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * if a converter handles offsets and updates the offsets
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * pointer at the end, then pArgs->offset should not change
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * here;
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * however, some converters do not handle offsets at all
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (sourceIndex<0) or may not update the offsets pointer
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->offsets=offsets+=length;
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(sourceIndex>=0) {
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    sourceIndex+=(int32_t)(pArgs->source-s);
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(cnv->preFromULength<0) {
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /*
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * switch the source to new replay units (cannot occur while replaying)
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * after offset handling and before end-of-input and callback handling
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 */
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(realSource==NULL) {
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSource=pArgs->source;
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSourceLimit=pArgs->sourceLimit;
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realFlush=pArgs->flush;
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSourceIndex=sourceIndex;
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_memcpy(replay, cnv->preFromU, -cnv->preFromULength*U_SIZEOF_UCHAR);
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->source=replay;
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->sourceLimit=replay-cnv->preFromULength;
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->flush=FALSE;
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((sourceIndex+=cnv->preFromULength)<0) {
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        sourceIndex=-1;
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cnv->preFromULength=0;
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* see implementation note before _fromUnicodeWithCallback() */
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    U_ASSERT(realSource==NULL);
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err=U_INTERNAL_PROGRAM_ERROR;
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* update pointers */
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s=pArgs->source;
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            t=pArgs->target;
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_SUCCESS(*err)) {
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s<pArgs->sourceLimit) {
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * continue with the conversion loop while there is still input left
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (continue converting by breaking out of only the inner loop)
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(realSource!=NULL) {
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* switch back from replaying to the real source and continue */
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->source=realSource;
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->sourceLimit=realSourceLimit;
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->flush=realFlush;
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    sourceIndex=realSourceIndex;
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSource=NULL;
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(pArgs->flush && cnv->fromUChar32!=0) {
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the entire input stream is consumed
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * and there is a partial, truncated input sequence left
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* inject an error and continue with callback handling */
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err=U_TRUNCATED_CHAR_FOUND;
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    calledCallback=FALSE; /* new error condition */
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* input consumed */
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(pArgs->flush) {
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /*
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * return to the conversion loop once more if the flush
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * flag is set and the conversion function has not
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * successfully processed the end of the input yet
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         *
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * (continue converting by breaking out of only the inner loop)
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         */
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(!converterSawEndOfInput) {
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            break;
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* reset the converter without calling the callback function */
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        _reset(cnv, UCNV_RESET_FROM_UNICODE, FALSE);
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* done successfully */
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* U_FAILURE(*err) */
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            {
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode e;
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if( calledCallback ||
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (e!=U_INVALID_CHAR_FOUND &&
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_ILLEGAL_CHAR_FOUND &&
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_TRUNCATED_CHAR_FOUND)
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ) {
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the callback did not or cannot resolve the error:
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * set output pointers and return
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the check for buffer overflow is redundant but it is
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * a high-runner case and hopefully documents the intent
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * well
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * if we were replaying, then the replay buffer must be
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * copied back into the UConverter
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * and the real arguments must be restored
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(realSource!=NULL) {
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t length;
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        U_ASSERT(cnv->preFromULength==0);
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        length=(int32_t)(pArgs->sourceLimit-pArgs->source);
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(length>0) {
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            uprv_memcpy(cnv->preFromU, pArgs->source, length*U_SIZEOF_UCHAR);
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            cnv->preFromULength=(int8_t)-length;
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->source=realSource;
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->sourceLimit=realSourceLimit;
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->flush=realFlush;
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* callback handling */
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            {
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UChar32 codePoint;
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* get and write the code point */
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                codePoint=cnv->fromUChar32;
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorInputLength=0;
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                U16_APPEND_UNSAFE(cnv->invalidUCharBuffer, errorInputLength, codePoint);
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->invalidUCharLength=(int8_t)errorInputLength;
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* set the converter state to deal with the next character */
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->fromUChar32=0;
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* call the callback function */
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->fromUCharErrorBehaviour(cnv->fromUContext, pArgs,
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cnv->invalidUCharBuffer, errorInputLength, codePoint,
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err==U_INVALID_CHAR_FOUND ? UCNV_UNASSIGNED : UCNV_ILLEGAL,
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    err);
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * loop back to the offset handling
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * this flag will indicate after offset handling
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * that a callback was called;
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * if the callback did not resolve the error, then we return
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            calledCallback=TRUE;
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Output the fromUnicode overflow buffer.
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Call this function if(cnv->charErrorBufferLength>0).
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return TRUE if overflow
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_outputOverflowFromUnicode(UConverter *cnv,
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                               char **target, const char *targetLimit,
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                               int32_t **pOffsets,
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                               UErrorCode *err) {
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *offsets;
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *overflow, *t;
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, length;
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=*target;
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pOffsets!=NULL) {
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offsets=*pOffsets;
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offsets=NULL;
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    overflow=(char *)cnv->charErrorBuffer;
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=cnv->charErrorBufferLength;
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=0;
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i<length) {
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(t==targetLimit) {
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the overflow buffer contains too much, keep the rest */
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t j=0;
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
11496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                overflow[j++]=overflow[i++];
11506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(i<length);
11516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->charErrorBufferLength=(int8_t)j;
11536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *target=t;
11546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offsets!=NULL) {
11556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pOffsets=offsets;
11566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *err=U_BUFFER_OVERFLOW_ERROR;
11586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
11596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the overflow contents to the target */
11626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *t++=overflow[i++];
11636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(offsets!=NULL) {
11646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *offsets++=-1; /* no source index available for old output */
11656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* the overflow buffer is completely copied to the target */
11696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv->charErrorBufferLength=0;
11706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *target=t;
11716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(offsets!=NULL) {
11726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pOffsets=offsets;
11736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
11756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
11786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_fromUnicode(UConverter *cnv,
11796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 char **target, const char *targetLimit,
11806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 const UChar **source, const UChar *sourceLimit,
11816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 int32_t *offsets,
11826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UBool flush,
11836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UErrorCode *err) {
11846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterFromUnicodeArgs args;
11856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s;
11866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *t;
11876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check parameters */
11896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(err==NULL || U_FAILURE(*err)) {
11906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv==NULL || target==NULL || source==NULL) {
11946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
11956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=*source;
11996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=*target;
12006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if ((const void *)U_MAX_PTR(sourceLimit) == (const void *)sourceLimit) {
12026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
12036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Prevent code from going into an infinite loop in case we do hit this
12046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit. The limit pointer is expected to be on a UChar * boundary.
12056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        This also prevents the next argument check from failing.
12066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        */
12076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceLimit = (const UChar *)(((const char *)sourceLimit) - 1);
12086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
12116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * All these conditions should never happen.
12126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
12136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 1) Make sure that the limits are >= to the address source or target
12146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
12156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 2) Make sure that the buffer sizes do not exceed the number range for
12166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * int32_t because some functions use the size (in units or bytes)
12176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * rather than comparing pointers, and because offsets are int32_t values.
12186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
12196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * size_t is guaranteed to be unsigned and large enough for the job.
12206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
12216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Return with an error instead of adjusting the limits because we would
12226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * not be able to maintain the semantics that either the source must be
12236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * consumed or the target filled (unless an error occurs).
12246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * An adjustment would be targetLimit=t+0x7fffffff; for example.
12256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
12266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
12276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * to a char * pointer and provide an incomplete UChar code unit.
12286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
12296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (sourceLimit<s || targetLimit<t ||
12306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((size_t)(sourceLimit-s)>(size_t)0x3fffffff && sourceLimit>s) ||
12316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t) ||
12326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (((const char *)sourceLimit-(const char *)s) & 1) != 0)
12336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
12346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
12356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
12366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* output the target overflow buffer */
12396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( cnv->charErrorBufferLength>0 &&
12406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_outputOverflowFromUnicode(cnv, target, targetLimit, &offsets, err)
12416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
12426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* U_BUFFER_OVERFLOW_ERROR */
12436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
12446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* *target may have moved, therefore stop using t */
12466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!flush && s==sourceLimit && cnv->preFromULength>=0) {
12486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* the overflow buffer is emptied and there is no new input: we are done */
12496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
12506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
12536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Do not simply return with a buffer overflow error if
12546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * !flush && t==targetLimit
12556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * because it is possible that the source will not generate any output.
12566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * For example, the skip callback may be called;
12576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * it does not output anything.
12586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
12596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* prepare the converter arguments */
12616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.converter=cnv;
12626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.flush=flush;
12636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.offsets=offsets;
12646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.source=s;
12656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.sourceLimit=sourceLimit;
12666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.target=*target;
12676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.targetLimit=targetLimit;
12686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.size=sizeof(args);
12696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _fromUnicodeWithCallback(&args, err);
12716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *source=args.source;
12736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *target=args.target;
12746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ucnv_toUnicode() --------------------------------------------------------- */
12776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
12796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) {
12806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterToUnicode toUnicode;
12816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverter *cnv;
12826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *s;
12836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *t;
12846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *offsets;
12856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t sourceIndex;
12866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t errorInputLength;
12876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool converterSawEndOfInput, calledCallback;
12886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* variables for m:n conversion */
12906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char replay[UCNV_EXT_MAX_BYTES];
12916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *realSource, *realSourceLimit;
12926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t realSourceIndex;
12936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool realFlush;
12946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv=pArgs->converter;
12966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=pArgs->source;
12976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=pArgs->target;
12986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    offsets=pArgs->offsets;
12996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* get the converter implementation function */
13016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    sourceIndex=0;
13026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(offsets==NULL) {
13036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUnicode=cnv->sharedData->impl->toUnicode;
13046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
13056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUnicode=cnv->sharedData->impl->toUnicodeWithOffsets;
13066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(toUnicode==NULL) {
13076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* there is no WithOffsets implementation */
13086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUnicode=cnv->sharedData->impl->toUnicode;
13096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* we will write -1 for each offset */
13106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceIndex=-1;
13116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv->preToULength>=0) {
13156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* normal mode */
13166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSource=NULL;
13176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* avoid compiler warnings - not otherwise necessary, and the values do not matter */
13196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceLimit=NULL;
13206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realFlush=FALSE;
13216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceIndex=0;
13226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
13236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
13246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Previous m:n conversion stored source units from a partial match
13256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * and failed to consume all of them.
13266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We need to "replay" them from a temporary buffer and convert them first.
13276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
13286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSource=pArgs->source;
13296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceLimit=pArgs->sourceLimit;
13306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realFlush=pArgs->flush;
13316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        realSourceIndex=sourceIndex;
13326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(replay, cnv->preToU, -cnv->preToULength);
13346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->source=replay;
13356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->sourceLimit=replay-cnv->preToULength;
13366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pArgs->flush=FALSE;
13376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceIndex=-1;
13386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->preToULength=0;
13406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
13436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * loop for conversion and error handling
13446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
13456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * loop {
13466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   convert
13476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   loop {
13486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     update offsets
13496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     handle end of input
13506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *     handle errors/call callback
13516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   }
13526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * }
13536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
13546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
13556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_SUCCESS(*err)) {
13566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* convert */
13576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toUnicode(pArgs, err);
13586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
13606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * set a flag for whether the converter
13616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * successfully processed the end of the input
13626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *
13636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * need not check cnv->preToULength==0 because a replay (<0) will cause
13646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * s<sourceLimit before converterSawEndOfInput is checked
13656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
13666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converterSawEndOfInput=
13676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (UBool)(U_SUCCESS(*err) &&
13686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->flush && pArgs->source==pArgs->sourceLimit &&
13696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        cnv->toULength==0);
13706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
13716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* handle error from getNextUChar() or ucnv_convertEx() */
13726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            converterSawEndOfInput=FALSE;
13736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no callback called yet for this iteration */
13766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        calledCallback=FALSE;
13776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no sourceIndex adjustment for conversion, only for callback output */
13796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorInputLength=0;
13806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
13826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * loop for offsets and error handling
13836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
13846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * iterates at most 3 times:
13856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 1. to clean up after the conversion function
13866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 2. after the callback
13876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * 3. after the callback again if there was truncated input
13886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
13896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(;;) {
13906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* update offsets if we write any */
13916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offsets!=NULL) {
13926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t length=(int32_t)(pArgs->target-t);
13936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(length>0) {
13946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    _updateOffsets(offsets, length, sourceIndex, errorInputLength);
13956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
13976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * if a converter handles offsets and updates the offsets
13986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * pointer at the end, then pArgs->offset should not change
13996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * here;
14006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * however, some converters do not handle offsets at all
14016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (sourceIndex<0) or may not update the offsets pointer
14026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
14036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->offsets=offsets+=length;
14046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
14056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(sourceIndex>=0) {
14076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    sourceIndex+=(int32_t)(pArgs->source-s);
14086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
14096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(cnv->preToULength<0) {
14126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /*
14136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * switch the source to new replay units (cannot occur while replaying)
14146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * after offset handling and before end-of-input and callback handling
14156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 */
14166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(realSource==NULL) {
14176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSource=pArgs->source;
14186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSourceLimit=pArgs->sourceLimit;
14196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realFlush=pArgs->flush;
14206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSourceIndex=sourceIndex;
14216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_memcpy(replay, cnv->preToU, -cnv->preToULength);
14236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->source=replay;
14246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->sourceLimit=replay-cnv->preToULength;
14256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->flush=FALSE;
14266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((sourceIndex+=cnv->preToULength)<0) {
14276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        sourceIndex=-1;
14286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
14296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cnv->preToULength=0;
14316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
14326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* see implementation note before _fromUnicodeWithCallback() */
14336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    U_ASSERT(realSource==NULL);
14346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err=U_INTERNAL_PROGRAM_ERROR;
14356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
14366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* update pointers */
14396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s=pArgs->source;
14406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            t=pArgs->target;
14416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_SUCCESS(*err)) {
14436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s<pArgs->sourceLimit) {
14446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
14456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * continue with the conversion loop while there is still input left
14466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (continue converting by breaking out of only the inner loop)
14476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
14486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
14496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(realSource!=NULL) {
14506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* switch back from replaying to the real source and continue */
14516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->source=realSource;
14526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->sourceLimit=realSourceLimit;
14536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pArgs->flush=realFlush;
14546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    sourceIndex=realSourceIndex;
14556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    realSource=NULL;
14576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
14586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(pArgs->flush && cnv->toULength>0) {
14596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
14606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the entire input stream is consumed
14616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * and there is a partial, truncated input sequence left
14626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
14636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* inject an error and continue with callback handling */
14656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err=U_TRUNCATED_CHAR_FOUND;
14666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    calledCallback=FALSE; /* new error condition */
14676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
14686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* input consumed */
14696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(pArgs->flush) {
14706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /*
14716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * return to the conversion loop once more if the flush
14726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * flag is set and the conversion function has not
14736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * successfully processed the end of the input yet
14746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         *
14756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * (continue converting by breaking out of only the inner loop)
14766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         */
14776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(!converterSawEndOfInput) {
14786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            break;
14796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
14806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* reset the converter without calling the callback function */
14826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE);
14836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
14846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* done successfully */
14866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
14876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
14886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* U_FAILURE(*err) */
14916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            {
14926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode e;
14936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if( calledCallback ||
14956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (e=*err)==U_BUFFER_OVERFLOW_ERROR ||
14966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (e!=U_INVALID_CHAR_FOUND &&
14976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_ILLEGAL_CHAR_FOUND &&
14986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_TRUNCATED_CHAR_FOUND &&
14996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_ILLEGAL_ESCAPE_SEQUENCE &&
15006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     e!=U_UNSUPPORTED_ESCAPE_SEQUENCE)
15016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ) {
15026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
15036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the callback did not or cannot resolve the error:
15046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * set output pointers and return
15056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *
15066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the check for buffer overflow is redundant but it is
15076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * a high-runner case and hopefully documents the intent
15086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * well
15096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *
15106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * if we were replaying, then the replay buffer must be
15116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * copied back into the UConverter
15126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * and the real arguments must be restored
15136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
15146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(realSource!=NULL) {
15156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t length;
15166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        U_ASSERT(cnv->preToULength==0);
15186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        length=(int32_t)(pArgs->sourceLimit-pArgs->source);
15206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(length>0) {
15216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            uprv_memcpy(cnv->preToU, pArgs->source, length);
15226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            cnv->preToULength=(int8_t)-length;
15236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
15246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->source=realSource;
15266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->sourceLimit=realSourceLimit;
15276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pArgs->flush=realFlush;
15286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
15296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
15316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
15326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* copy toUBytes[] to invalidCharBuffer[] */
15356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorInputLength=cnv->invalidCharLength=cnv->toULength;
15366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(errorInputLength>0) {
15376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uprv_memcpy(cnv->invalidCharBuffer, cnv->toUBytes, errorInputLength);
15386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* set the converter state to deal with the next character */
15416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->toULength=0;
15426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* call the callback function */
15446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(cnv->toUCallbackReason==UCNV_ILLEGAL && *err==U_INVALID_CHAR_FOUND) {
15456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->toUCallbackReason = UCNV_UNASSIGNED;
15466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs,
15486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->invalidCharBuffer, errorInputLength,
15496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cnv->toUCallbackReason,
15506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                err);
15516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->toUCallbackReason = UCNV_ILLEGAL; /* reset to default value */
15526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
15546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * loop back to the offset handling
15556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *
15566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * this flag will indicate after offset handling
15576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * that a callback was called;
15586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * if the callback did not resolve the error, then we return
15596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
15606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            calledCallback=TRUE;
15616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
15626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
15646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
15666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Output the toUnicode overflow buffer.
15676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Call this function if(cnv->UCharErrorBufferLength>0).
15686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return TRUE if overflow
15696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
15706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
15716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_outputOverflowToUnicode(UConverter *cnv,
15726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UChar **target, const UChar *targetLimit,
15736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             int32_t **pOffsets,
15746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UErrorCode *err) {
15756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *offsets;
15766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *overflow, *t;
15776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, length;
15786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=*target;
15806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pOffsets!=NULL) {
15816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offsets=*pOffsets;
15826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
15836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        offsets=NULL;
15846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    overflow=cnv->UCharErrorBuffer;
15876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=cnv->UCharErrorBufferLength;
15886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    i=0;
15896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(i<length) {
15906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(t==targetLimit) {
15916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the overflow buffer contains too much, keep the rest */
15926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t j=0;
15936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
15956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                overflow[j++]=overflow[i++];
15966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(i<length);
15976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->UCharErrorBufferLength=(int8_t)j;
15996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *target=t;
16006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(offsets!=NULL) {
16016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pOffsets=offsets;
16026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
16036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *err=U_BUFFER_OVERFLOW_ERROR;
16046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
16056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the overflow contents to the target */
16086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *t++=overflow[i++];
16096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(offsets!=NULL) {
16106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *offsets++=-1; /* no source index available for old output */
16116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* the overflow buffer is completely copied to the target */
16156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cnv->UCharErrorBufferLength=0;
16166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *target=t;
16176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(offsets!=NULL) {
16186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pOffsets=offsets;
16196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
16216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
16246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_toUnicode(UConverter *cnv,
16256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UChar **target, const UChar *targetLimit,
16266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               const char **source, const char *sourceLimit,
16276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               int32_t *offsets,
16286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UBool flush,
16296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UErrorCode *err) {
16306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterToUnicodeArgs args;
16316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *s;
16326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *t;
16336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check parameters */
16356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(err==NULL || U_FAILURE(*err)) {
16366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv==NULL || target==NULL || source==NULL) {
16406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
16416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=*source;
16456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=*target;
16466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if ((const void *)U_MAX_PTR(targetLimit) == (const void *)targetLimit) {
16486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
16496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Prevent code from going into an infinite loop in case we do hit this
16506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit. The limit pointer is expected to be on a UChar * boundary.
16516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        This also prevents the next argument check from failing.
16526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        */
16536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        targetLimit = (const UChar *)(((const char *)targetLimit) - 1);
16546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
16576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * All these conditions should never happen.
16586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
16596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 1) Make sure that the limits are >= to the address source or target
16606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
16616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 2) Make sure that the buffer sizes do not exceed the number range for
16626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * int32_t because some functions use the size (in units or bytes)
16636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * rather than comparing pointers, and because offsets are int32_t values.
16646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
16656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * size_t is guaranteed to be unsigned and large enough for the job.
16666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
16676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Return with an error instead of adjusting the limits because we would
16686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * not be able to maintain the semantics that either the source must be
16696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * consumed or the target filled (unless an error occurs).
16706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * An adjustment would be sourceLimit=t+0x7fffffff; for example.
16716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
16726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 3) Make sure that the user didn't incorrectly cast a UChar * pointer
16736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * to a char * pointer and provide an incomplete UChar code unit.
16746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
16756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (sourceLimit<s || targetLimit<t ||
16766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s) ||
16776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((size_t)(targetLimit-t)>(size_t)0x3fffffff && targetLimit>t) ||
16786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (((const char *)targetLimit-(const char *)t) & 1) != 0
16796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
16806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
16816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* output the target overflow buffer */
16856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( cnv->UCharErrorBufferLength>0 &&
16866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_outputOverflowToUnicode(cnv, target, targetLimit, &offsets, err)
16876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
16886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* U_BUFFER_OVERFLOW_ERROR */
16896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* *target may have moved, therefore stop using t */
16926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!flush && s==sourceLimit && cnv->preToULength>=0) {
16946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* the overflow buffer is emptied and there is no new input: we are done */
16956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
16966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
16996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Do not simply return with a buffer overflow error if
17006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * !flush && t==targetLimit
17016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * because it is possible that the source will not generate any output.
17026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * For example, the skip callback may be called;
17036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * it does not output anything.
17046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
17056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* prepare the converter arguments */
17076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.converter=cnv;
17086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.flush=flush;
17096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.offsets=offsets;
17106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.source=s;
17116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.sourceLimit=sourceLimit;
17126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.target=*target;
17136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.targetLimit=targetLimit;
17146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.size=sizeof(args);
17156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _toUnicodeWithCallback(&args, err);
17176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *source=args.source;
17196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *target=args.target;
17206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
17216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ucnv_to/fromUChars() ----------------------------------------------------- */
17236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
17256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_fromUChars(UConverter *cnv,
17266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                char *dest, int32_t destCapacity,
17276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                const UChar *src, int32_t srcLength,
17286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UErrorCode *pErrorCode) {
17296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *srcLimit;
17306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *originalDest, *destLimit;
17316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t destLength;
17326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check arguments */
17346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
17356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
17366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( cnv==NULL ||
17396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destCapacity<0 || (destCapacity>0 && dest==NULL) ||
17406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength<-1 || (srcLength!=0 && src==NULL)
17416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
17426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
17436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
17446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* initialize */
17476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_resetFromUnicode(cnv);
17486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    originalDest=dest;
17496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(srcLength==-1) {
17506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength=u_strlen(src);
17516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(srcLength>0) {
17536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLimit=src+srcLength;
17546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLimit=dest+destCapacity;
17556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
17576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
17586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destLimit=(char *)U_MAX_PTR(dest);
17596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* perform the conversion */
17626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
17636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLength=(int32_t)(dest-originalDest);
17646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* if an overflow occurs, then get the preflighting length */
17666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
17676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            char buffer[1024];
17686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destLimit=buffer+sizeof(buffer);
17706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
17716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                dest=buffer;
17726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
17736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
17746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                destLength+=(int32_t)(dest-buffer);
17756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
17766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
17776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
17786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLength=0;
17796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_terminateChars(originalDest, destCapacity, destLength, pErrorCode);
17826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
17836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
17856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_toUChars(UConverter *cnv,
17866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UChar *dest, int32_t destCapacity,
17876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              const char *src, int32_t srcLength,
17886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UErrorCode *pErrorCode) {
17896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *srcLimit;
17906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *originalDest, *destLimit;
17916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t destLength;
17926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check arguments */
17946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
17956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
17966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
17976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
17986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( cnv==NULL ||
17996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destCapacity<0 || (destCapacity>0 && dest==NULL) ||
18006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength<-1 || (srcLength!=0 && src==NULL))
18016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
18026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
18036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
18046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* initialize */
18076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucnv_resetToUnicode(cnv);
18086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    originalDest=dest;
18096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(srcLength==-1) {
18106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength=(int32_t)uprv_strlen(src);
18116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(srcLength>0) {
18136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLimit=src+srcLength;
18146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLimit=dest+destCapacity;
18156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
18176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
18186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destLimit=(UChar *)U_MAX_PTR(dest);
18196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* perform the conversion */
18226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
18236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLength=(int32_t)(dest-originalDest);
18246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* if an overflow occurs, then get the preflighting length */
18266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR)
18276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        {
18286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar buffer[1024];
18296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destLimit=buffer+sizeof(buffer)/U_SIZEOF_UCHAR;
18316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do {
18326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                dest=buffer;
18336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
18346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
18356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                destLength+=(int32_t)(dest-buffer);
18366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
18376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
18386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
18396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
18406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        destLength=0;
18416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_terminateUChars(originalDest, destCapacity, destLength, pErrorCode);
18446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
18456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ucnv_getNextUChar() ------------------------------------------------------ */
18476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UChar32 U_EXPORT2
18496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_getNextUChar(UConverter *cnv,
18506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const char **source, const char *sourceLimit,
18516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  UErrorCode *err) {
18526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterToUnicodeArgs args;
18536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar buffer[U16_MAX_LENGTH];
18546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *s;
18556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c;
18566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i, length;
18576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check parameters */
18596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(err==NULL || U_FAILURE(*err)) {
18606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
18616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv==NULL || source==NULL) {
18646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
18656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
18666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=*source;
18696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(sourceLimit<s) {
18706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
18716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
18726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
18756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Make sure that the buffer sizes do not exceed the number range for
18766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * int32_t because some functions use the size (in units or bytes)
18776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * rather than comparing pointers, and because offsets are int32_t values.
18786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
18796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * size_t is guaranteed to be unsigned and large enough for the job.
18806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
18816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Return with an error instead of adjusting the limits because we would
18826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * not be able to maintain the semantics that either the source must be
18836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * consumed or the target filled (unless an error occurs).
18846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * An adjustment would be sourceLimit=t+0x7fffffff; for example.
18856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
18866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) {
18876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_ILLEGAL_ARGUMENT_ERROR;
18886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0xffff;
18896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
18906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    c=U_SENTINEL;
18926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* flush the target overflow buffer */
18946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(cnv->UCharErrorBufferLength>0) {
18956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar *overflow;
18966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
18976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        overflow=cnv->UCharErrorBuffer;
18986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=0;
18996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=cnv->UCharErrorBufferLength;
19006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        U16_NEXT(overflow, i, length, c);
19016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* move the remaining overflow contents up to the beginning */
19036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((cnv->UCharErrorBufferLength=(int8_t)(length-i))>0) {
19046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+i,
19056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR);
19066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!U16_IS_LEAD(c) || i<length) {
19096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return c;
19106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Continue if the overflow buffer contained only a lead surrogate,
19136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * in case the converter outputs single surrogates from complete
19146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * input sequences.
19156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
19176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
19196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * flush==TRUE is implied for ucnv_getNextUChar()
19206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
19216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * do not simply return even if s==sourceLimit because the converter may
19226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * not have seen flush==TRUE before
19236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
19246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* prepare the converter arguments */
19266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.converter=cnv;
19276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.flush=TRUE;
19286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.offsets=NULL;
19296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.source=s;
19306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.sourceLimit=sourceLimit;
19316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.target=buffer;
19326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.targetLimit=buffer+1;
19336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    args.size=sizeof(args);
19346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(c<0) {
19366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
19376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * call the native getNextUChar() implementation if we are
19386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * at a character boundary (toULength==0)
19396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
19406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * unlike with _toUnicode(), getNextUChar() implementations must set
19416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * U_TRUNCATED_CHAR_FOUND for truncated input,
19426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * in addition to setting toULength/toUBytes[]
19436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
19446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(cnv->toULength==0 && cnv->sharedData->impl->getNextUChar!=NULL) {
19456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=cnv->sharedData->impl->getNextUChar(&args, err);
19466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *source=s=args.source;
19476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(*err==U_INDEX_OUTOFBOUNDS_ERROR) {
19486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* reset the converter without calling the callback function */
19496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                _reset(cnv, UCNV_RESET_TO_UNICODE, FALSE);
19506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0xffff; /* no output */
19516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(U_SUCCESS(*err) && c>=0) {
19526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return c;
19536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
19546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * else fall through to use _toUnicode() because
19556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *   UCNV_GET_NEXT_UCHAR_USE_TO_U: the native function did not want to handle it after all
19566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *   U_FAILURE: call _toUnicode() for callback handling (do not output c)
19576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
19586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
19596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* convert to one UChar in buffer[0], or handle getNextUChar() errors */
19626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _toUnicodeWithCallback(&args, err);
19636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*err==U_BUFFER_OVERFLOW_ERROR) {
19656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *err=U_ZERO_ERROR;
19666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
19676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=0;
19696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=(int32_t)(args.target-buffer);
19706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
19716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* write the lead surrogate from the overflow buffer */
19726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buffer[0]=(UChar)c;
19736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        args.target=buffer+1;
19746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=0;
19756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=1;
19766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
19776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* buffer contents starts at i and ends before length */
19796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*err)) {
19816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=0xffff; /* no output */
19826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(length==0) {
19836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no input or only state changes */
19846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *err=U_INDEX_OUTOFBOUNDS_ERROR;
19856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no need to reset explicitly because _toUnicodeWithCallback() did it */
19866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=0xffff; /* no output */
19876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
19886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=buffer[0];
19896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        i=1;
19906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!U16_IS_LEAD(c)) {
19916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* consume c=buffer[0], done */
19926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
19936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* got a lead surrogate, see if a trail surrogate follows */
19946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar c2;
19956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
19966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(cnv->UCharErrorBufferLength>0) {
19976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* got overflow output from the conversion */
19986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U16_IS_TRAIL(c2=cnv->UCharErrorBuffer[0])) {
19996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* got a trail surrogate, too */
20006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c=U16_GET_SUPPLEMENTARY(c, c2);
20016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* move the remaining overflow contents up to the beginning */
20036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((--cnv->UCharErrorBufferLength)>0) {
20046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        uprv_memmove(cnv->UCharErrorBuffer, cnv->UCharErrorBuffer+1,
20056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     cnv->UCharErrorBufferLength*U_SIZEOF_UCHAR);
20066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
20076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
20086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* c is an unpaired lead surrogate, just return it */
20096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(args.source<sourceLimit) {
20116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* convert once more, to buffer[1] */
20126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                args.targetLimit=buffer+2;
20136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                _toUnicodeWithCallback(&args, err);
20146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(*err==U_BUFFER_OVERFLOW_ERROR) {
20156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *err=U_ZERO_ERROR;
20166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length=(int32_t)(args.target-buffer);
20196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_SUCCESS(*err) && length==2 && U16_IS_TRAIL(c2=buffer[1])) {
20206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* got a trail surrogate, too */
20216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c=U16_GET_SUPPLEMENTARY(c, c2);
20226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    i=2;
20236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
20246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
20256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
20266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
20296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * move leftover output from buffer[i..length[
20306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * into the beginning of the overflow buffer
20316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
20326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(i<length) {
20336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* move further overflow back */
20346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t delta=length-i;
20356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((length=cnv->UCharErrorBufferLength)>0) {
20366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memmove(cnv->UCharErrorBuffer+delta, cnv->UCharErrorBuffer,
20376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         length*U_SIZEOF_UCHAR);
20386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
20396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->UCharErrorBufferLength=(int8_t)(length+delta);
20406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cnv->UCharErrorBuffer[0]=buffer[i++];
20426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(delta>1) {
20436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cnv->UCharErrorBuffer[1]=buffer[i];
20446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
20456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *source=args.source;
20486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return c;
20496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
20506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ucnv_convert() and siblings ---------------------------------------------- */
20526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
20546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_convertEx(UConverter *targetCnv, UConverter *sourceCnv,
20556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               char **target, const char *targetLimit,
20566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               const char **source, const char *sourceLimit,
20576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UChar *pivotStart, UChar **pivotSource,
20586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UChar **pivotTarget, const UChar *pivotLimit,
20596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UBool reset, UBool flush,
20606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               UErrorCode *pErrorCode) {
20616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar pivotBuffer[CHUNK_SIZE];
20626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *myPivotSource;
20636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *myPivotTarget;
20646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *s;
20656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *t;
20666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterToUnicodeArgs toUArgs;
20686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterFromUnicodeArgs fromUArgs;
20696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UConverterConvert convert;
20706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* error checking */
20726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
20736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
20746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( targetCnv==NULL || sourceCnv==NULL ||
20776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        source==NULL || *source==NULL ||
20786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        target==NULL || *target==NULL || targetLimit==NULL
20796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
20806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
20816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
20826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=*source;
20856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t=*target;
20866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((sourceLimit!=NULL && sourceLimit<s) || targetLimit<t) {
20876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
20886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
20896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
20906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
20916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
20926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Make sure that the buffer sizes do not exceed the number range for
20936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * int32_t. See ucnv_toUnicode() for a more detailed comment.
20946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
20956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(
20966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (sourceLimit!=NULL && ((size_t)(sourceLimit-s)>(size_t)0x7fffffff && sourceLimit>s)) ||
20976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((size_t)(targetLimit-t)>(size_t)0x7fffffff && targetLimit>t)
20986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
20996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
21006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
21016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pivotStart==NULL) {
21046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!flush) {
21056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* streaming conversion requires an explicit pivot buffer */
21066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
21076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
21086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
21096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* use the stack pivot buffer */
21116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        myPivotSource=myPivotTarget=pivotStart=pivotBuffer;
21126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pivotSource=(UChar **)&myPivotSource;
21136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pivotTarget=&myPivotTarget;
21146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pivotLimit=pivotBuffer+CHUNK_SIZE;
21156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(  pivotStart>=pivotLimit ||
21166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pivotSource==NULL || *pivotSource==NULL ||
21176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pivotTarget==NULL || *pivotTarget==NULL ||
21186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pivotLimit==NULL
21196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
21206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
21216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
21226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(sourceLimit==NULL) {
21256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* get limit of single-byte-NUL-terminated source string */
21266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceLimit=uprv_strchr(*source, 0);
21276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(reset) {
21306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_resetToUnicode(sourceCnv);
21316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_resetFromUnicode(targetCnv);
21326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pivotSource=*pivotTarget=pivotStart;
21336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(targetCnv->charErrorBufferLength>0) {
21346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* output the targetCnv overflow buffer */
21356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(ucnv_outputOverflowFromUnicode(targetCnv, target, targetLimit, NULL, pErrorCode)) {
21366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* U_BUFFER_OVERFLOW_ERROR */
21376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
21386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
21396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* *target has moved, therefore stop using t */
21406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( !flush &&
21426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            targetCnv->preFromULength>=0 && *pivotSource==*pivotTarget &&
21436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceCnv->UCharErrorBufferLength==0 && sourceCnv->preToULength>=0 && s==sourceLimit
21446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
21456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the fromUnicode overflow buffer is emptied and there is no new input: we are done */
21466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
21476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
21486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Is direct-UTF-8 conversion available? */
21516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( sourceCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
21526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        targetCnv->sharedData->impl->fromUTF8!=NULL
21536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
21546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        convert=targetCnv->sharedData->impl->fromUTF8;
21556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if( targetCnv->sharedData->staticData->conversionType==UCNV_UTF8 &&
21566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org               sourceCnv->sharedData->impl->toUTF8!=NULL
21576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
21586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        convert=sourceCnv->sharedData->impl->toUTF8;
21596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
21606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        convert=NULL;
21616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
21646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * If direct-UTF-8 conversion is available, then we use a smaller
21656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * pivot buffer for error handling and partial matches
21666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * so that we quickly return to direct conversion.
21676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
21686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * 32 is large enough for UCNV_EXT_MAX_UCHARS and UCNV_ERROR_BUFFER_LENGTH.
21696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
21706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * We could reduce the pivot buffer size further, at the cost of
21716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * buffer overflows from callbacks.
21726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * The pivot buffer should not be smaller than the maximum number of
21736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * fromUnicode extension table input UChars
21746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * (for m:n conversion, see
21756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * targetCnv->sharedData->mbcs.extIndexes[UCNV_EXT_COUNT_UCHARS])
21766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * or 2 for surrogate pairs.
21776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
21786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Too small a buffer can cause thrashing between pivoting and direct
21796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * conversion, with function call overhead outweighing the benefits
21806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * of direct conversion.
21816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
21826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(convert!=NULL && (pivotLimit-pivotStart)>32) {
21836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pivotLimit=pivotStart+32;
21846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
21856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* prepare the converter arguments */
21876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.converter=targetCnv;
21886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.flush=FALSE;
21896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.offsets=NULL;
21906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.target=*target;
21916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.targetLimit=targetLimit;
21926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fromUArgs.size=sizeof(fromUArgs);
21936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
21946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.converter=sourceCnv;
21956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.flush=flush;
21966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.offsets=NULL;
21976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.source=s;
21986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.sourceLimit=sourceLimit;
21996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.targetLimit=pivotLimit;
22006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    toUArgs.size=sizeof(toUArgs);
22016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
22036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * TODO: Consider separating this function into two functions,
22046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * extracting exactly the conversion loop,
22056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * for readability and to reduce the set of visible variables.
22066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
22076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * Otherwise stop using s and t from here on.
22086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
22096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    s=t=NULL;
22106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
22126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * conversion loop
22136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
22146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * The sequence of steps in the loop may appear backward,
22156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * but the principle is simple:
22166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * In the chain of
22176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *   source - sourceCnv overflow - pivot - targetCnv overflow - target
22186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * empty out later buffers before refilling them from earlier ones.
22196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     *
22206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * The targetCnv overflow buffer is flushed out only once before the loop.
22216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
22226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
22236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
22246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * if(pivot not empty or error or replay or flush fromUnicode) {
22256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *   fromUnicode(pivot -> target);
22266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * }
22276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
22286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * For pivoting conversion; and for direct conversion for
22296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * error callback handling and flushing the replay buffer.
22306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
22316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( *pivotSource<*pivotTarget ||
22326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U_FAILURE(*pErrorCode) ||
22336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            targetCnv->preFromULength<0 ||
22346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUArgs.flush
22356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
22366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUArgs.source=*pivotSource;
22376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUArgs.sourceLimit=*pivotTarget;
22386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            _fromUnicodeWithCallback(&fromUArgs, pErrorCode);
22396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(*pErrorCode)) {
22406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* target overflow, or conversion error */
22416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pivotSource=(UChar *)fromUArgs.source;
22426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
22436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
22446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
22466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * _fromUnicodeWithCallback() must have consumed the pivot contents
22476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * (*pivotSource==*pivotTarget) since it returned with U_SUCCESS()
22486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
22496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
22506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* The pivot buffer is empty; reset it so we start at pivotStart. */
22526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pivotSource=*pivotTarget=pivotStart;
22536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
22556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * if(sourceCnv overflow buffer not empty) {
22566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *     move(sourceCnv overflow buffer -> pivot);
22576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *     continue;
22586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * }
22596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
22606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* output the sourceCnv overflow buffer */
22616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(sourceCnv->UCharErrorBufferLength>0) {
22626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(ucnv_outputOverflowToUnicode(sourceCnv, pivotTarget, pivotLimit, NULL, pErrorCode)) {
22636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* U_BUFFER_OVERFLOW_ERROR */
22646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
22656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
22666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            continue;
22676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
22686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
22706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * check for end of input and break if done
22716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
22726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Checking both flush and fromUArgs.flush ensures that the converters
22736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * have been called with the flush flag set if the ucnv_convertEx()
22746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * caller set it.
22756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
22766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( toUArgs.source==sourceLimit &&
22776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceCnv->preToULength>=0 && sourceCnv->toULength==0 &&
22786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (!flush || fromUArgs.flush)
22796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
22806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* done successfully */
22816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
22826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
22836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
22846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
22856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * use direct conversion if available
22866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * but not if continuing a partial match
22876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * or flushing the toUnicode replay buffer
22886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
22896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(convert!=NULL && targetCnv->preFromUFirstCP<0 && sourceCnv->preToULength==0) {
22906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(*pErrorCode==U_USING_DEFAULT_WARNING) {
22916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* remove a warning that may be set by this function */
22926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
22936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
22946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            convert(&fromUArgs, &toUArgs, pErrorCode);
22956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
22966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
22976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(U_FAILURE(*pErrorCode)) {
22986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(sourceCnv->toULength>0) {
22996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
23006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * Fall through to calling _toUnicodeWithCallback()
23016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * for callback handling.
23026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *
23036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * The pivot buffer will be reset with
23046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     *   *pivotSource=*pivotTarget=pivotStart;
23056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * which indicates a toUnicode error to the caller
23066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (*pivotSource==pivotStart shows no pivot UChars consumed).
23076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
23086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
23096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
23106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * Indicate a fromUnicode error to the caller
23116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * (*pivotSource>pivotStart shows some pivot UChars consumed).
23126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
23136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *pivotSource=*pivotTarget=pivotStart+1;
23146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
23156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * Loop around to calling _fromUnicodeWithCallbacks()
23166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * for callback handling.
23176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
23186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    continue;
23196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
23206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(*pErrorCode==U_USING_DEFAULT_WARNING) {
23216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /*
23226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * No error, but the implementation requested to temporarily
23236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * fall back to pivoting.
23246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 */
23256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
23266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
23276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * The following else branches are almost identical to the end-of-input
23286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * handling in _toUnicodeWithCallback().
23296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * Avoid calling it just for the end of input.
23306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
23316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(flush && sourceCnv->toULength>0) { /* flush==toUArgs.flush */
23326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /*
23336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * the entire input stream is consumed
23346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 * and there is a partial, truncated input sequence left
23356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 */
23366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* inject an error and continue with callback handling */
23386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_TRUNCATED_CHAR_FOUND;
23396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
23406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* input consumed */
23416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(flush) {
23426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* reset the converters without calling the callback functions */
23436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    _reset(sourceCnv, UCNV_RESET_TO_UNICODE, FALSE);
23446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    _reset(targetCnv, UCNV_RESET_FROM_UNICODE, FALSE);
23456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
23466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* done successfully */
23486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
23496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
23506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
23516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
23536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * toUnicode(source -> pivot);
23546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
23556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * For pivoting conversion; and for direct conversion for
23566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * error callback handling, continuing partial matches
23576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * and flushing the replay buffer.
23586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
23596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * The pivot buffer is empty and reset.
23606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
23616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        toUArgs.target=pivotStart; /* ==*pivotTarget */
23626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* toUArgs.targetLimit=pivotLimit; already set before the loop */
23636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _toUnicodeWithCallback(&toUArgs, pErrorCode);
23646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pivotTarget=toUArgs.target;
23656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
23666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* pivot overflow: continue with the conversion loop */
23676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_ZERO_ERROR;
23686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(U_FAILURE(*pErrorCode) || (!flush && *pivotTarget==pivotStart)) {
23696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* conversion error, or there was nothing left to convert */
23706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
23716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
23726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
23736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * else:
23746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * _toUnicodeWithCallback() wrote into the pivot buffer,
23756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * continue with fromUnicode conversion.
23766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
23776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Set the fromUnicode flush flag if we flush and if toUnicode has
23786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * processed the end of the input.
23796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
23806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( flush && toUArgs.source==sourceLimit &&
23816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceCnv->preToULength>=0 &&
23826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sourceCnv->UCharErrorBufferLength==0
23836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
23846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fromUArgs.flush=TRUE;
23856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
23866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
23876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
23896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * The conversion loop is exited when one of the following is true:
23906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - the entire source text has been converted successfully to the target buffer
23916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - a target buffer overflow occurred
23926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * - a conversion error occurred
23936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
23946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *source=toUArgs.source;
23966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *target=fromUArgs.target;
23976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
23986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* terminate the target buffer if possible */
23996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(flush && U_SUCCESS(*pErrorCode)) {
24006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(*target!=targetLimit) {
24016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            **target=0;
24026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
24036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_ZERO_ERROR;
24046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
24056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
24066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_STRING_NOT_TERMINATED_WARNING;
24076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
24086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
24096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
24106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* internal implementation of ucnv_convert() etc. with preflighting */
24126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
24136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgucnv_internalConvert(UConverter *outConverter, UConverter *inConverter,
24146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     char *target, int32_t targetCapacity,
24156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     const char *source, int32_t sourceLength,
24166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     UErrorCode *pErrorCode) {
24176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar pivotBuffer[CHUNK_SIZE];
24186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *pivot, *pivot2;
24196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *myTarget;
24216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *sourceLimit;
24226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *targetLimit;
24236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t targetLength=0;
24246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set up */
24266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(sourceLength<0) {
24276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceLimit=uprv_strchr(source, 0);
24286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
24296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        sourceLimit=source+sourceLength;
24306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
24316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* if there is no input data, we're done */
24336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(source==sourceLimit) {
24346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return u_terminateChars(target, targetCapacity, 0, pErrorCode);
24356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
24366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pivot=pivot2=pivotBuffer;
24386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    myTarget=target;
24396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    targetLength=0;
24406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(targetCapacity>0) {
24426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* perform real conversion */
24436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        targetLimit=target+targetCapacity;
24446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ucnv_convertEx(outConverter, inConverter,
24456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       &myTarget, targetLimit,
24466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       &source, sourceLimit,
24476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE,
24486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       FALSE,
24496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       TRUE,
24506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       pErrorCode);
24516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        targetLength=(int32_t)(myTarget-target);
24526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
24536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
24556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * If the output buffer is exhausted (or we are only "preflighting"), we need to stop writing
24566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * to it but continue the conversion in order to store in targetCapacity
24576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * the number of bytes that was required.
24586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
24596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR || targetCapacity==0)
24606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
24616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char targetBuffer[CHUNK_SIZE];
24626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
24636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        targetLimit=targetBuffer+CHUNK_SIZE;
24646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        do {
24656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_ZERO_ERROR;
24666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            myTarget=targetBuffer;
24676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ucnv_convertEx(outConverter, inConverter,
24686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &myTarget, targetLimit,
24696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           &source, sourceLimit,
24706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           pivotBuffer, &pivot, &pivot2, pivotBuffer+CHUNK_SIZE,
24716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           FALSE,
24726f31ac30b9092fd02a8c97e5216cf53f3e4fae4