package com.ximple.eofms.util;
|
|
//~--- JDK imports ------------------------------------------------------------
|
|
import java.nio.ByteBuffer;
|
import java.nio.ByteOrder;
|
import java.nio.LongBuffer;
|
|
/**
|
* BinConverter
|
* User: Ulysses
|
* Date: 2007/9/17
|
* Time: 上午 01:13:13
|
*/
|
public class BinConverter
|
{
|
// our table for binhex conversion
|
final static char[] HEXTAB =
|
{
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
};
|
|
/**
|
* gets bytes from an array into a long
|
*
|
* @param buffer where to get the bytes
|
* @param nStartIndex index from where to read the data
|
* @return the 64bit integer
|
*/
|
public static long byteArrayToLong(byte[] buffer, int nStartIndex)
|
{
|
return (((long) buffer[nStartIndex]) << 56) | (((long) buffer[nStartIndex + 1] & 0x0ffL) << 48)
|
| (((long) buffer[nStartIndex + 2] & 0x0ffL) << 40) | (((long) buffer[nStartIndex + 3] & 0x0ffL) << 32)
|
| (((long) buffer[nStartIndex + 4] & 0x0ffL) << 24) | (((long) buffer[nStartIndex + 5] & 0x0ffL) << 16)
|
| (((long) buffer[nStartIndex + 6] & 0x0ffL) << 8) | ((long) buffer[nStartIndex + 7] & 0x0ff);
|
}
|
|
/**
|
* converts a long o bytes which are put into a given array
|
*
|
* @param lValue the 64bit integer to convert
|
* @param buffer the target buffer
|
* @param nStartIndex where to place the bytes in the buffer
|
*/
|
public static void longToByteArray(long lValue, byte[] buffer, int nStartIndex)
|
{
|
buffer[nStartIndex] = (byte) (lValue >>> 56);
|
buffer[nStartIndex + 1] = (byte) ((lValue >>> 48) & 0x0ff);
|
buffer[nStartIndex + 2] = (byte) ((lValue >>> 40) & 0x0ff);
|
buffer[nStartIndex + 3] = (byte) ((lValue >>> 32) & 0x0ff);
|
buffer[nStartIndex + 4] = (byte) ((lValue >>> 24) & 0x0ff);
|
buffer[nStartIndex + 5] = (byte) ((lValue >>> 16) & 0x0ff);
|
buffer[nStartIndex + 6] = (byte) ((lValue >>> 8) & 0x0ff);
|
buffer[nStartIndex + 7] = (byte) lValue;
|
}
|
|
/**
|
* converts values from an integer array to a long
|
*
|
* @param buffer where to get the bytes
|
* @param nStartIndex index from where to read the data
|
* @return the 64bit integer
|
*/
|
public static long intArrayToLong(int[] buffer, int nStartIndex)
|
{
|
return (((long) buffer[nStartIndex]) << 32) | (((long) buffer[nStartIndex + 1]) & 0x0ffffffffL);
|
}
|
|
/**
|
* converts a long to integers which are put into a given array
|
*
|
* @param lValue the 64bit integer to convert
|
* @param buffer the target buffer
|
* @param nStartIndex where to place the bytes in the buffer
|
*/
|
public static void longToIntArray(long lValue, int[] buffer, int nStartIndex)
|
{
|
buffer[nStartIndex] = (int) (lValue >>> 32);
|
buffer[nStartIndex + 1] = (int) lValue;
|
}
|
|
/**
|
* makes a long from two integers (treated unsigned)
|
*
|
* @param nLo lower 32bits
|
* @param nHi higher 32bits
|
* @return the built long
|
*/
|
public static long makeLong(int nLo, int nHi)
|
{
|
return (((long) nHi << 32) | ((long) nLo & 0x00000000ffffffffL));
|
}
|
|
/**
|
* gets the lower 32 bits of a long
|
*
|
* @param lVal the long integer
|
* @return lower 32 bits
|
*/
|
public static int longLo32(long lVal)
|
{
|
return (int) lVal;
|
}
|
|
/**
|
* gets the higher 32 bits of a long
|
*
|
* @param lVal the long integer
|
* @return higher 32 bits
|
*/
|
public static int longHi32(long lVal)
|
{
|
return (int) ((long) (lVal >>> 32));
|
}
|
|
/**
|
* converts a byte array to a binhex string
|
*
|
* @param data the byte array
|
* @return the binhex string
|
*/
|
public static String bytesToBinHex(byte[] data)
|
{
|
// just map the call
|
return bytesToBinHex(data, 0, data.length);
|
}
|
|
/**
|
* converts a byte array to a binhex string
|
*
|
* @param data the byte array
|
* @param nStartPos start index where to get the bytes
|
* @param nNumOfBytes number of bytes to convert
|
* @return the binhex string
|
*/
|
public static String bytesToBinHex(byte[] data, int nStartPos, int nNumOfBytes)
|
{
|
StringBuffer sbuf = new StringBuffer();
|
|
sbuf.setLength(nNumOfBytes << 1);
|
|
int nPos = 0;
|
|
for (int nI = 0; nI < nNumOfBytes; nI++)
|
{
|
sbuf.setCharAt(nPos++, HEXTAB[(data[nI + nStartPos] >> 4) & 0x0f]);
|
sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0x0f]);
|
}
|
|
return sbuf.toString();
|
}
|
|
/**
|
* converts a binhex string back into a byte array (invalid codes will be skipped)
|
*
|
* @param sBinHex binhex string
|
* @param data the target array
|
* @param nSrcPos from which character in the string the conversion should begin,
|
* remember that (nSrcPos modulo 2) should equals 0 normally
|
* @param nDstPos to store the bytes from which position in the array
|
* @param nNumOfBytes number of bytes to extract
|
* @return number of extracted bytes
|
*/
|
public static int binHexToBytes(String sBinHex, byte[] data, int nSrcPos, int nDstPos, int nNumOfBytes)
|
{
|
// check for correct ranges
|
int nStrLen = sBinHex.length();
|
int nAvailBytes = (nStrLen - nSrcPos) >> 1;
|
|
if (nAvailBytes < nNumOfBytes)
|
{
|
nNumOfBytes = nAvailBytes;
|
}
|
|
int nOutputCapacity = data.length - nDstPos;
|
|
if (nNumOfBytes > nOutputCapacity)
|
{
|
nNumOfBytes = nOutputCapacity;
|
}
|
|
// convert now
|
int nResult = 0;
|
|
for (int nI = 0; nI < nNumOfBytes; nI++)
|
{
|
byte bActByte = 0;
|
boolean blConvertOK = true;
|
|
for (int nJ = 0; nJ < 2; nJ++)
|
{
|
bActByte <<= 4;
|
|
char cActChar = sBinHex.charAt(nSrcPos++);
|
|
if ((cActChar >= 'a') && (cActChar <= 'f'))
|
{
|
bActByte |= (byte) (cActChar - 'a') + 10;
|
} else if ((cActChar >= '0') && (cActChar <= '9'))
|
{
|
bActByte |= (byte) (cActChar - '0');
|
} else
|
{
|
blConvertOK = false;
|
}
|
}
|
|
if (blConvertOK)
|
{
|
data[nDstPos++] = bActByte;
|
nResult++;
|
}
|
}
|
|
return nResult;
|
}
|
|
/**
|
* converts a byte array into an UNICODE string
|
*
|
* @param data the byte array
|
* @param nStartPos where to begin the conversion
|
* @param nNumOfBytes number of bytes to handle
|
* @return the string
|
*/
|
public static String byteArrayToUNCString(byte[] data, int nStartPos, int nNumOfBytes)
|
{
|
// we need two bytes for every character
|
nNumOfBytes &= ~1;
|
|
// enough bytes in the buffer?
|
int nAvailCapacity = data.length - nStartPos;
|
|
if (nAvailCapacity < nNumOfBytes)
|
{
|
nNumOfBytes = nAvailCapacity;
|
}
|
|
StringBuffer sbuf = new StringBuffer();
|
|
sbuf.setLength(nNumOfBytes >> 1);
|
|
int nSBufPos = 0;
|
|
while (nNumOfBytes > 0)
|
{
|
sbuf.setCharAt(nSBufPos++, (char) (((int) data[nStartPos] << 8) | ((int) data[nStartPos + 1] & 0x0ff)));
|
nStartPos += 2;
|
nNumOfBytes -= 2;
|
}
|
|
return sbuf.toString();
|
}
|
|
public static long[] marshalByteArray(byte[] raws, boolean hasSignature)
|
{
|
int remainder = raws.length % 8;
|
ByteBuffer rawData = ByteBuffer.wrap(raws);
|
|
rawData.rewind();
|
rawData.order(ByteOrder.LITTLE_ENDIAN);
|
|
LongBuffer longBuffer = ((ByteBuffer) rawData.rewind()).asLongBuffer();
|
int resultSize = longBuffer.limit() + ((remainder != 0)
|
? 1
|
: 0) + (hasSignature
|
? 1
|
: 0);
|
long[] result = new long[resultSize];
|
int i = 0;
|
|
if (hasSignature)
|
{
|
result[i] = raws.length;
|
i++;
|
}
|
|
while (longBuffer.hasRemaining())
|
{
|
result[i] = longBuffer.get();
|
i++;
|
}
|
|
if (remainder != 0)
|
{
|
int pos = (i - (hasSignature
|
? 1
|
: 0)) * 8;
|
|
// int pos = rawData.position();
|
byte[] temp = new byte[8];
|
|
for (int j = 0; j < remainder; j++)
|
{
|
temp[7 - j] = raws[pos + j];
|
}
|
|
// System.arraycopy(raws, pos, temp, 0, remainder);
|
result[i] = BinConverter.byteArrayToLong(temp, 0);
|
}
|
|
return result;
|
}
|
|
public static byte[] unmarshalByteArray(long[] raws, boolean hasSignature)
|
{
|
LongBuffer longBuffer = LongBuffer.wrap(raws);
|
int resultBufferSize = (raws.length - (hasSignature
|
? 1
|
: 0)) * 8;
|
int resultSize = resultBufferSize;
|
|
if (hasSignature)
|
{
|
resultSize = (int) longBuffer.get();
|
}
|
|
ByteBuffer result = ByteBuffer.allocate(resultBufferSize);
|
|
result.order(ByteOrder.LITTLE_ENDIAN);
|
|
while (longBuffer.hasRemaining())
|
{
|
result.putLong(longBuffer.get());
|
}
|
|
if (resultSize == resultBufferSize)
|
{
|
return result.array();
|
}
|
|
byte[] resultData = new byte[resultSize];
|
|
result.position(0);
|
result.get(resultData, 0, resultSize);
|
|
return resultData;
|
}
|
|
public static long[] marshalCompactByteArray(byte[] raws)
|
{
|
byte[] compactRaws = new byte[raws.length + 2];
|
ByteBuffer bbCompact = ByteBuffer.wrap(compactRaws);
|
bbCompact.order(ByteOrder.LITTLE_ENDIAN);
|
bbCompact.putShort((short) raws.length);
|
bbCompact.put(raws);
|
long[] longData = BinConverter.marshalByteArray(compactRaws, false);
|
return longData;
|
}
|
|
public static byte[] unmarshalCompactByteArray(long[] raws)
|
{
|
byte[] rawData = BinConverter.unmarshalByteArray(raws, false);
|
|
ByteBuffer bbCompact = ByteBuffer.wrap(rawData);
|
bbCompact.order(ByteOrder.LITTLE_ENDIAN);
|
short originSize = bbCompact.getShort();
|
|
byte[] rawOriginData = new byte[originSize];
|
bbCompact.get(rawOriginData, 0, originSize);
|
return rawOriginData;
|
}
|
}
|