/*
******************************************************************************
*
-* Copyright (C) 1998-2004, International Business Machines
+* Copyright (C) 1998-2006,2008 International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
#include "utracimp.h"
#include "ustr_imp.h"
#include "ucnv_imp.h"
-#include "ucnv_io.h"
#include "ucnv_cnv.h"
#include "ucnv_bld.h"
{ "ISO_2022,locale=ko,version=0", 0x20a9 }
};
-U_CAPI const char* U_EXPORT2
-ucnv_getDefaultName ()
-{
- return ucnv_io_getDefaultConverterName();
-}
-
-U_CAPI void U_EXPORT2
-ucnv_setDefaultName (const char *converterName)
-{
- ucnv_io_setDefaultConverterName(converterName);
-}
/*Calls through createConverter */
U_CAPI UConverter* U_EXPORT2
ucnv_open (const char *name,
return ucnv_open(u_austrcpy(asciiName, name), err);
}
+/* Copy the string that is represented by the UConverterPlatform enum
+ * @param platformString An output buffer
+ * @param platform An enum representing a platform
+ * @return the length of the copied string.
+ */
+static int32_t
+ucnv_copyPlatformString(char *platformString, UConverterPlatform pltfrm)
+{
+ switch (pltfrm)
+ {
+ case UCNV_IBM:
+ uprv_strcpy(platformString, "ibm-");
+ return 4;
+ case UCNV_UNKNOWN:
+ break;
+ }
+
+ /* default to empty string */
+ *platformString = 0;
+ return 0;
+}
+
/*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
*through createConverter*/
U_CAPI UConverter* U_EXPORT2
uprv_memcpy(localConverter, cnv, sizeof(UConverter));
localConverter->isCopyLocal = localConverter->isExtraLocal = FALSE;
+ /* copy the substitution string */
+ if (cnv->subChars == (uint8_t *)cnv->subUChars) {
+ localConverter->subChars = (uint8_t *)localConverter->subUChars;
+ } else {
+ localConverter->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
+ if (localConverter->subChars == NULL) {
+ uprv_free(allocatedConverter);
+ UTRACE_EXIT_STATUS(*status);
+ return NULL;
+ }
+ uprv_memcpy(localConverter->subChars, cnv->subChars, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
+ }
+
/* now either call the safeclone fcn or not */
if (cnv->sharedData->impl->safeClone != NULL) {
/* call the custom safeClone function */
}
if(localConverter==NULL || U_FAILURE(*status)) {
+ if (allocatedConverter != NULL && allocatedConverter->subChars != (uint8_t *)allocatedConverter->subUChars) {
+ uprv_free(allocatedConverter->subChars);
+ }
uprv_free(allocatedConverter);
UTRACE_EXIT_STATUS(*status);
return NULL;
U_CAPI void U_EXPORT2
ucnv_close (UConverter * converter)
{
- /* first, notify the callback functions that the converter is closed */
- UConverterToUnicodeArgs toUArgs = {
- sizeof(UConverterToUnicodeArgs),
- TRUE,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- };
- UConverterFromUnicodeArgs fromUArgs = {
- sizeof(UConverterFromUnicodeArgs),
- TRUE,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- };
UErrorCode errorCode = U_ZERO_ERROR;
UTRACE_ENTRY_OC(UTRACE_UCNV_CLOSE);
UTRACE_DATA3(UTRACE_OPEN_CLOSE, "close converter %s at %p, isCopyLocal=%b",
ucnv_getName(converter, &errorCode), converter, converter->isCopyLocal);
- toUArgs.converter = fromUArgs.converter = converter;
+ /* In order to speed up the close, only call the callbacks when they have been changed.
+ This performance check will only work when the callbacks are set within a shared library
+ or from user code that statically links this code. */
+ /* first, notify the callback functions that the converter is closed */
+ if (converter->fromCharErrorBehaviour != UCNV_TO_U_DEFAULT_CALLBACK) {
+ UConverterToUnicodeArgs toUArgs = {
+ sizeof(UConverterToUnicodeArgs),
+ TRUE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
- converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_CLOSE, &errorCode);
- errorCode = U_ZERO_ERROR;
- converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLOSE, &errorCode);
+ toUArgs.converter = converter;
+ errorCode = U_ZERO_ERROR;
+ converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_CLOSE, &errorCode);
+ }
+ if (converter->fromUCharErrorBehaviour != UCNV_FROM_U_DEFAULT_CALLBACK) {
+ UConverterFromUnicodeArgs fromUArgs = {
+ sizeof(UConverterFromUnicodeArgs),
+ TRUE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+ fromUArgs.converter = converter;
+ errorCode = U_ZERO_ERROR;
+ converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLOSE, &errorCode);
+ }
if (converter->sharedData->impl->close != NULL) {
converter->sharedData->impl->close(converter);
}
+ if (converter->subChars != (uint8_t *)converter->subUChars) {
+ uprv_free(converter->subChars);
+ }
+
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
}
if(!converter->isCopyLocal){
- uprv_free (converter);
+ uprv_free(converter);
}
UTRACE_EXIT();
U_CAPI const char* U_EXPORT2
ucnv_getAvailableName (int32_t n)
{
- if (0 <= n && n <= 0xffff) {
- UErrorCode err = U_ZERO_ERROR;
- const char *name = ucnv_io_getAvailableConverter((uint16_t)n, &err);
- if (U_SUCCESS(err)) {
- return name;
+ if (0 <= n && n <= 0xffff) {
+ UErrorCode err = U_ZERO_ERROR;
+ const char *name = ucnv_bld_getAvailableConverter((uint16_t)n, &err);
+ if (U_SUCCESS(err)) {
+ return name;
+ }
}
- }
- return NULL;
+ return NULL;
}
U_CAPI int32_t U_EXPORT2
ucnv_countAvailable ()
{
UErrorCode err = U_ZERO_ERROR;
- return ucnv_io_countAvailableConverters(&err);
-}
-
-U_CAPI uint16_t U_EXPORT2
-ucnv_countAliases(const char *alias, UErrorCode *pErrorCode)
-{
- return ucnv_io_countAliases(alias, pErrorCode);
-}
-
-
-U_CAPI const char* U_EXPORT2
-ucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode)
-{
- return ucnv_io_getAlias(alias, n, pErrorCode);
-}
-
-U_CAPI void U_EXPORT2
-ucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode)
-{
- ucnv_io_getAliases(alias, 0, aliases, pErrorCode);
-}
-
-U_CAPI uint16_t U_EXPORT2
-ucnv_countStandards(void)
-{
- UErrorCode err = U_ZERO_ERROR;
- return ucnv_io_countStandards(&err);
+ return ucnv_bld_countAvailableConverters(&err);
}
U_CAPI void U_EXPORT2
if (U_FAILURE (*err))
return;
+ if (converter->subCharLen <= 0) {
+ /* Unicode string or empty string from ucnv_setSubstString(). */
+ *len = 0;
+ return;
+ }
+
if (*len < converter->subCharLen) /*not enough space in subChars */
{
*err = U_INDEX_OUTOFBOUNDS_ERROR;
return;
}
- uprv_memcpy (mySubChar, converter->subChar, converter->subCharLen); /*fills in the subchars */
- *len = converter->subCharLen; /*store # of bytes copied to buffer */
- uprv_memcpy (mySubChar, converter->subChar, converter->subCharLen); /*fills in the subchars */
+ uprv_memcpy (mySubChar, converter->subChars, converter->subCharLen); /*fills in the subchars */
*len = converter->subCharLen; /*store # of bytes copied to buffer */
}
return;
}
- uprv_memcpy (converter->subChar, mySubChar, len); /*copies the subchars */
+ uprv_memcpy (converter->subChars, mySubChar, len); /*copies the subchars */
converter->subCharLen = len; /*sets the new len */
/*
return;
}
+U_DRAFT void U_EXPORT2
+ucnv_setSubstString(UConverter *cnv,
+ const UChar *s,
+ int32_t length,
+ UErrorCode *err) {
+ UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
+ char chars[UCNV_ERROR_BUFFER_LENGTH];
+
+ UConverter *clone;
+ uint8_t *subChars;
+ int32_t cloneSize, length8;
+
+ /* Let the following functions check all arguments. */
+ cloneSize = sizeof(cloneBuffer);
+ clone = ucnv_safeClone(cnv, cloneBuffer, &cloneSize, err);
+ ucnv_setFromUCallBack(clone, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, err);
+ length8 = ucnv_fromUChars(clone, chars, (int32_t)sizeof(chars), s, length, err);
+ ucnv_close(clone);
+ if (U_FAILURE(*err)) {
+ return;
+ }
+
+ if (cnv->sharedData->impl->writeSub == NULL
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ || (cnv->sharedData->staticData->conversionType == UCNV_MBCS &&
+ ucnv_MBCSGetType(cnv) != UCNV_EBCDIC_STATEFUL)
+#endif
+ ) {
+ /* The converter is not stateful. Store the charset bytes as a fixed string. */
+ subChars = (uint8_t *)chars;
+ } else {
+ /*
+ * The converter has a non-default writeSub() function, indicating
+ * that it is stateful.
+ * Store the Unicode string for on-the-fly conversion for correct
+ * state handling.
+ */
+ if (length > UCNV_ERROR_BUFFER_LENGTH) {
+ /*
+ * Should not occur. The converter should output at least one byte
+ * per UChar, which means that ucnv_fromUChars() should catch all
+ * overflows.
+ */
+ *err = U_BUFFER_OVERFLOW_ERROR;
+ return;
+ }
+ subChars = (uint8_t *)s;
+ if (length < 0) {
+ length = u_strlen(s);
+ }
+ length8 = length * U_SIZEOF_UCHAR;
+ }
+
+ /*
+ * For storing the substitution string, select either the small buffer inside
+ * UConverter or allocate a subChars buffer.
+ */
+ if (length8 > UCNV_MAX_SUBCHAR_LEN) {
+ /* Use a separate buffer for the string. Outside UConverter to not make it too large. */
+ if (cnv->subChars == (uint8_t *)cnv->subUChars) {
+ /* Allocate a new buffer for the string. */
+ cnv->subChars = (uint8_t *)uprv_malloc(UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
+ if (cnv->subChars == NULL) {
+ cnv->subChars = (uint8_t *)cnv->subUChars;
+ *err = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ uprv_memset(cnv->subChars, 0, UCNV_ERROR_BUFFER_LENGTH * U_SIZEOF_UCHAR);
+ }
+ }
+
+ /* Copy the substitution string into the UConverter or its subChars buffer. */
+ if (length8 == 0) {
+ cnv->subCharLen = 0;
+ } else {
+ uprv_memcpy(cnv->subChars, subChars, length8);
+ if (subChars == (uint8_t *)chars) {
+ cnv->subCharLen = (int8_t)length8;
+ } else /* subChars == s */ {
+ cnv->subCharLen = (int8_t)-length;
+ }
+ }
+
+ /* See comment in ucnv_setSubstChars(). */
+ cnv->subChar1 = 0;
+}
+
/*resets the internal states of a converter
*goal : have the same behaviour than a freshly created converter
*/
e!=U_ILLEGAL_CHAR_FOUND &&
e!=U_TRUNCATED_CHAR_FOUND &&
e!=U_ILLEGAL_ESCAPE_SEQUENCE &&
- e!=U_UNSUPPORTED_ESCAPE_SEQUENCE)
+ e!=U_UNSUPPORTED_ESCAPE_SEQUENCE &&
+ e!=U_PARSE_ERROR) /* temporary err to flag empty segment, will be reset to U_ILLEGAL_ESCAPE_SEQUENCE below */
) {
/*
* the callback did not or cannot resolve the error:
cnv->toULength=0;
/* call the callback function */
- cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs,
- cnv->invalidCharBuffer, errorInputLength,
- (*err==U_INVALID_CHAR_FOUND || *err==U_UNSUPPORTED_ESCAPE_SEQUENCE) ?
- UCNV_UNASSIGNED : UCNV_ILLEGAL,
- err);
+ {
+ UConverterCallbackReason reason;
+ if (*err == U_PARSE_ERROR) { /* Here U_PARSE_ERROR indicates empty segment */
+ *err = U_ILLEGAL_ESCAPE_SEQUENCE;
+ reason = UCNV_IRREGULAR;
+ } else {
+ reason = (*err==U_INVALID_CHAR_FOUND || *err==U_UNSUPPORTED_ESCAPE_SEQUENCE) ?
+ UCNV_UNASSIGNED : UCNV_ILLEGAL;
+ }
+ cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs,
+ cnv->invalidCharBuffer, errorInputLength, reason, err);
+ }
/*
* loop back to the offset handling
ucnv_resetToUnicode(cnv);
originalDest=dest;
if(srcLength==-1) {
- srcLength=uprv_strlen(src);
+ srcLength=(int32_t)uprv_strlen(src);
}
if(srcLength>0) {
srcLimit=src+srcLength;
}
if(pivotStart==NULL) {
+ if(!flush) {
+ /* streaming conversion requires an explicit pivot buffer */
+ *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
/* use the stack pivot buffer */
pivotStart=myPivotSource=myPivotTarget=pivotBuffer;
pivotSource=&myPivotSource;
FALSE,
TRUE,
pErrorCode);
- targetLength=myTarget-target;
+ targetLength=(int32_t)(myTarget-target);
}
/*
FALSE,
TRUE,
pErrorCode);
- targetLength+=(myTarget-targetBuffer);
+ targetLength+=(int32_t)(myTarget-targetBuffer);
} while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
/* done with preflighting, set warnings and errors as appropriate */
}
if(sourceLength==-1){
- sourceLength=uprv_strlen(source);
+ sourceLength=(int32_t)uprv_strlen(source);
}
return NULL;
}
+ U_DRAFT int32_t U_EXPORT2
+ ucnv_fromUCountPending(const UConverter* cnv, UErrorCode* status){
+
+ if(status == NULL || U_FAILURE(*status)){
+ return -1;
+ }
+ if(cnv == NULL){
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return -1;
+ }
+
+ if(cnv->preFromULength > 0){
+ return U16_LENGTH(cnv->preFromUFirstCP)+cnv->preFromULength ;
+ }else if(cnv->preFromULength < 0){
+ return -cnv->preFromULength ;
+ }else if(cnv->fromUChar32 > 0){
+ return 1;
+ }else if(cnv->preFromUFirstCP >0){
+ return U16_LENGTH(cnv->preFromUFirstCP);
+ }
+ return 0;
+
+ }
+
+U_DRAFT int32_t U_EXPORT2
+ucnv_toUCountPending(const UConverter* cnv, UErrorCode* status){
+
+ if(status == NULL || U_FAILURE(*status)){
+ return -1;
+ }
+ if(cnv == NULL){
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return -1;
+ }
+
+ if(cnv->preToULength > 0){
+ return cnv->preToULength ;
+ }else if(cnv->preToULength < 0){
+ return -cnv->preToULength;
+ }else if(cnv->toULength > 0){
+ return cnv->toULength;
+ }
+ return 0;
+}
#endif
/*