X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b75a7d8f3b4adbae880cab104ce2c6a50eee4db2..9d88c94317aeac5dd26c1dbe8c2112dbe855d2b5:/icuSources/common/ucnvscsu.c diff --git a/icuSources/common/ucnvscsu.c b/icuSources/common/ucnvscsu.c index e02f9a70..1211da7a 100644 --- a/icuSources/common/ucnvscsu.c +++ b/icuSources/common/ucnvscsu.c @@ -1,7 +1,7 @@ /* ****************************************************************************** * -* Copyright (C) 2000-2003, International Business Machines +* Copyright (C) 2000-2004, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -20,6 +20,9 @@ */ #include "unicode/utypes.h" + +#if !UCONFIG_NO_CONVERSION + #include "unicode/ucnv.h" #include "unicode/ucnv_cb.h" #include "ucnv_bld.h" @@ -181,7 +184,7 @@ _SCSUReset(UConverter *cnv, UConverterResetChoice choice) { break; } - cnv->fromUSurrogateLead=0; + cnv->fromUChar32=0; } } @@ -216,8 +219,6 @@ _SCSUClose(UConverter *cnv) { /* SCSU-to-Unicode conversion functions ------------------------------------- */ -/* ### TODO check operator precedence | << + < */ - static void _SCSUToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, UErrorCode *pErrorCode) { @@ -272,11 +273,9 @@ _SCSUToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, * 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) { @@ -367,13 +366,20 @@ singleByteMode: 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: @@ -426,6 +432,8 @@ singleByteMode: 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: @@ -436,10 +444,9 @@ singleByteMode: 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(btoUDynamicOffsets[dynamicWindow]=b<<7UL; } else if((uint8_t)(b-gapThreshold)<(reservedStart-gapThreshold)) { @@ -448,10 +455,9 @@ singleByteMode: 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; @@ -487,6 +493,8 @@ fastUnicode: 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); @@ -496,23 +504,32 @@ fastUnicode: } 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: @@ -528,80 +545,25 @@ fastUnicode: } 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; - } } /* @@ -619,7 +581,6 @@ _SCSUToUnicode(UConverterToUnicodeArgs *pArgs, const uint8_t *source, *sourceLimit; UChar *target; const UChar *targetLimit; - UBool isSingleByteMode; uint8_t state, byteOne; int8_t quoteWindow, dynamicWindow; @@ -658,11 +619,9 @@ _SCSUToUnicode(UConverterToUnicodeArgs *pArgs, * 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) { @@ -731,13 +690,20 @@ singleByteMode: 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: @@ -772,6 +738,8 @@ singleByteMode: 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: @@ -781,10 +749,9 @@ singleByteMode: 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(btoUDynamicOffsets[dynamicWindow]=b<<7UL; } else if((uint8_t)(b-gapThreshold)<(reservedStart-gapThreshold)) { @@ -793,10 +760,9 @@ singleByteMode: 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; @@ -825,6 +791,8 @@ fastUnicode: 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); @@ -833,23 +801,32 @@ fastUnicode: } 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: @@ -861,80 +838,24 @@ fastUnicode: } 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 ----------------------------------- */ @@ -1095,7 +1016,6 @@ _SCSUFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, int32_t sourceIndex, nextSourceIndex; - uint32_t i; int32_t length; /* variables for compression heuristics */ @@ -1120,7 +1040,7 @@ _SCSUFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, 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; @@ -1188,7 +1108,8 @@ getTrailSingle: } 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 */ @@ -1197,7 +1118,8 @@ getTrailSingle: } 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 */ @@ -1383,7 +1305,8 @@ getTrailUnicode: } 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 */ @@ -1392,7 +1315,8 @@ getTrailUnicode: } else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */ - goto callback; + *pErrorCode=U_ILLEGAL_CHAR_FOUND; + goto endloop; } /* compress supplementary character */ @@ -1443,22 +1367,12 @@ getTrailUnicode: } 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; @@ -1566,59 +1480,6 @@ outputBytes: 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; - } } /* @@ -1643,7 +1504,6 @@ _SCSUFromUnicode(UConverterFromUnicodeArgs *pArgs, uint32_t c, delta; - uint32_t i; int32_t length; /* variables for compression heuristics */ @@ -1667,7 +1527,7 @@ _SCSUFromUnicode(UConverterFromUnicodeArgs *pArgs, dynamicWindow=scsu->fromUDynamicWindow; currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]; - c=cnv->fromUSurrogateLead; + c=cnv->fromUChar32; /* similar conversion "loop" as in toUnicode */ loop: @@ -1720,7 +1580,8 @@ getTrailSingle: } 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 */ @@ -1729,7 +1590,8 @@ getTrailSingle: } 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 */ @@ -1902,7 +1764,8 @@ getTrailUnicode: } 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 */ @@ -1911,7 +1774,8 @@ getTrailUnicode: } else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */ - goto callback; + *pErrorCode=U_ILLEGAL_CHAR_FOUND; + goto endloop; } /* compress supplementary character */ @@ -1961,22 +1825,12 @@ getTrailUnicode: } 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; @@ -2052,54 +1906,6 @@ outputBytes: 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 ------------------------------------------------------------ */ @@ -2141,7 +1947,7 @@ _SCSUWriteSub(UConverterFromUnicodeArgs *pArgs, } /* structure for SafeClone calculations */ -struct cloneStruct +struct cloneSCSUStruct { UConverter cnv; SCSUData mydata; @@ -2153,8 +1959,8 @@ _SCSUSafeClone(const UConverter *cnv, 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; @@ -2165,9 +1971,8 @@ _SCSUSafeClone(const UConverter *cnv, 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; @@ -2177,9 +1982,6 @@ _SCSUSafeClone(const UConverter *cnv, } - - - static const UConverterImpl _SCSUImpl={ UCNV_SCSU, @@ -2194,7 +1996,7 @@ static const UConverterImpl _SCSUImpl={ _SCSUToUnicodeWithOffsets, _SCSUFromUnicode, _SCSUFromUnicodeWithOffsets, - _SCSUGetNextUChar, + NULL, NULL, _SCSUGetName, @@ -2209,7 +2011,13 @@ static const UConverterStaticData _SCSUStaticData={ 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, @@ -2222,4 +2030,4 @@ const UConverterSharedData _SCSUData={ 0 }; -/* ### clarify: if an error occurs, does a converter reset itself? or is it in a defined or undefined state? */ +#endif