f4b79b2e20
X-SVN-Rev: 3304
717 lines
25 KiB
C
717 lines
25 KiB
C
/*
|
|
**********************************************************************
|
|
* Copyright (C) 2000, International Business Machines
|
|
* Corporation and others. All Rights Reserved.
|
|
**********************************************************************
|
|
* file name: ucnvebcdic.c
|
|
* encoding: US-ASCII
|
|
* tab size: 8 (not used)
|
|
* indentation:4
|
|
*
|
|
* created on: 2000Aug29
|
|
* created by: Ram Viswanadha
|
|
*
|
|
* Change history:
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "unicode/utypes.h"
|
|
#include "unicode/ucnv.h"
|
|
#include "unicode/ucnv_err.h"
|
|
#include "unicode/ucnv_cb.h"
|
|
#include "unicode/ustring.h"
|
|
#include "cmemory.h"
|
|
#include "ucmp16.h"
|
|
#include "ucnv_bld.h"
|
|
#include "ucnv_cnv.h"
|
|
#include "cstring.h"
|
|
|
|
|
|
/* Protos */
|
|
U_CFUNC void T_UConverter_fromUnicode_EBCDIC_STATEFUL(UConverterFromUnicodeArgs * args,
|
|
UErrorCode * err);
|
|
|
|
U_CFUNC void T_UConverter_fromUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args,
|
|
UErrorCode * err);
|
|
|
|
U_CFUNC void T_UConverter_toUnicode_EBCDIC_STATEFUL(UConverterToUnicodeArgs * args,
|
|
UErrorCode * err);
|
|
|
|
U_CFUNC void T_UConverter_toUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC (UConverterToUnicodeArgs * args,
|
|
UErrorCode * err);
|
|
|
|
|
|
U_CFUNC UChar32 T_UConverter_getNextUChar_EBCDIC_STATEFUL (UConverterToUnicodeArgs * args,
|
|
UErrorCode * err);
|
|
|
|
/* Forward declaration */
|
|
|
|
U_CFUNC void
|
|
_DBCSLoad(UConverterSharedData *sharedData, const uint8_t *raw, UErrorCode *pErrorCode);
|
|
|
|
U_CFUNC void
|
|
_DBCSUnload(UConverterSharedData *sharedData);
|
|
|
|
|
|
|
|
|
|
|
|
U_CFUNC void T_UConverter_toUnicode_EBCDIC_STATEFUL (UConverterToUnicodeArgs *args,
|
|
UErrorCode * err)
|
|
{
|
|
char *mySource = (char *) args->source;
|
|
UChar *myTarget = args->target;
|
|
int32_t mySourceIndex = 0;
|
|
int32_t myTargetIndex = 0;
|
|
int32_t targetLength = args->targetLimit - args->target;
|
|
int32_t sourceLength = args->sourceLimit - args->source;
|
|
CompactShortArray *myToUnicode = NULL;
|
|
UChar targetUniChar = 0x0000;
|
|
UChar mySourceChar = 0x0000;
|
|
int32_t myMode = args->converter->mode;
|
|
|
|
myToUnicode = &(args->converter->sharedData->table->dbcs.toUnicode);
|
|
while (mySourceIndex < sourceLength)
|
|
{
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
/*gets the corresponding UniChar */
|
|
mySourceChar = (unsigned char) (args->source[mySourceIndex++]);
|
|
if (mySourceChar == UCNV_SI) myMode = UCNV_SI;
|
|
else if (mySourceChar == UCNV_SO) myMode = UCNV_SO;
|
|
else if ((myMode == UCNV_SO) &&
|
|
(args->converter->toUnicodeStatus == 0x00))
|
|
{
|
|
args->converter->toUnicodeStatus = (unsigned char) mySourceChar;
|
|
}
|
|
else
|
|
{
|
|
/*In case there is a state, we update the source char
|
|
*by concatenating the previous char with the current
|
|
*one
|
|
*/
|
|
if (args->converter->toUnicodeStatus != 0x00)
|
|
{
|
|
mySourceChar |= (UChar) (args->converter->toUnicodeStatus << 8);
|
|
args->converter->toUnicodeStatus = 0x00;
|
|
}
|
|
else mySourceChar &= 0x00FF;
|
|
|
|
/*gets the corresponding Unicode codepoint */
|
|
targetUniChar = (UChar) ucmp16_getu (myToUnicode, mySourceChar);
|
|
|
|
/*writing the UniChar to the output stream */
|
|
if (targetUniChar < 0xfffe)
|
|
{
|
|
/*writes the UniChar to the output stream */
|
|
args->target[myTargetIndex++] = targetUniChar;
|
|
}
|
|
|
|
else
|
|
{
|
|
const char* saveSource = args->source;
|
|
UChar* saveTarget = args->target;
|
|
int32_t *saveOffsets = args->offsets;
|
|
UConverterCallbackReason reason;
|
|
|
|
if (targetUniChar == 0xfffe)
|
|
{
|
|
reason = UCNV_UNASSIGNED;
|
|
*err = U_INVALID_CHAR_FOUND;
|
|
}
|
|
else
|
|
{
|
|
reason = UCNV_ILLEGAL;
|
|
*err = U_ILLEGAL_CHAR_FOUND;
|
|
}
|
|
|
|
if (mySourceChar > 0xff)
|
|
{
|
|
args->converter->invalidCharLength = 2;
|
|
args->converter->invalidCharBuffer[0] = (char) (mySourceChar >> 8);
|
|
args->converter->invalidCharBuffer[1] = (char) mySourceChar;
|
|
}
|
|
else
|
|
{
|
|
args->converter->invalidCharLength = 1;
|
|
args->converter->invalidCharBuffer[0] = (char) mySourceChar;
|
|
}
|
|
args->converter->mode = myMode;
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
ToU_CALLBACK_MACRO(args->converter->toUContext,
|
|
args,
|
|
args->converter->invalidCharBuffer,
|
|
args->converter->invalidCharLength,
|
|
reason,
|
|
err);
|
|
|
|
myMode = args->converter->mode;
|
|
args->source = saveSource;
|
|
args->target = saveTarget;
|
|
args->offsets = saveOffsets;
|
|
myMode = args->converter->mode;
|
|
if (U_FAILURE (*err)) break;
|
|
args->converter->invalidCharLength = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*If at the end of conversion we are still carrying state information
|
|
*flush is TRUE, we can deduce that the input stream is truncated
|
|
*/
|
|
if (args->converter->toUnicodeStatus
|
|
&& (mySourceIndex == sourceLength)
|
|
&& (args->flush == TRUE))
|
|
{
|
|
if (U_SUCCESS(*err))
|
|
{
|
|
*err = U_TRUNCATED_CHAR_FOUND;
|
|
args->converter->toUnicodeStatus = 0x00;
|
|
}
|
|
}
|
|
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
args->converter->mode = myMode;
|
|
|
|
return;
|
|
}
|
|
|
|
U_CFUNC void T_UConverter_toUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC (UConverterToUnicodeArgs * args,
|
|
UErrorCode * err)
|
|
{
|
|
char *mySource = (char *) args->source;
|
|
UChar *myTarget = args->target;
|
|
int32_t mySourceIndex = 0;
|
|
int32_t myTargetIndex = 0;
|
|
int32_t targetLength = args->targetLimit - args->target;
|
|
int32_t sourceLength = args->sourceLimit - args->source;
|
|
CompactShortArray *myToUnicode = NULL;
|
|
UChar targetUniChar = 0x0000;
|
|
UChar mySourceChar = 0x0000;
|
|
int32_t myMode = args->converter->mode;
|
|
|
|
myToUnicode = &args->converter->sharedData->table->dbcs.toUnicode;
|
|
|
|
while (mySourceIndex < sourceLength)
|
|
{
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
/*gets the corresponding UniChar */
|
|
mySourceChar = (unsigned char) (args->source[mySourceIndex++]);
|
|
if (mySourceChar == UCNV_SI) myMode = UCNV_SI;
|
|
else if (mySourceChar == UCNV_SO) myMode = UCNV_SO;
|
|
else if ((myMode == UCNV_SO) &&
|
|
(args->converter->toUnicodeStatus == 0x00))
|
|
{
|
|
args->converter->toUnicodeStatus = (unsigned char) mySourceChar;
|
|
}
|
|
else
|
|
{
|
|
/*In case there is a state, we update the source char
|
|
*by concatenating the previous char with the current
|
|
*one
|
|
*/
|
|
if (args->converter->toUnicodeStatus != 0x00)
|
|
{
|
|
mySourceChar |= (UChar) (args->converter->toUnicodeStatus << 8);
|
|
args->converter->toUnicodeStatus = 0x00;
|
|
}
|
|
else mySourceChar &= 0x00FF;
|
|
|
|
/*gets the corresponding Unicode codepoint */
|
|
targetUniChar = (UChar) ucmp16_getu (myToUnicode, mySourceChar);
|
|
|
|
/*writing the UniChar to the output stream */
|
|
if (targetUniChar < 0xfffe)
|
|
{
|
|
/*writes the UniChar to the output stream */
|
|
{
|
|
if(myMode == UCNV_SO)
|
|
args->offsets[myTargetIndex] = mySourceIndex-2; /* double byte */
|
|
else
|
|
args->offsets[myTargetIndex] = mySourceIndex-1; /* single byte */
|
|
}
|
|
args->target[myTargetIndex++] = targetUniChar;
|
|
}
|
|
else
|
|
{
|
|
int32_t currentOffset = args->offsets[myTargetIndex-1] + 2;/* Because mySourceIndex was already incremented */
|
|
int32_t My_i = myTargetIndex;
|
|
const char* saveSource = args->source;
|
|
UChar* saveTarget = args->target;
|
|
int32_t *saveOffsets = args->offsets;
|
|
UConverterCallbackReason reason;
|
|
|
|
if (targetUniChar == 0xfffe)
|
|
{
|
|
reason = UCNV_UNASSIGNED;
|
|
*err = U_INVALID_CHAR_FOUND;
|
|
}
|
|
else
|
|
{
|
|
reason = UCNV_ILLEGAL;
|
|
*err = U_ILLEGAL_CHAR_FOUND;
|
|
}
|
|
|
|
if (mySourceChar > 0xFF)
|
|
{
|
|
args->converter->invalidCharLength = 2;
|
|
args->converter->invalidCharBuffer[0] = (char) (mySourceChar >> 8);
|
|
args->converter->invalidCharBuffer[1] = (char) mySourceChar;
|
|
}
|
|
else
|
|
{
|
|
args->converter->invalidCharLength = 1;
|
|
args->converter->invalidCharBuffer[0] = (char) mySourceChar;
|
|
}
|
|
args->converter->mode = myMode;
|
|
|
|
args->target = args->target + myTargetIndex;
|
|
args->source = args->source + mySourceIndex;
|
|
args->offsets = args->offsets?args->offsets+myTargetIndex:0;
|
|
/* call back handles the offset array */
|
|
ToU_CALLBACK_OFFSETS_LOGIC_MACRO(args->converter->toUContext,
|
|
args,
|
|
args->source,
|
|
1,
|
|
reason,
|
|
err);
|
|
|
|
args->source = saveSource;
|
|
args->target = saveTarget;
|
|
myMode = args->converter->mode;
|
|
if (U_FAILURE (*err)) break;
|
|
args->converter->invalidCharLength = 0;
|
|
myMode = args->converter->mode;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*If at the end of conversion we are still carrying state information
|
|
*flush is TRUE, we can deduce that the input stream is truncated
|
|
*/
|
|
if (args->converter->toUnicodeStatus
|
|
&& (mySourceIndex == sourceLength)
|
|
&& (args->flush == TRUE))
|
|
{
|
|
if (U_SUCCESS(*err))
|
|
{
|
|
*err = U_TRUNCATED_CHAR_FOUND;
|
|
args->converter->toUnicodeStatus = 0x00;
|
|
}
|
|
}
|
|
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
args->converter->mode = myMode;
|
|
|
|
return;
|
|
}
|
|
|
|
U_CFUNC void T_UConverter_fromUnicode_EBCDIC_STATEFUL (UConverterFromUnicodeArgs * args,
|
|
UErrorCode * err)
|
|
|
|
{
|
|
const UChar *mySource = args->source;
|
|
unsigned char *myTarget = (unsigned char *) args->target;
|
|
int32_t mySourceIndex = 0;
|
|
int32_t myTargetIndex = 0;
|
|
int32_t targetLength = args->targetLimit - args->target;
|
|
int32_t sourceLength = args->sourceLimit - args->source;
|
|
CompactShortArray *myFromUnicode = NULL;
|
|
UChar targetUniChar = 0x0000;
|
|
UChar mySourceChar = 0x0000;
|
|
UBool isTargetUCharDBCS = (UBool)args->converter->fromUnicodeStatus;
|
|
UBool oldIsTargetUCharDBCS = isTargetUCharDBCS;
|
|
|
|
myFromUnicode = &args->converter->sharedData->table->dbcs.fromUnicode;
|
|
/*writing the char to the output stream */
|
|
while (mySourceIndex < sourceLength)
|
|
{
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
mySourceChar = (UChar) args->source[mySourceIndex++];
|
|
targetUniChar = (UChar) ucmp16_getu (myFromUnicode, mySourceChar);
|
|
oldIsTargetUCharDBCS = isTargetUCharDBCS;
|
|
|
|
if (targetUniChar != missingCharMarker)
|
|
{
|
|
isTargetUCharDBCS = (UBool)(targetUniChar>0x00FF);
|
|
if (oldIsTargetUCharDBCS != isTargetUCharDBCS)
|
|
{
|
|
if (isTargetUCharDBCS) args->target[myTargetIndex++] = UCNV_SO;
|
|
else args->target[myTargetIndex++] = UCNV_SI;
|
|
|
|
|
|
if ((!isTargetUCharDBCS)&&(myTargetIndex+1 >= targetLength))
|
|
{
|
|
args->converter->charErrorBuffer[args->converter->charErrorBufferLength++] = (char) targetUniChar;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
else if (myTargetIndex+1 >= targetLength)
|
|
{
|
|
args->converter->charErrorBuffer[0] = (char) (targetUniChar >> 8);
|
|
args->converter->charErrorBuffer[1] = (char)(targetUniChar & 0x00FF);
|
|
args->converter->charErrorBufferLength = 2;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (!isTargetUCharDBCS)
|
|
{
|
|
args->target[myTargetIndex++] = (char) targetUniChar;
|
|
}
|
|
else
|
|
{
|
|
args->target[myTargetIndex++] = (char) (targetUniChar >> 8);
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
args->target[myTargetIndex++] = (char) targetUniChar;
|
|
}
|
|
else
|
|
{
|
|
args->converter->charErrorBuffer[0] = (char) targetUniChar;
|
|
args->converter->charErrorBufferLength = 1;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const UChar* saveSource = args->source;
|
|
char* saveTarget = args->target;
|
|
int32_t *saveOffsets = args->offsets;
|
|
|
|
isTargetUCharDBCS = oldIsTargetUCharDBCS;
|
|
*err = U_INVALID_CHAR_FOUND;
|
|
args->converter->invalidUCharBuffer[0] = (UChar) mySourceChar;
|
|
args->converter->invalidUCharLength = 1;
|
|
|
|
args->converter->fromUnicodeStatus = (int32_t)isTargetUCharDBCS;
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
FromU_CALLBACK_MACRO(args->converter->fromUContext,
|
|
args,
|
|
args->converter->invalidUCharBuffer,
|
|
1,
|
|
(UChar32) mySourceChar,
|
|
UCNV_UNASSIGNED,
|
|
err);
|
|
args->source = saveSource;
|
|
args->target = saveTarget;
|
|
args->offsets = saveOffsets;
|
|
isTargetUCharDBCS = (UBool) args->converter->fromUnicodeStatus;
|
|
if (U_FAILURE (*err)) break;
|
|
args->converter->invalidUCharLength = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
|
|
args->converter->fromUnicodeStatus = (int32_t)isTargetUCharDBCS;
|
|
|
|
return;
|
|
}
|
|
|
|
U_CFUNC void T_UConverter_fromUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC (UConverterFromUnicodeArgs * args,
|
|
UErrorCode * err)
|
|
|
|
{
|
|
const UChar *mySource = args->source;
|
|
unsigned char *myTarget = (unsigned char *) args->target;
|
|
int32_t mySourceIndex = 0;
|
|
int32_t myTargetIndex = 0;
|
|
int32_t targetLength = args->targetLimit - args->target;
|
|
int32_t sourceLength = args->sourceLimit - args->source;
|
|
CompactShortArray *myFromUnicode = NULL;
|
|
UChar targetUniChar = 0x0000;
|
|
UChar mySourceChar = 0x0000;
|
|
UBool isTargetUCharDBCS = (UBool)args->converter->fromUnicodeStatus;
|
|
UBool oldIsTargetUCharDBCS = isTargetUCharDBCS;
|
|
|
|
myFromUnicode = &args->converter->sharedData->table->dbcs.fromUnicode;
|
|
/*writing the char to the output stream */
|
|
while (mySourceIndex < sourceLength)
|
|
{
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
mySourceChar = (UChar) args->source[mySourceIndex++];
|
|
targetUniChar = (UChar) ucmp16_getu (myFromUnicode, mySourceChar);
|
|
oldIsTargetUCharDBCS = isTargetUCharDBCS;
|
|
|
|
if (targetUniChar != missingCharMarker)
|
|
{
|
|
isTargetUCharDBCS =(UBool) (targetUniChar>0x00FF);
|
|
if (oldIsTargetUCharDBCS != isTargetUCharDBCS)
|
|
{
|
|
args->offsets[myTargetIndex] = mySourceIndex-1;
|
|
if (isTargetUCharDBCS) args->target[myTargetIndex++] = UCNV_SO;
|
|
else args->target[myTargetIndex++] = UCNV_SI;
|
|
|
|
|
|
if ((!isTargetUCharDBCS)&&(myTargetIndex+1 >= targetLength))
|
|
{
|
|
args->converter->charErrorBuffer[0] = (char) targetUniChar;
|
|
args->converter->charErrorBufferLength = 1;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
else if (myTargetIndex+1 >= targetLength)
|
|
{
|
|
args->converter->charErrorBuffer[0] = (char) (targetUniChar >> 8);
|
|
args->converter->charErrorBuffer[1] = (char) (targetUniChar & 0x00FF);
|
|
args->converter->charErrorBufferLength = 2;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isTargetUCharDBCS)
|
|
{
|
|
args->offsets[myTargetIndex] = mySourceIndex-1;
|
|
args->target[myTargetIndex++] = (char) targetUniChar;
|
|
}
|
|
else
|
|
{
|
|
args->offsets[myTargetIndex] = mySourceIndex-1;
|
|
args->target[myTargetIndex++] = (char) (targetUniChar >> 8);
|
|
if (myTargetIndex < targetLength)
|
|
{
|
|
args->offsets[myTargetIndex] = mySourceIndex-1;
|
|
args->target[myTargetIndex++] = (char) targetUniChar;
|
|
}
|
|
else
|
|
{
|
|
args->converter->charErrorBuffer[0] = (char) targetUniChar;
|
|
args->converter->charErrorBufferLength = 1;
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int32_t currentOffset = args->offsets[myTargetIndex-1]+1;
|
|
char * saveTarget = args->target;
|
|
const UChar* saveSource = args->source;
|
|
int32_t *saveOffsets = args->offsets;
|
|
*err = U_INVALID_CHAR_FOUND;
|
|
args->converter->invalidUCharBuffer[0] = (UChar) mySourceChar;
|
|
args->converter->invalidUCharLength = 1;
|
|
|
|
/* Breaks out of the loop since behaviour was set to stop */
|
|
args->converter->fromUnicodeStatus = (int32_t)isTargetUCharDBCS;
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
args->offsets = args->offsets?args->offsets+myTargetIndex:0;
|
|
FromU_CALLBACK_OFFSETS_LOGIC_MACRO(args->converter->fromUContext,
|
|
args,
|
|
args->converter->invalidUCharBuffer,
|
|
1,
|
|
(UChar32)mySourceChar,
|
|
UCNV_UNASSIGNED,
|
|
err);
|
|
isTargetUCharDBCS = (UBool)(args->converter->fromUnicodeStatus);
|
|
args->source = saveSource;
|
|
args->target = saveTarget;
|
|
args->offsets = saveOffsets;
|
|
isTargetUCharDBCS = (UBool)(args->converter->fromUnicodeStatus);
|
|
if (U_FAILURE (*err)) break;
|
|
args->converter->invalidUCharLength = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*err = U_BUFFER_OVERFLOW_ERROR;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
args->target += myTargetIndex;
|
|
args->source += mySourceIndex;
|
|
|
|
args->converter->fromUnicodeStatus = (int32_t)isTargetUCharDBCS;
|
|
|
|
return;
|
|
}
|
|
|
|
U_CFUNC UChar32 T_UConverter_getNextUChar_EBCDIC_STATEFUL(UConverterToUnicodeArgs* args,
|
|
UErrorCode* err)
|
|
{
|
|
UChar myUChar;
|
|
char const *sourceInitial = args->source;
|
|
/*safe keeps a ptr to the beginning in case we need to step back*/
|
|
|
|
/*Input boundary check*/
|
|
if (args->source >= args->sourceLimit)
|
|
{
|
|
*err = U_INDEX_OUTOFBOUNDS_ERROR;
|
|
return 0xffff;
|
|
}
|
|
|
|
/*Checks to see if with have SI/SO shifters
|
|
if we do we change the mode appropriately and we consume the byte*/
|
|
while ((*(args->source) == UCNV_SI) || (*(args->source) == UCNV_SO))
|
|
{
|
|
args->converter->mode = *(args->source);
|
|
args->source++;
|
|
sourceInitial = args->source;
|
|
|
|
/*Rechecks boundary after consuming the shift sequence*/
|
|
if (args->source >= args->sourceLimit)
|
|
{
|
|
*err = U_INDEX_OUTOFBOUNDS_ERROR;
|
|
return 0xffff;
|
|
}
|
|
}
|
|
|
|
if (args->converter->mode == UCNV_SI)
|
|
{
|
|
myUChar = ucmp16_getu( (&(args->converter->sharedData->table->dbcs.toUnicode)),
|
|
((UChar)(uint8_t)(*(args->source))));
|
|
args->source++;
|
|
}
|
|
else
|
|
{
|
|
/*Lead byte: we Build the codepoint and get the corresponding character
|
|
* and update the source ptr*/
|
|
if ((args->source + 2) > args->sourceLimit)
|
|
{
|
|
*err = U_TRUNCATED_CHAR_FOUND;
|
|
return 0xffff;
|
|
}
|
|
|
|
myUChar = ucmp16_getu( (&(args->converter->sharedData->table->dbcs.toUnicode)),
|
|
(((UChar)(uint8_t)((*(args->source))) << 8) |((uint8_t)*(args->source+1))) );
|
|
|
|
args->source += 2;
|
|
}
|
|
|
|
if (myUChar < 0xfffe) return myUChar;
|
|
else
|
|
{
|
|
/* HSYS: Check logic here */
|
|
UChar* myUCharPtr = &myUChar;
|
|
UConverterCallbackReason reason;
|
|
|
|
if (myUChar == 0xfffe)
|
|
{
|
|
reason = UCNV_UNASSIGNED;
|
|
*err = U_INVALID_CHAR_FOUND;
|
|
}
|
|
else
|
|
{
|
|
reason = UCNV_ILLEGAL;
|
|
*err = U_ILLEGAL_CHAR_FOUND;
|
|
}
|
|
|
|
/*It's is very likely that the ErrorFunctor will write to the
|
|
*internal buffers */
|
|
args->target = myUCharPtr;
|
|
args->targetLimit = myUCharPtr + 1;
|
|
|
|
args->converter->fromCharErrorBehaviour(args->converter->toUContext,
|
|
args,
|
|
sourceInitial,
|
|
args->source - sourceInitial,
|
|
reason,
|
|
err);
|
|
|
|
/*makes the internal caching transparent to the user*/
|
|
if (*err == U_BUFFER_OVERFLOW_ERROR) *err = U_ZERO_ERROR;
|
|
|
|
return myUChar;
|
|
}
|
|
}
|
|
|
|
U_CFUNC void
|
|
_EBCDIC_STATEFUL_WriteSub(UConverterFromUnicodeArgs *pArgs, int32_t offsetIndex, UErrorCode *pErrorCode) {
|
|
UConverter *cnv = pArgs->converter;
|
|
char *p;
|
|
char buffer[4];
|
|
|
|
p = buffer;
|
|
|
|
/* fromUnicodeStatus contains UBool "in DBCS mode" */
|
|
if(cnv->subCharLen == 1) {
|
|
if(cnv->fromUnicodeStatus) {
|
|
/* DBCS mode and SBCS sub char: change to SBCS */
|
|
cnv->fromUnicodeStatus = FALSE;
|
|
*p++ = UCNV_SI;
|
|
}
|
|
*p++ = cnv->subChar[0];
|
|
} else {
|
|
if(!cnv->fromUnicodeStatus) {
|
|
/* SBCS mode and DBCS sub char: change to DBCS */
|
|
cnv->fromUnicodeStatus = TRUE;
|
|
*p++ = UCNV_SO;
|
|
}
|
|
*p++ = cnv->subChar[0];
|
|
*p++ = cnv->subChar[1];
|
|
}
|
|
ucnv_cbFromUWriteBytes(pArgs,
|
|
buffer, (int32_t)(p - buffer),
|
|
offsetIndex, pErrorCode);
|
|
}
|
|
|
|
static const UConverterImpl _EBCDICStatefulImpl={
|
|
UCNV_EBCDIC_STATEFUL,
|
|
|
|
_DBCSLoad,
|
|
_DBCSUnload,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
T_UConverter_toUnicode_EBCDIC_STATEFUL,
|
|
T_UConverter_toUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC,
|
|
T_UConverter_fromUnicode_EBCDIC_STATEFUL,
|
|
T_UConverter_fromUnicode_EBCDIC_STATEFUL_OFFSETS_LOGIC,
|
|
T_UConverter_getNextUChar_EBCDIC_STATEFUL,
|
|
|
|
NULL,
|
|
NULL,
|
|
_EBCDIC_STATEFUL_WriteSub
|
|
};
|
|
|
|
/* Static data is in tools/makeconv/ucnvstat.c for data-based
|
|
* converters. Be sure to update it as well.
|
|
*/
|
|
|
|
const UConverterSharedData _EBCDICStatefulData={
|
|
sizeof(UConverterSharedData), 1,
|
|
NULL, NULL, NULL, FALSE, &_EBCDICStatefulImpl,
|
|
0
|
|
};
|