mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-2404 implement data swapping for extensions
X-SVN-Rev: 13530
This commit is contained in:
parent
46044283f2
commit
5988436ee7
1 changed files with 146 additions and 48 deletions
|
@ -26,6 +26,8 @@
|
|||
#include "unicode/uloc.h"
|
||||
#include "ucnv_io.h"
|
||||
#include "ucnv_bld.h"
|
||||
#include "ucnvmbcs.h"
|
||||
#include "ucnv_ext.h"
|
||||
#include "ucnv_cnv.h"
|
||||
#include "ucnv_imp.h"
|
||||
#include "uhash.h"
|
||||
|
@ -870,6 +872,9 @@ ucnv_swap(const UDataSwapper *ds,
|
|||
_MBCSHeader mbcsHeader;
|
||||
uint8_t outputType;
|
||||
|
||||
const int32_t *inExtIndexes;
|
||||
int32_t extOffset;
|
||||
|
||||
/* udata_swapDataHeader checks the arguments */
|
||||
headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
|
@ -963,10 +968,43 @@ ucnv_swap(const UDataSwapper *ds,
|
|||
mbcsHeader.flags= ds->readUInt32(inMBCSHeader->flags);
|
||||
mbcsHeader.fromUBytesLength= ds->readUInt32(inMBCSHeader->fromUBytesLength);
|
||||
|
||||
extOffset=(int32_t)mbcsHeader.flags>>8;
|
||||
outputType=(uint8_t)mbcsHeader.flags;
|
||||
|
||||
/* make sure that the output type is known */
|
||||
switch(outputType) {
|
||||
case MBCS_OUTPUT_1:
|
||||
case MBCS_OUTPUT_2:
|
||||
case MBCS_OUTPUT_3:
|
||||
case MBCS_OUTPUT_4:
|
||||
case MBCS_OUTPUT_3_EUC:
|
||||
case MBCS_OUTPUT_4_EUC:
|
||||
case MBCS_OUTPUT_2_SISO:
|
||||
case MBCS_OUTPUT_EXT_ONLY:
|
||||
/* OK */
|
||||
break;
|
||||
default:
|
||||
udata_printError(ds, "ucnv_swap(): unsupported MBCS output type 0x%x\n",
|
||||
outputType);
|
||||
*pErrorCode=U_UNSUPPORTED_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate the length of the MBCS data */
|
||||
size=(int32_t)(mbcsHeader.offsetFromUBytes+mbcsHeader.fromUBytesLength);
|
||||
if(extOffset==0) {
|
||||
size=(int32_t)(mbcsHeader.offsetFromUBytes+mbcsHeader.fromUBytesLength);
|
||||
} else {
|
||||
/* there is extension data after the base data, see ucnv_ext.h */
|
||||
if(length<(extOffset+UCNV_EXT_INDEXES_MIN_LENGTH*4)) {
|
||||
udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table with extension data\n",
|
||||
length);
|
||||
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inExtIndexes=(const int32_t *)(inBytes+extOffset);
|
||||
size=extOffset+udata_readInt32(ds, inExtIndexes[UCNV_EXT_SIZE]);
|
||||
}
|
||||
|
||||
if(length>=0) {
|
||||
if(length<size) {
|
||||
|
@ -985,66 +1023,126 @@ ucnv_swap(const UDataSwapper *ds,
|
|||
ds->swapArray32(ds, &inMBCSHeader->countStates, 7*4,
|
||||
&outMBCSHeader->countStates, pErrorCode);
|
||||
|
||||
/* swap the state table, 1kB per state */
|
||||
ds->swapArray32(ds, inMBCSHeader+1, (int32_t)(mbcsHeader.countStates*1024),
|
||||
outMBCSHeader+1, pErrorCode);
|
||||
if(outputType==MBCS_OUTPUT_EXT_ONLY) {
|
||||
/*
|
||||
* extension-only file,
|
||||
* contains a base name instead of normal base table data
|
||||
*/
|
||||
|
||||
/* swap the toUFallbacks[] */
|
||||
offset=sizeof(_MBCSHeader)+mbcsHeader.countStates*1024;
|
||||
ds->swapArray32(ds, inBytes+offset, (int32_t)(mbcsHeader.countToUFallbacks*8),
|
||||
outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap the unicodeCodeUnits[] */
|
||||
offset=mbcsHeader.offsetToUCodeUnits;
|
||||
count=mbcsHeader.offsetFromUTable-offset;
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
|
||||
/* offset to the stage 1 table, independent of the outputType */
|
||||
offset=mbcsHeader.offsetFromUTable;
|
||||
|
||||
if(outputType==MBCS_OUTPUT_1) {
|
||||
/* SBCS: swap the fromU tables, all 16 bits wide */
|
||||
count=(mbcsHeader.offsetFromUBytes-offset)+mbcsHeader.fromUBytesLength;
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
/* swap the base name, between the header and the extension data */
|
||||
ds->swapInvChars(ds, inMBCSHeader+1, uprv_strlen((const char *)(inMBCSHeader+1)),
|
||||
outMBCSHeader+1, pErrorCode);
|
||||
} else {
|
||||
/* otherwise: swap the stage tables separately */
|
||||
/* normal file with base table data */
|
||||
|
||||
/* stage 1 table: uint16_t[0x440 or 0x40] */
|
||||
if(inStaticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
|
||||
count=0x440*2; /* for all of Unicode */
|
||||
} else {
|
||||
count=0x40*2; /* only BMP */
|
||||
}
|
||||
/* swap the state table, 1kB per state */
|
||||
ds->swapArray32(ds, inMBCSHeader+1, (int32_t)(mbcsHeader.countStates*1024),
|
||||
outMBCSHeader+1, pErrorCode);
|
||||
|
||||
/* swap the toUFallbacks[] */
|
||||
offset=sizeof(_MBCSHeader)+mbcsHeader.countStates*1024;
|
||||
ds->swapArray32(ds, inBytes+offset, (int32_t)(mbcsHeader.countToUFallbacks*8),
|
||||
outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap the unicodeCodeUnits[] */
|
||||
offset=mbcsHeader.offsetToUCodeUnits;
|
||||
count=mbcsHeader.offsetFromUTable-offset;
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
|
||||
/* stage 2 table: uint32_t[] */
|
||||
offset+=count;
|
||||
count=mbcsHeader.offsetFromUBytes-offset;
|
||||
ds->swapArray32(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
/* offset to the stage 1 table, independent of the outputType */
|
||||
offset=mbcsHeader.offsetFromUTable;
|
||||
|
||||
/* stage 3/result bytes: sometimes uint16_t[] or uint32_t[] */
|
||||
offset=mbcsHeader.offsetFromUBytes;
|
||||
count=mbcsHeader.fromUBytesLength;
|
||||
switch(outputType) {
|
||||
case MBCS_OUTPUT_2:
|
||||
case MBCS_OUTPUT_3_EUC:
|
||||
case MBCS_OUTPUT_2_SISO:
|
||||
if(outputType==MBCS_OUTPUT_1) {
|
||||
/* SBCS: swap the fromU tables, all 16 bits wide */
|
||||
count=(mbcsHeader.offsetFromUBytes-offset)+mbcsHeader.fromUBytesLength;
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
break;
|
||||
case MBCS_OUTPUT_4:
|
||||
} else {
|
||||
/* otherwise: swap the stage tables separately */
|
||||
|
||||
/* stage 1 table: uint16_t[0x440 or 0x40] */
|
||||
if(inStaticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
|
||||
count=0x440*2; /* for all of Unicode */
|
||||
} else {
|
||||
count=0x40*2; /* only BMP */
|
||||
}
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
|
||||
/* stage 2 table: uint32_t[] */
|
||||
offset+=count;
|
||||
count=mbcsHeader.offsetFromUBytes-offset;
|
||||
ds->swapArray32(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
break;
|
||||
default:
|
||||
/* just uint8_t[], nothing to swap */
|
||||
break;
|
||||
|
||||
/* stage 3/result bytes: sometimes uint16_t[] or uint32_t[] */
|
||||
offset=mbcsHeader.offsetFromUBytes;
|
||||
count=mbcsHeader.fromUBytesLength;
|
||||
switch(outputType) {
|
||||
case MBCS_OUTPUT_2:
|
||||
case MBCS_OUTPUT_3_EUC:
|
||||
case MBCS_OUTPUT_2_SISO:
|
||||
ds->swapArray16(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
break;
|
||||
case MBCS_OUTPUT_4:
|
||||
ds->swapArray32(ds, inBytes+offset, (int32_t)count,
|
||||
outBytes+offset, pErrorCode);
|
||||
break;
|
||||
default:
|
||||
/* just uint8_t[], nothing to swap */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(extOffset!=0) {
|
||||
/* swap the extension data */
|
||||
inBytes+=extOffset;
|
||||
outBytes+=extOffset;
|
||||
|
||||
/* swap toUTable[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_LENGTH]);
|
||||
ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap toUUChars[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_LENGTH]);
|
||||
ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap fromUTableUChars[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_UCHARS_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_LENGTH]);
|
||||
ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap fromUTableValues[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_VALUES_INDEX]);
|
||||
/* same length as for fromUTableUChars[] */
|
||||
ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
|
||||
|
||||
/* no need to swap fromUBytes[] */
|
||||
|
||||
/* swap fromUStage12[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_LENGTH]);
|
||||
ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap fromUStage3[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_LENGTH]);
|
||||
ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap fromUStage3b[] */
|
||||
offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_INDEX]);
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_LENGTH]);
|
||||
ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
|
||||
|
||||
/* swap indexes[] */
|
||||
length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_INDEXES_LENGTH]);
|
||||
ds->swapArray32(ds, inBytes, length*4, outBytes, pErrorCode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
udata_printError(ds, "ucnv_swap(): unknown conversionType=%d!=UCNV_MBCS\n",
|
||||
|
|
Loading…
Add table
Reference in a new issue