src.com.ibm.as400.access.ConvTableMixedMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: ConvTableMixedMap.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2004 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.UnsupportedEncodingException;
// This is the parent class for all ConvTableXXX classes that represent mixed-byte ccsids.
abstract class ConvTableMixedMap extends ConvTable
{
private static final String copyright = "Copyright (C) 1997-2004 International Business Machines Corporation and others.";
ConvTableSingleMap sbTable_ = null; // The single-byte portion of this mixed-byte table.
ConvTableDoubleMap dbTable_ = null; // The double-byte portion of this mixed-byte table.
static final byte shiftOut_ = 0x0E; // Byte used to shift-out of single byte mode.
static final byte shiftIn_ = 0x0F; // Byte used to shift-in to single byte mode.
// Constructor.
ConvTableMixedMap(int ccsid, int sbCcsid, int dbCcsid) throws UnsupportedEncodingException
{
super(ccsid);
sbTable_ = (ConvTableSingleMap)ConvTable.getTable(sbCcsid, null);
dbTable_ = (ConvTableDoubleMap)ConvTable.getTable(dbCcsid, null);
if (Trace.traceConversion_) Trace.log(Trace.CONVERSION, "Successfully loaded mixed-byte map for ccsid: " + ccsid_);
}
// Perform an OS/400 CCSID to Unicode conversion.
final String byteArrayToString(byte[] buf, int offset, int length, BidiConversionProperties properties)
{
if (Trace.traceConversion_) Trace.log(Trace.CONVERSION, "Converting byte array to string for ccsid: " + ccsid_, buf, offset, length);
char[] dest = new char[length];
boolean inSBMode = true;
int destPos = 0;
for (int srcPos = offset; srcPos < offset + length; ++srcPos)
{
byte curByte = buf[srcPos];
if (inSBMode)
{
// In single byte mode.
if (curByte == shiftOut_)
{
// Shift out character. Switch to double byte mode.
inSBMode = false;
}
else
{
// Normal character. Perform single-byte lookup.
dest[destPos++] = sbTable_.toUnicode_[(0x00FF & curByte)];
}
}
else
{
// In double byte mode.
if (curByte == shiftIn_)
{
// Shift in character. Switch to single byte mode.
inSBMode = true;
}
else
{
try
{
// Normal character. Perform double-byte lookup.
int unicodeLength = dbTable_.toUnicode(dest, destPos, ((0x00FF & curByte) << 8) + (0x00FF & buf[++srcPos])); /*@KDC*/
destPos += unicodeLength;
// dest[destPos++] = dbTable_.toUnicode_[((0x00FF & curByte) << 8) + (0x00FF & buf[++srcPos])];
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
// Swallow this if we are doing fault-tolerant conversion.
if(!CharConverter.isFaultTolerantConversion())
{
throw aioobe;
}
// No need to decrement because increment in dest[destPost++] not longer occurs
// --destPos;
}
}
}
}
if (Trace.traceConversion_) Trace.log(Trace.CONVERSION, "Destination string for ccsid: " + ccsid_ + ": 0," + destPos, ConvTable.dumpCharArray(dest));
return String.copyValueOf(dest, 0, destPos);
}
// Perform a Unicode to OS/400 CCSID conversion.
final byte[] stringToByteArray(String source, BidiConversionProperties properties)
{
char[] src = source.toCharArray();
if (Trace.traceConversion_) Trace.log(Trace.CONVERSION, "Converting string to byte array for ccsid: " + ccsid_, ConvTable.dumpCharArray(src));
// Max possible length for mixed-byte byte array.
byte[] dest = new byte[(src.length * 5 + 3) / 2];
boolean inSBMode = true;
byte sbLookup = 0x00;
char dbLookup = '\u0000';
int[] increment = new int[1]; /*@KDA*/
int destPos = 0; /*@KDA*/
for (int srcPos = 0; srcPos < src.length; ++srcPos)
{
char curChar = src[srcPos];
// There is no concept of mode context when converting a String to a byte array.
// The table we look at first is only based on the current character in the String.
if ((curChar & 0xFF00) == 0x0000 || curChar == euro_)
{
// Use single-byte table first.
sbLookup = sbTable_.fromUnicode_[curChar];
if (sbLookup == sbSubChar_ && curChar != sbSubUnic_)
{
// Character wasn't in single-byte table. Check double-byte table next.
dbLookup = dbTable_.fromUnicode(src,srcPos,increment);
if (increment[0] == 2) {
// move an extra byte in the source @KDA
srcPos++;
}
// dbLookup = dbTable_.fromUnicode_[curChar]; @KDC
if (dbLookup == dbSubChar_)
{
// Character wasn't in the double-byte table either, so use single-byte substitution character.
if (!inSBMode)
{
inSBMode = true;
dest[destPos++] = shiftIn_;
}
dest[destPos++] = sbSubChar_;
}
else
{
// Character found in double-byte table.
if (inSBMode)
{
inSBMode = false;
dest[destPos++] = shiftOut_;
}
dest[destPos++] = (byte)((0xFFFF & dbLookup) >>> 8);
dest[destPos++] = (byte)(0x00FF & dbLookup);
}
}
else
{
// Character found in single-byte table.
if (!inSBMode)
{
inSBMode = true;
dest[destPos++] = shiftIn_;
}
dest[destPos++] = sbLookup;
}
}
else
{
// Use double-byte table first.
// dbLookup = dbTable_.fromUnicode_[curChar];
dbLookup = dbTable_.fromUnicode(src,srcPos,increment);
if (increment[0] == 2) {
// move an extra byte in the source @KDA
srcPos++;
}
if (dbLookup == dbSubChar_ && curChar != dbSubUnic_)
{
// Character wasn't in double-byte table. Check single-byte table next.
sbLookup = sbTable_.fromUnicode_[curChar];
if (sbLookup == sbSubChar_)
{
// Character wasn't in the single-byte table either, so use double-byte substitution character.
if (inSBMode)
{
inSBMode = false;
dest[destPos++] = shiftOut_;
}
dest[destPos++] = (byte)((0xFFFF & dbSubChar_) >>> 8);
dest[destPos++] = (byte)(0x00FF & dbSubChar_);
}
else
{
// Character found in single-byte table.
if (!inSBMode)
{
inSBMode = true;
dest[destPos++] = shiftIn_;
}
dest[destPos++] = sbLookup;
}
}
else
{
// Character found in double-byte table.
if (inSBMode)
{
inSBMode = false;
dest[destPos++] = shiftOut_;
}
dest[destPos++] = (byte)((0xFFFF & dbLookup) >>> 8);
dest[destPos++] = (byte)(0x00FF & dbLookup);
}
}
}
// Write final shift in, just in case.
if (!inSBMode)
{
dest[destPos++] = shiftIn_;
}
byte[] ret = new byte[destPos];
System.arraycopy(dest, 0, ret, 0, destPos);
if (Trace.traceConversion_) Trace.log(Trace.CONVERSION, "Destination byte array for ccsid: " + ccsid_, ret);
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy