]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ucnvscsu.c
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / common / ucnvscsu.c
index e02f9a7008a7b7089b2302a3cb4cb3c0e0d2b308..1211da7a9b3f3af401cac3c1d007fb311ed93513 100644 (file)
@@ -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(b<gapThreshold) {
                     scsu->toUDynamicOffsets[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(b<gapThreshold) {
                     scsu->toUDynamicOffsets[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