}
BufferedInputStream b = new BufferedInputStream(i, UConverterConstants.CNV_DATA_BUFFER_SIZE);
reader = new UConverterDataReader(b);
reader.readStaticData(staticData);
} catch (IOException e) {
throw new InvalidFormatException();
} catch (Exception e) {
throw new InvalidFormatException();
}
UConverterSharedData data = null;
int type = staticData.conversionType;
if (type != UConverterSharedData.UConverterType.MBCS
|| staticData.structSize != UConverterStaticData.SIZE_OF_UCONVERTER_STATIC_DATA) {
throw new InvalidFormatException();
}
data = new UConverterSharedData(1, null, false, 0);
data.dataReader = reader;
data.staticData = staticData;
data.sharedDataCached = false;
// Load data
UConverterMBCSTable mbcsTable = data.mbcs;
MBCSHeader header = new MBCSHeader();
try {
reader.readMBCSHeader(header);
} catch (IOException e) {
throw new InvalidFormatException();
}
int offset;
// int[] extIndexesArray = null;
String baseNameString = null;
int[][] stateTableArray = null;
MBCSToUFallback[] toUFallbacksArray = null;
char[] unicodeCodeUnitsArray = null;
char[] fromUnicodeTableArray = null;
byte[] fromUnicodeBytesArray = null;
if (header.version[0] == 5 && header.version[1] >= 3 && (header.options & MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK) == 0) {
noFromU = ((header.options & MBCS_OPT_NO_FROM_U) != 0);
} else if (header.version[0] != 4) {
throw new InvalidFormatException();
}
mbcsTable.outputType = (byte) header.flags;
/* extension data, header version 4.2 and higher */
offset = header.flags >>> 8;
// if(offset!=0 && mbcsTable.outputType == MBCS_OUTPUT_EXT_ONLY) {
if (mbcsTable.outputType == MBCS_OUTPUT_EXT_ONLY) {
try {
baseNameString = reader.readBaseTableName();
if (offset != 0) {
// agljport:commment subtract 32 for sizeof(_MBCSHeader) and length of baseNameString and 1 null
// terminator byte all already read;
mbcsTable.extIndexes = reader.readExtIndexes(offset
- (reader.bytesRead - reader.staticDataBytesRead));
}
} catch (IOException e) {
throw new InvalidFormatException();
}
}
// agljport:add this would be unnecessary if extIndexes were memory mapped
/*
* if(mbcsTable.extIndexes != null) {
*
* try { //int nbytes = mbcsTable.extIndexes[UConverterExt.UCNV_EXT_TO_U_LENGTH]*4 +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_TO_U_UCHARS_LENGTH]*2 +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_FROM_U_LENGTH]*6 +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_FROM_U_BYTES_LENGTH] +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_FROM_U_STAGE_12_LENGTH]*2 +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_FROM_U_STAGE_3_LENGTH]*2 +
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_FROM_U_STAGE_3B_LENGTH]*4; //int nbytes =
* mbcsTable.extIndexes[UConverterExt.UCNV_EXT_SIZE] //byte[] extTables = dataReader.readExtTables(nbytes);
* //mbcsTable.extTables = ByteBuffer.wrap(extTables); } catch(IOException e) { System.err.println("Caught
* IOException: " + e.getMessage()); pErrorCode[0] = UErrorCode.U_INVALID_FORMAT_ERROR; return; } }
*/
if (mbcsTable.outputType == MBCS_OUTPUT_EXT_ONLY) {
UConverterSharedData baseSharedData = null;
ByteBuffer extIndexes;
String baseName;
/* extension-only file, load the base table and set values appropriately */
extIndexes = mbcsTable.extIndexes;
if (extIndexes == null) {
/* extension-only file without extension */
throw new InvalidFormatException();
}
if (nestedLoads != 1) {
/* an extension table must not be loaded as a base table */
throw new InvalidFormatException();
}
/* load the base table */
baseName = baseNameString;
if (baseName.equals(staticData.name)) {
/* forbid loading this same extension-only file */
throw new InvalidFormatException();
}
// agljport:fix args.size=sizeof(UConverterLoadArgs);
baseSharedData = loadConverter(2, baseName, classPath, loader);
if (baseSharedData.staticData.conversionType != UConverterType.MBCS
|| baseSharedData.mbcs.baseSharedData != null) {
// agljport:fix ucnv_unload(baseSharedData);
throw new InvalidFormatException();
}
/* copy the base table data */
// agljport:comment deep copy in C changes mbcs through local reference mbcsTable; in java we probably don't
// need the deep copy so can just make sure mbcs and its local reference both refer to the same new object
mbcsTable = data.mbcs = baseSharedData.mbcs;
/* overwrite values with relevant ones for the extension converter */
mbcsTable.baseSharedData = baseSharedData;
mbcsTable.extIndexes = extIndexes;
/*
* It would be possible to share the swapLFNL data with a base converter, but the generated name would have
* to be different, and the memory would have to be free'd only once. It is easier to just create the data
* for the extension converter separately when it is requested.
*/
mbcsTable.swapLFNLStateTable = null;
mbcsTable.swapLFNLFromUnicodeBytes = null;
mbcsTable.swapLFNLName = null;
/*
* Set a special, runtime-only outputType if the extension converter is a DBCS version of a base converter
* that also maps single bytes.
*/
if (staticData.conversionType == UConverterType.DBCS
|| (staticData.conversionType == UConverterType.MBCS && staticData.minBytesPerChar >= 2)) {
if (baseSharedData.mbcs.outputType == MBCS_OUTPUT_2_SISO) {
/* the base converter is SI/SO-stateful */
int entry;
/* get the dbcs state from the state table entry for SO=0x0e */
entry = mbcsTable.stateTable[0][0xe];
if (MBCS_ENTRY_IS_FINAL(entry) && MBCS_ENTRY_FINAL_ACTION(entry) == MBCS_STATE_CHANGE_ONLY
&& MBCS_ENTRY_FINAL_STATE(entry) != 0) {
mbcsTable.dbcsOnlyState = (byte) MBCS_ENTRY_FINAL_STATE(entry);
mbcsTable.outputType = MBCS_OUTPUT_DBCS_ONLY;
}
} else if (baseSharedData.staticData.conversionType == UConverterType.MBCS
&& baseSharedData.staticData.minBytesPerChar == 1
&& baseSharedData.staticData.maxBytesPerChar == 2 && mbcsTable.countStates <= 127) {
/* non-stateful base converter, need to modify the state table */
int newStateTable[][/* 256 */];
int state[]; // this works because java 2-D array is array of references and we can have state =
// newStateTable[i];
int i, count;
/* allocate a new state table and copy the base state table contents */
count = mbcsTable.countStates;
newStateTable = new int[(count + 1) * 1024][256];
for (i = 0; i < mbcsTable.stateTable.length; ++i)
System.arraycopy(mbcsTable.stateTable[i], 0, newStateTable[i], 0,
mbcsTable.stateTable[i].length);
/* change all final single-byte entries to go to a new all-illegal state */
state = newStateTable[0];
for (i = 0; i < 256; ++i) {
if (MBCS_ENTRY_IS_FINAL(state[i])) {
state[i] = MBCS_ENTRY_TRANSITION(count, 0);
}
}
/* build the new all-illegal state */
state = newStateTable[count];
for (i = 0; i < 256; ++i) {
state[i] = MBCS_ENTRY_FINAL(0, MBCS_STATE_ILLEGAL, 0);
}
mbcsTable.stateTable = newStateTable;
mbcsTable.countStates = (byte) (count + 1);
mbcsTable.stateTableOwned = true;
mbcsTable.outputType = MBCS_OUTPUT_DBCS_ONLY;
}
}
/*
* unlike below for files with base tables, do not get the unicodeMask from the sharedData; instead, use the
* base table's unicodeMask, which we copied in the memcpy above; this is necessary because the static data
* unicodeMask, especially the UCNV_HAS_SUPPLEMENTARY flag, is part of the base table data
*/
} else {
/* conversion file with a base table; an additional extension table is optional */
/* make sure that the output type is known */
switch (mbcsTable.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:
/* OK */
break;
default:
throw new InvalidFormatException();
}
stateTableArray = new int[header.countStates][256];
toUFallbacksArray = new MBCSToUFallback[header.countToUFallbacks];
for (int i = 0; i < toUFallbacksArray.length; ++i)
toUFallbacksArray[i] = new MBCSToUFallback();
unicodeCodeUnitsArray = new char[(header.offsetFromUTable - header.offsetToUCodeUnits) / 2];
fromUnicodeTableArray = new char[(header.offsetFromUBytes - header.offsetFromUTable) / 2];
fromUnicodeBytesArray = new byte[header.fromUBytesLength];
try {
reader.readMBCSTable(stateTableArray, toUFallbacksArray, unicodeCodeUnitsArray, fromUnicodeTableArray,
fromUnicodeBytesArray);
} catch (IOException e) {
throw new InvalidFormatException();
}
mbcsTable.countStates = (byte) header.countStates;
mbcsTable.countToUFallbacks = header.countToUFallbacks;
mbcsTable.stateTable = stateTableArray;
mbcsTable.toUFallbacks = toUFallbacksArray;
mbcsTable.unicodeCodeUnits = unicodeCodeUnitsArray;
mbcsTable.fromUnicodeTable = fromUnicodeTableArray;
mbcsTable.fromUnicodeBytes = fromUnicodeBytesArray;
mbcsTable.fromUBytesLength = header.fromUBytesLength;
/*
* converter versions 6.1 and up contain a unicodeMask that is used here to select the most efficient
* function implementations
*/
// agljport:fix info.size=sizeof(UDataInfo);
// agljport:fix udata_getInfo((UDataMemory *)sharedData->dataMemory, &info);
// agljport:fix if(info.formatVersion[0]>6 || (info.formatVersion[0]==6 && info.formatVersion[1]>=1)) {
/* mask off possible future extensions to be safe */
mbcsTable.unicodeMask = (short) (staticData.unicodeMask & 3);
// agljport:fix } else {
/* for older versions, assume worst case: contains anything possible (prevent over-optimizations) */
// agljport:fix mbcsTable->unicodeMask=UCNV_HAS_SUPPLEMENTARY|UCNV_HAS_SURROGATES;
// agljport:fix }
if (offset != 0) {
try {
// agljport:commment subtract 32 for sizeof(_MBCSHeader) and length of baseNameString and 1 null
// terminator byte all already read;
// int namelen = baseNameString != null? baseNameString.length() + 1: 0;
mbcsTable.extIndexes = reader.readExtIndexes(offset
- (reader.bytesRead - reader.staticDataBytesRead));
} catch (IOException e) {
throw new InvalidFormatException();
}
}
if (header.version[1] >= 3 && (mbcsTable.unicodeMask & UConverterConstants.HAS_SURROGATES) == 0 &&
(mbcsTable.countStates == 1 ? ((char)header.version[2] >= (SBCS_FAST_MAX>>8)) : ((char)header.version[2] >= (MBCS_FAST_MAX>>8)))) {