/*
******************************************************************************
*
-* Copyright (C) 2000-2003, International Business Machines
+* Copyright (C) 2000-2009, 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;
}
}
static void
_SCSUOpen(UConverter *cnv,
- const char *name,
- const char *locale,
- uint32_t options,
+ UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
+ const char *locale=pArgs->locale;
+ if(pArgs->onlyTestIsLoadable) {
+ return;
+ }
cnv->extraInfo=uprv_malloc(sizeof(SCSUData));
if(cnv->extraInfo!=NULL) {
if(locale!=NULL && locale[0]=='j' && locale[1]=='a' && (locale[2]==0 || locale[2]=='_')) {
} else {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
}
+
+ /* Set the substitution character U+fffd as a Unicode string. */
+ cnv->subUChars[0]=0xfffd;
+ cnv->subCharLen=-1;
}
static void
/* 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;
* first to the overflow buffer what does not fit into the
* regular target.
*/
- /* we know that 1<=targetCapacity<length<=4 */
+ /* we know that 0<=targetCapacity<length<=4 */
+ /* targetCapacity==0 when SCU+supplementary where SCU used up targetCapacity==1 */
length-=targetCapacity;
p=(uint8_t *)cnv->charErrorBuffer;
switch(length) {
/* each branch falls through to the next one */
+ case 4:
+ *p++=(uint8_t)(c>>24);
case 3:
*p++=(uint8_t)(c>>16);
case 2:
*offsets++=sourceIndex;
}
default:
- /* will never occur */
break;
}
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;
* first to the overflow buffer what does not fit into the
* regular target.
*/
- /* we know that 1<=targetCapacity<length<=4 */
+ /* we know that 0<=targetCapacity<length<=4 */
+ /* targetCapacity==0 when SCU+supplementary where SCU used up targetCapacity==1 */
length-=targetCapacity;
p=(uint8_t *)cnv->charErrorBuffer;
switch(length) {
/* each branch falls through to the next one */
+ case 4:
+ *p++=(uint8_t)(c>>24);
case 3:
*p++=(uint8_t)(c>>16);
case 2:
case 1:
*target++=(uint8_t)c;
default:
- /* will never occur */
break;
}
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 ------------------------------------------------------------ */
}
}
-static void
-_SCSUWriteSub(UConverterFromUnicodeArgs *pArgs,
- int32_t offsetIndex,
- UErrorCode *pErrorCode) {
- static const char squ_fffd[]={ (char)SQU, (char)0xffu, (char)0xfdu };
-
- /*
- * The substitution character is U+fffd={ ff, fd }.
- * If the SCSU converter is in Unicode mode, then these two bytes just need to
- * be written. Otherwise, this character is quoted.
- */
- if(((SCSUData *)pArgs->converter->extraInfo)->fromUIsSingleByteMode) {
- /* single-byte mode: quote Unicode */
- ucnv_cbFromUWriteBytes(pArgs,
- squ_fffd, 3,
- offsetIndex, pErrorCode);
- } else {
- /* Unicode mode: just write U+fffd */
- ucnv_cbFromUWriteBytes(pArgs,
- squ_fffd+1, 2,
- offsetIndex, pErrorCode);
- }
-}
-
/* 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,
- _SCSUWriteSub,
+ NULL,
_SCSUSafeClone,
ucnv_getCompleteUnicodeSet
};
static const UConverterStaticData _SCSUStaticData={
sizeof(UConverterStaticData),
"SCSU",
- 0, /* CCSID for SCSU */
+ 1212, /* 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! */
+ /*
+ * The subchar here is ignored because _SCSUOpen() sets U+fffd as a Unicode
+ * substitution string.
+ */
+ { 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