/*
******************************************************************************
*
-* Copyright (C) 2000-2003, International Business Machines
+* Copyright (C) 2000-2004, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
*/
#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_CONVERSION
+
#include "unicode/ucnv.h"
#include "unicode/ucnv_cb.h"
#include "ucnv_bld.h"
break;
}
- cnv->fromUSurrogateLead=0;
+ cnv->fromUChar32=0;
}
}
/* SCSU-to-Unicode conversion functions ------------------------------------- */
-/* ### TODO check operator precedence | << + < */
-
static void
_SCSUToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
UErrorCode *pErrorCode) {
* The end of the input or output buffer is also handled by the slower loop.
* The slow loop jumps (goto) to the fast-path loop again as soon as possible.
*
- * The callback handling is done by jumping (goto) to the callback section at the end
- * of the function. From there, it either jumps to here to continue or to
- * the endloop section to clean up and return.
+ * The callback handling is done by returning with an error code.
+ * The conversion framework actually calls the callback function.
*/
-loop:
if(isSingleByteMode) {
/* fast path for single-byte mode */
if(state==readCommand) {
goto fastUnicode;
} else /* Srs */ {
/* callback(illegal) */
- cnv->invalidCharBuffer[0]=b;
- cnv->invalidCharLength=1;
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
+ goto endloop;
}
+
+ /* store the first byte of a multibyte sequence in toUBytes[] */
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
break;
case quotePairOne:
byteOne=b;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=quotePairTwo;
break;
case quotePairTwo:
case definePairOne:
dynamicWindow=(int8_t)((b>>5)&7);
byteOne=(uint8_t)(b&0x1f);
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=definePairTwo;
break;
case definePairTwo:
case defineOne:
if(b==0) {
/* callback(illegal): Reserved window offset value 0 */
- cnv->invalidCharBuffer[0]=(char)(SD0+dynamicWindow);
- cnv->invalidCharBuffer[1]=b;
- cnv->invalidCharLength=2;
- goto callback;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
+ goto endloop;
} else if(b<gapThreshold) {
scsu->toUDynamicOffsets[dynamicWindow]=b<<7UL;
} else if((uint8_t)(b-gapThreshold)<(reservedStart-gapThreshold)) {
scsu->toUDynamicOffsets[dynamicWindow]=fixedOffsets[b-fixedThreshold];
} else {
/* callback(illegal): Reserved window offset value 0xa8..0xf8 */
- cnv->invalidCharBuffer[0]=(char)(SD0+dynamicWindow);
- cnv->invalidCharBuffer[1]=b;
- cnv->invalidCharLength=2;
- goto callback;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
+ goto endloop;
}
sourceIndex=nextSourceIndex;
state=readCommand;
case readCommand:
if((uint8_t)(b-UC0)>(Urs-UC0)) {
byteOne=b;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=quotePairTwo;
} else if(/* UC0<=b && */ b<=UC7) {
dynamicWindow=(int8_t)(b-UC0);
} else if(/* UD0<=b && */ b<=UD7) {
dynamicWindow=(int8_t)(b-UD0);
isSingleByteMode=TRUE;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=defineOne;
goto singleByteMode;
} else if(b==UDX) {
isSingleByteMode=TRUE;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=definePairOne;
goto singleByteMode;
} else if(b==UQU) {
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=quotePairOne;
} else /* Urs */ {
/* callback(illegal) */
- cnv->invalidCharBuffer[0]=b;
- cnv->invalidCharLength=1;
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
+ goto endloop;
}
break;
case quotePairOne:
byteOne=b;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=quotePairTwo;
break;
case quotePairTwo:
}
endloop:
- if(pArgs->flush && source>=sourceLimit) {
- /* reset the state for the next conversion */
- if(state!=readCommand && U_SUCCESS(*pErrorCode)) {
- /* a character byte sequence remains incomplete */
- *pErrorCode=U_TRUNCATED_CHAR_FOUND;
- }
- _SCSUReset(cnv, UCNV_RESET_TO_UNICODE);
- } else {
- /* set the converter state back into UConverter */
- scsu->toUIsSingleByteMode=isSingleByteMode;
- scsu->toUState=state;
- scsu->toUQuoteWindow=quoteWindow;
- scsu->toUDynamicWindow=dynamicWindow;
- scsu->toUByteOne=byteOne;
+ /* set the converter state back into UConverter */
+ if(U_FAILURE(*pErrorCode) && *pErrorCode!=U_BUFFER_OVERFLOW_ERROR) {
+ /* reset to deal with the next character */
+ state=readCommand;
+ } else if(state==readCommand) {
+ /* not in a multi-byte sequence, reset toULength */
+ cnv->toULength=0;
}
+ scsu->toUIsSingleByteMode=isSingleByteMode;
+ scsu->toUState=state;
+ scsu->toUQuoteWindow=quoteWindow;
+ scsu->toUDynamicWindow=dynamicWindow;
+ scsu->toUByteOne=byteOne;
-finish:
/* write back the updated pointers */
pArgs->source=(const char *)source;
pArgs->target=target;
pArgs->offsets=offsets;
return;
-
-callback:
- /* call the callback function with all the preparations and post-processing */
- /* update the arguments structure */
- pArgs->source=(const char *)source;
- pArgs->target=target;
- pArgs->offsets=offsets;
- /* the current bytes were copied to invalidCharBuffer before the goto callback jump */
-
- /* set the converter state in UConverter to deal with the next character */
- scsu->toUIsSingleByteMode=isSingleByteMode;
- scsu->toUState=readCommand;
- scsu->toUQuoteWindow=quoteWindow;
- scsu->toUDynamicWindow=dynamicWindow;
- scsu->toUByteOne=0;
-
- /* call the callback function */
- *pErrorCode=U_ILLEGAL_CHAR_FOUND;
- cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs, cnv->invalidCharBuffer, cnv->invalidCharLength, UCNV_ILLEGAL, pErrorCode);
-
- /* get the converter state from UConverter */
- isSingleByteMode=scsu->toUIsSingleByteMode;
- state=scsu->toUState;
- quoteWindow=scsu->toUQuoteWindow;
- dynamicWindow=scsu->toUDynamicWindow;
- byteOne=scsu->toUByteOne;
-
- /* update target and deal with offsets if necessary */
- offsets=ucnv_updateCallbackOffsets(offsets, (int32_t)(pArgs->target-target), sourceIndex);
- target=pArgs->target;
-
- /* update the source pointer and index */
- sourceIndex=(int32_t)(nextSourceIndex+((const uint8_t *)pArgs->source-source));
- source=(const uint8_t *)pArgs->source;
-
- /*
- * If the callback overflowed the target, then we need to
- * stop here with an overflow indication.
- */
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- goto endloop;
- } else if(cnv->UCharErrorBufferLength>0) {
- /* target is full */
- *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
- goto endloop;
- } else if(U_FAILURE(*pErrorCode)) {
- /* break on error */
- _SCSUReset(cnv, UCNV_RESET_TO_UNICODE);
- goto finish;
- } else {
- goto loop;
- }
}
/*
const uint8_t *source, *sourceLimit;
UChar *target;
const UChar *targetLimit;
-
UBool isSingleByteMode;
uint8_t state, byteOne;
int8_t quoteWindow, dynamicWindow;
* The end of the input or output buffer is also handled by the slower loop.
* The slow loop jumps (goto) to the fast-path loop again as soon as possible.
*
- * The callback handling is done by jumping (goto) to the callback section at the end
- * of the function. From there, it either jumps to here to continue or to
- * the endloop section to clean up and return.
+ * The callback handling is done by returning with an error code.
+ * The conversion framework actually calls the callback function.
*/
-loop:
if(isSingleByteMode) {
/* fast path for single-byte mode */
if(state==readCommand) {
goto fastUnicode;
} else /* Srs */ {
/* callback(illegal) */
- cnv->invalidCharBuffer[0]=b;
- cnv->invalidCharLength=1;
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
+ goto endloop;
}
+
+ /* store the first byte of a multibyte sequence in toUBytes[] */
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
break;
case quotePairOne:
byteOne=b;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=quotePairTwo;
break;
case quotePairTwo:
case definePairOne:
dynamicWindow=(int8_t)((b>>5)&7);
byteOne=(uint8_t)(b&0x1f);
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=definePairTwo;
break;
case definePairTwo:
case defineOne:
if(b==0) {
/* callback(illegal): Reserved window offset value 0 */
- cnv->invalidCharBuffer[0]=(char)(SD0+dynamicWindow);
- cnv->invalidCharBuffer[1]=b;
- cnv->invalidCharLength=2;
- goto callback;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
+ goto endloop;
} else if(b<gapThreshold) {
scsu->toUDynamicOffsets[dynamicWindow]=b<<7UL;
} else if((uint8_t)(b-gapThreshold)<(reservedStart-gapThreshold)) {
scsu->toUDynamicOffsets[dynamicWindow]=fixedOffsets[b-fixedThreshold];
} else {
/* callback(illegal): Reserved window offset value 0xa8..0xf8 */
- cnv->invalidCharBuffer[0]=(char)(SD0+dynamicWindow);
- cnv->invalidCharBuffer[1]=b;
- cnv->invalidCharLength=2;
- goto callback;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
+ goto endloop;
}
state=readCommand;
goto fastSingle;
case readCommand:
if((uint8_t)(b-UC0)>(Urs-UC0)) {
byteOne=b;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=quotePairTwo;
} else if(/* UC0<=b && */ b<=UC7) {
dynamicWindow=(int8_t)(b-UC0);
} else if(/* UD0<=b && */ b<=UD7) {
dynamicWindow=(int8_t)(b-UD0);
isSingleByteMode=TRUE;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=defineOne;
goto singleByteMode;
} else if(b==UDX) {
isSingleByteMode=TRUE;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=definePairOne;
goto singleByteMode;
} else if(b==UQU) {
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
state=quotePairOne;
} else /* Urs */ {
/* callback(illegal) */
- cnv->invalidCharBuffer[0]=b;
- cnv->invalidCharLength=1;
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ cnv->toUBytes[0]=b;
+ cnv->toULength=1;
+ goto endloop;
}
break;
case quotePairOne:
byteOne=b;
+ cnv->toUBytes[1]=b;
+ cnv->toULength=2;
state=quotePairTwo;
break;
case quotePairTwo:
}
endloop:
- if(pArgs->flush && source>=sourceLimit) {
- /* reset the state for the next conversion */
- if(state!=readCommand && U_SUCCESS(*pErrorCode)) {
- /* a character byte sequence remains incomplete */
- *pErrorCode=U_TRUNCATED_CHAR_FOUND;
- }
- _SCSUReset(cnv, UCNV_RESET_TO_UNICODE);
- } else {
- /* set the converter state back into UConverter */
- scsu->toUIsSingleByteMode=isSingleByteMode;
- scsu->toUState=state;
- scsu->toUQuoteWindow=quoteWindow;
- scsu->toUDynamicWindow=dynamicWindow;
- scsu->toUByteOne=byteOne;
+ /* set the converter state back into UConverter */
+ if(U_FAILURE(*pErrorCode) && *pErrorCode!=U_BUFFER_OVERFLOW_ERROR) {
+ /* reset to deal with the next character */
+ state=readCommand;
+ } else if(state==readCommand) {
+ /* not in a multi-byte sequence, reset toULength */
+ cnv->toULength=0;
}
+ scsu->toUIsSingleByteMode=isSingleByteMode;
+ scsu->toUState=state;
+ scsu->toUQuoteWindow=quoteWindow;
+ scsu->toUDynamicWindow=dynamicWindow;
+ scsu->toUByteOne=byteOne;
-finish:
/* write back the updated pointers */
pArgs->source=(const char *)source;
pArgs->target=target;
return;
-
-callback:
- /* call the callback function with all the preparations and post-processing */
- /* update the arguments structure */
- pArgs->source=(const char *)source;
- pArgs->target=target;
- /* the current bytes were copied to invalidCharBuffer before the goto callback jump */
-
- /* set the converter state in UConverter to deal with the next character */
- scsu->toUIsSingleByteMode=isSingleByteMode;
- scsu->toUState=readCommand;
- scsu->toUQuoteWindow=quoteWindow;
- scsu->toUDynamicWindow=dynamicWindow;
- scsu->toUByteOne=0;
-
- /* call the callback function */
- *pErrorCode=U_ILLEGAL_CHAR_FOUND;
- cnv->fromCharErrorBehaviour(cnv->toUContext, pArgs, cnv->invalidCharBuffer, cnv->invalidCharLength, UCNV_ILLEGAL, pErrorCode);
-
- /* get the converter state from UConverter */
- isSingleByteMode=scsu->toUIsSingleByteMode;
- state=scsu->toUState;
- quoteWindow=scsu->toUQuoteWindow;
- dynamicWindow=scsu->toUDynamicWindow;
- byteOne=scsu->toUByteOne;
-
- target=pArgs->target;
-
- source=(const uint8_t *)pArgs->source;
-
- /*
- * If the callback overflowed the target, then we need to
- * stop here with an overflow indication.
- */
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- goto endloop;
- } else if(cnv->UCharErrorBufferLength>0) {
- /* target is full */
- *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
- goto endloop;
- } else if(U_FAILURE(*pErrorCode)) {
- /* break on error */
- _SCSUReset(cnv, UCNV_RESET_TO_UNICODE);
- goto finish;
- } else {
- goto loop;
- }
-}
-
-static UChar32
-_SCSUGetNextUChar(UConverterToUnicodeArgs *pArgs,
- UErrorCode *pErrorCode) {
- return ucnv_getNextUCharFromToUImpl(pArgs, _SCSUToUnicode, TRUE, pErrorCode);
}
/* SCSU-from-Unicode conversion functions ----------------------------------- */
int32_t sourceIndex, nextSourceIndex;
- uint32_t i;
int32_t length;
/* variables for compression heuristics */
dynamicWindow=scsu->fromUDynamicWindow;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
- c=cnv->fromUSurrogateLead;
+ c=cnv->fromUChar32;
/* sourceIndex=-1 if the current character began in the previous buffer */
sourceIndex= c==0 ? 0 : -1;
} else {
/* this is an unmatched lead code unit (1st surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
} else {
/* no more input */
} else {
/* this is an unmatched trail code unit (2nd surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
/* compress supplementary character U+10000..U+10ffff */
} else {
/* this is an unmatched lead code unit (1st surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
} else {
/* no more input */
} else {
/* this is an unmatched trail code unit (2nd surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
/* compress supplementary character */
}
endloop:
- if(pArgs->flush && source>=sourceLimit) {
- /* reset the state for the next conversion */
- if(c!=0 && U_SUCCESS(*pErrorCode)) {
- /* a character byte sequence remains incomplete */
- *pErrorCode=U_TRUNCATED_CHAR_FOUND;
- }
- _SCSUReset(cnv, UCNV_RESET_FROM_UNICODE);
- } else {
- /* set the converter state back into UConverter */
- scsu->fromUIsSingleByteMode=isSingleByteMode;
- scsu->fromUDynamicWindow=dynamicWindow;
+ /* set the converter state back into UConverter */
+ scsu->fromUIsSingleByteMode=isSingleByteMode;
+ scsu->fromUDynamicWindow=dynamicWindow;
- cnv->fromUSurrogateLead=(UChar)c;
- }
+ cnv->fromUChar32=c;
-finish:
/* write back the updated pointers */
pArgs->source=source;
pArgs->target=(char *)target;
c=0;
goto endloop;
}
-
-callback:
- /* call the callback function with all the preparations and post-processing */
- /* update the arguments structure */
- pArgs->source=source;
- pArgs->target=(char *)target;
- pArgs->offsets=offsets;
- /* set the converter state in UConverter to deal with the next character */
- scsu->fromUIsSingleByteMode=isSingleByteMode;
- scsu->fromUDynamicWindow=dynamicWindow;
- cnv->fromUSurrogateLead=0;
-
- /* write the code point as code units */
- i=0;
- UTF_APPEND_CHAR_UNSAFE(cnv->invalidUCharBuffer, i, c);
- cnv->invalidUCharLength=(int8_t)i;
-
- /* call the callback function */
- *pErrorCode=U_ILLEGAL_CHAR_FOUND;
- cnv->fromUCharErrorBehaviour(cnv->fromUContext, pArgs, cnv->invalidUCharBuffer, i, c, UCNV_ILLEGAL, pErrorCode);
-
- /* get the converter state from UConverter */
- isSingleByteMode=scsu->fromUIsSingleByteMode;
- dynamicWindow=scsu->fromUDynamicWindow;
- currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
- c=cnv->fromUSurrogateLead;
-
- /* update target and deal with offsets if necessary */
- offsets=ucnv_updateCallbackOffsets(offsets, (int32_t)(((uint8_t *)pArgs->target)-target), sourceIndex);
- target=(uint8_t *)pArgs->target;
-
- /* update the source pointer and index */
- sourceIndex=(int32_t)(nextSourceIndex+(pArgs->source-source));
- source=pArgs->source;
- targetCapacity=(int32_t)((uint8_t *)pArgs->targetLimit-target);
-
- /*
- * If the callback overflowed the target, then we need to
- * stop here with an overflow indication.
- */
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- goto endloop;
- } else if(cnv->charErrorBufferLength>0) {
- /* target is full */
- *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
- goto endloop;
- } else if(U_FAILURE(*pErrorCode)) {
- /* break on error */
- _SCSUReset(cnv, UCNV_RESET_FROM_UNICODE);
- goto finish;
- } else {
- goto loop;
- }
}
/*
uint32_t c, delta;
- uint32_t i;
int32_t length;
/* variables for compression heuristics */
dynamicWindow=scsu->fromUDynamicWindow;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
- c=cnv->fromUSurrogateLead;
+ c=cnv->fromUChar32;
/* similar conversion "loop" as in toUnicode */
loop:
} else {
/* this is an unmatched lead code unit (1st surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
} else {
/* no more input */
} else {
/* this is an unmatched trail code unit (2nd surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
/* compress supplementary character U+10000..U+10ffff */
} else {
/* this is an unmatched lead code unit (1st surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
} else {
/* no more input */
} else {
/* this is an unmatched trail code unit (2nd surrogate) */
/* callback(illegal) */
- goto callback;
+ *pErrorCode=U_ILLEGAL_CHAR_FOUND;
+ goto endloop;
}
/* compress supplementary character */
}
endloop:
- if(pArgs->flush && source>=sourceLimit) {
- /* reset the state for the next conversion */
- if(c!=0 && U_SUCCESS(*pErrorCode)) {
- /* a character byte sequence remains incomplete */
- *pErrorCode=U_TRUNCATED_CHAR_FOUND;
- }
- _SCSUReset(cnv, UCNV_RESET_FROM_UNICODE);
- } else {
- /* set the converter state back into UConverter */
- scsu->fromUIsSingleByteMode=isSingleByteMode;
- scsu->fromUDynamicWindow=dynamicWindow;
+ /* set the converter state back into UConverter */
+ scsu->fromUIsSingleByteMode=isSingleByteMode;
+ scsu->fromUDynamicWindow=dynamicWindow;
- cnv->fromUSurrogateLead=(UChar)c;
- }
+ cnv->fromUChar32=c;
-finish:
/* write back the updated pointers */
pArgs->source=source;
pArgs->target=(char *)target;
c=0;
goto endloop;
}
-
-callback:
- /* call the callback function with all the preparations and post-processing */
- /* update the arguments structure */
- pArgs->source=source;
- pArgs->target=(char *)target;
- /* set the converter state in UConverter to deal with the next character */
- scsu->fromUIsSingleByteMode=isSingleByteMode;
- scsu->fromUDynamicWindow=dynamicWindow;
- cnv->fromUSurrogateLead=0;
-
- /* write the code point as code units */
- i=0;
- UTF_APPEND_CHAR_UNSAFE(cnv->invalidUCharBuffer, i, c);
- cnv->invalidUCharLength=(int8_t)i;
-
- /* call the callback function */
- *pErrorCode=U_ILLEGAL_CHAR_FOUND;
- cnv->fromUCharErrorBehaviour(cnv->fromUContext, pArgs, cnv->invalidUCharBuffer, i, c, UCNV_ILLEGAL, pErrorCode);
-
- /* get the converter state from UConverter */
- isSingleByteMode=scsu->fromUIsSingleByteMode;
- dynamicWindow=scsu->fromUDynamicWindow;
- currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
- c=cnv->fromUSurrogateLead;
-
- target=(uint8_t *)pArgs->target;
-
- source=pArgs->source;
- targetCapacity=(int32_t)((uint8_t *)pArgs->targetLimit-target);
-
- /*
- * If the callback overflowed the target, then we need to
- * stop here with an overflow indication.
- */
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- goto endloop;
- } else if(cnv->charErrorBufferLength>0) {
- /* target is full */
- *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
- goto endloop;
- } else if(U_FAILURE(*pErrorCode)) {
- /* break on error */
- _SCSUReset(cnv, UCNV_RESET_FROM_UNICODE);
- goto finish;
- } else {
- goto loop;
- }
}
/* miscellaneous ------------------------------------------------------------ */
}
/* structure for SafeClone calculations */
-struct cloneStruct
+struct cloneSCSUStruct
{
UConverter cnv;
SCSUData mydata;
int32_t *pBufferSize,
UErrorCode *status)
{
- struct cloneStruct * localClone;
- int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
+ struct cloneSCSUStruct * localClone;
+ int32_t bufferSizeNeeded = sizeof(struct cloneSCSUStruct);
if (U_FAILURE(*status)){
return 0;
return 0;
}
- localClone = (struct cloneStruct *)stackBuffer;
- uprv_memcpy(&localClone->cnv, cnv, sizeof(UConverter));
- localClone->cnv.isCopyLocal = TRUE;
+ localClone = (struct cloneSCSUStruct *)stackBuffer;
+ /* ucnv.c/ucnv_safeClone() copied the main UConverter already */
uprv_memcpy(&localClone->mydata, cnv->extraInfo, sizeof(SCSUData));
localClone->cnv.extraInfo = &localClone->mydata;
}
-
-
-
static const UConverterImpl _SCSUImpl={
UCNV_SCSU,
_SCSUToUnicodeWithOffsets,
_SCSUFromUnicode,
_SCSUFromUnicodeWithOffsets,
- _SCSUGetNextUChar,
+ NULL,
NULL,
_SCSUGetName,
0, /* CCSID for SCSU */
UCNV_IBM, UCNV_SCSU,
1, 3, /* one UChar generates at least 1 byte and at most 3 bytes */
- { 0x0e, 0xff, 0xfd, 0 }, 3, /* ### the subchar really must be written by an SCSU function! */
+ /*
+ * ### TODO the subchar really must be written by an SCSU function
+ * however, currently SCSU's fromUnicode() never causes errors, therefore
+ * no callbacks will be called and no subchars written
+ * See Jitterbug 2837 - RFE: forbid converting surrogate code points in all charsets
+ */
+ { 0x0e, 0xff, 0xfd, 0 }, 3,
FALSE, FALSE,
0,
0,
0
};
-/* ### clarify: if an error occurs, does a converter reset itself? or is it in a defined or undefined state? */
+#endif