org.filesys.util.DataPacker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfileserver Show documentation
Show all versions of jfileserver Show documentation
Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems
/*
* Copyright (C) 2006-2010 Alfresco Software Limited.
* Copyright (C) 2018 GK Spencer
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
package org.filesys.util;
/**
* The data packing class is a static class that is used to pack and unpack
* basic data types to/from network byte order and Intel byte order.
*
* @author gkspencer
*/
public final class DataPacker {
// Flag to indicate the byte order of the platform that we are currently
// running on.
private static boolean bigEndian = false;
/**
* Return the current endian setting.
*
* @return true if the system is big endian, else false.
*/
public final static boolean isBigEndian() {
return bigEndian;
}
/**
* Unpack a null terminated data string from the data buffer.
*
* @param typ Data type, as specified by SMBDataType.
* @param bytarray Byte array to unpack the string value from.
* @param pos Offset to start unpacking the string value.
* @param maxlen Maximum length of data to be searched for a null character.
* @param uni String is V1Unicode if true, else ASCII
* @return String, else null if the terminating null character was not found.
*/
public final static String getDataString(char typ, byte[] bytarray, int pos, int maxlen, boolean uni) {
// Check if the data string has the required data type
if (bytarray[pos++] == (byte) typ) {
// Extract the null terminated string
if (uni == true)
return getUnicodeString(bytarray, wordAlign(pos), maxlen / 2);
else
return getString(bytarray, pos, maxlen - 1);
}
// Invalid data type
return null;
}
/**
* Unpack a 32-bit integer.
*
* @param buf Byte buffer containing the integer to be unpacked.
* @param pos Position within the buffer that the integer is stored.
* @return The unpacked 32-bit integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static int getInt(byte[] buf, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough
if (buf.length < pos + 3)
throw new IndexOutOfBoundsException();
// Unpack the 32-bit value
int i1 = (int) buf[pos] & 0xFF;
int i2 = (int) buf[pos + 1] & 0xFF;
int i3 = (int) buf[pos + 2] & 0xFF;
int i4 = (int) buf[pos + 3] & 0xFF;
int iVal = (i1 << 24) + (i2 << 16) + (i3 << 8) + i4;
// Return the unpacked value
return iVal;
}
/**
* Unpack a 32-bit integer that is stored in Intel format.
*
* @param bytarray Byte array containing the Intel integer to be unpacked.
* @param pos Offset that the Intel integer is stored within the byte array.
* @return Unpacked integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static int getIntelInt(byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to restore the int
if (bytarray.length < pos + 3)
throw new IndexOutOfBoundsException();
// Determine the byte ordering for this platform, and restore the int
int iVal = 0;
// Restore the int value from the byte array
int i1 = (int) bytarray[pos + 3] & 0xFF;
int i2 = (int) bytarray[pos + 2] & 0xFF;
int i3 = (int) bytarray[pos + 1] & 0xFF;
int i4 = (int) bytarray[pos] & 0xFF;
iVal = (i1 << 24) + (i2 << 16) + (i3 << 8) + i4;
// Return the int value
return iVal;
}
/**
* Unpack a 64-bit long.
*
* @param buf Byte buffer containing the integer to be unpacked.
* @param pos Position within the buffer that the integer is stored.
* @return The unpacked 64-bit long value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static long getLong(byte[] buf, int pos)
throws IndexOutOfBoundsException {
// Check if the byte array is long enough to restore the long
if (buf.length < pos + 7)
throw new IndexOutOfBoundsException();
// Restore the long value from the byte array
long lVal = 0L;
for (int i = 0; i < 8; i++) {
// Get the current byte, shift the value and add to the return value
long curVal = (long) buf[pos + i] & 0xFF;
curVal = curVal << ((7 - i) * 8);
lVal += curVal;
}
// Return the long value
return lVal;
}
/**
* Unpack a 64-bit integer that is stored in Intel format.
*
* @param bytarray Byte array containing the Intel long to be unpacked.
* @param pos Offset that the Intel integer is stored within the byte array.
* @return Unpacked long value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static long getIntelLong(byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to restore the long
if (bytarray.length < pos + 7)
throw new IndexOutOfBoundsException();
// Restore the long value from the byte array
long lVal = 0L;
for (int i = 0; i < 8; i++) {
// Get the current byte, shift the value and add to the return value
long curVal = (long) bytarray[pos + i] & 0xFF;
curVal = curVal << (i * 8);
lVal += curVal;
}
// Return the long value
return lVal;
}
/**
* Unpack a 16-bit value that is stored in Intel format.
*
* @param bytarray Byte array containing the short value to be unpacked.
* @param pos Offset to start unpacking the short value.
* @return Unpacked short value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static int getIntelShort(byte[] bytarray, int pos)
throws IndexOutOfBoundsException {
// Check if the byte array is long enough to restore the int
if (bytarray.length < pos)
throw new IndexOutOfBoundsException();
// Restore the short value from the byte array
int sVal = (((int) bytarray[pos + 1] << 8) + ((int) bytarray[pos] & 0xFF));
// Return the short value
return sVal & 0xFFFF;
}
/**
* Unpack a 16-bit value.
*
* @param bytarray Byte array containing the short to be unpacked.
* @param pos Offset within the byte array that the short is stored.
* @return Unpacked short value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static int getShort(byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to restore the int
if (bytarray.length < pos)
throw new IndexOutOfBoundsException();
// Determine the byte ordering for this platform, and restore the short
int sVal = 0;
if (bigEndian == true) {
// Big endian
sVal = ((((int) bytarray[pos + 1]) << 8) + ((int) bytarray[pos] & 0xFF));
}
else {
// Little endian
sVal = ((((int) bytarray[pos]) << 8) + ((int) bytarray[pos + 1] & 0xFF));
}
// Return the short value
return sVal & 0xFFFF;
}
/**
* Unpack a null terminated string from the data buffer.
*
* @param bytarray Byte array to unpack the string value from.
* @param pos Offset to start unpacking the string value.
* @param maxlen Maximum length of data to be searched for a null character.
* @return String, else null if the terminating null character was
* not found.
*/
public final static String getString(byte[] bytarray, int pos, int maxlen) {
// Search for the trailing null
int maxpos = pos + maxlen;
int endpos = pos;
while (bytarray[endpos] != 0x00 && endpos < maxpos)
endpos++;
// Check if we reached the end of the buffer
if (endpos <= maxpos)
return new String(bytarray, pos, endpos - pos);
return null;
}
/**
* Unpack a null terminated string from the data buffer. The string may be ASCII or V1Unicode.
*
* @param bytarray Byte array to unpack the string value from.
* @param pos Offset to start unpacking the string value.
* @param maxlen Maximum length of data to be searched for a null character.
* @param isUni V1Unicode string if true, else ASCII string
* @return String, else null if the terminating null character was not found.
*/
public final static String getString(byte[] bytarray, int pos, int maxlen, boolean isUni) {
// Get a string from the buffer
String str = null;
if (isUni)
str = getUnicodeString(bytarray, pos, maxlen);
else
str = getString(bytarray, pos, maxlen);
// return the string
return str;
}
/**
* Unpack a null terminated V1Unicode string from the data buffer.
*
* @param byt Byte array to unpack the string value from.
* @param pos Offset to start unpacking the string value.
* @param maxlen Maximum length of data to be searched for a null character.
* @return String, else null if the terminating null character was not found.
*/
public final static String getUnicodeString(byte[] byt, int pos, int maxlen) {
// Check for an empty string
if (maxlen == 0)
return "";
// Search for the trailing null
int maxpos = pos + (maxlen * 2);
int endpos = pos;
char[] chars = new char[maxlen];
int cpos = 0;
char curChar;
do {
// Get a Unicode character from the buffer
curChar = (char) (((byt[endpos + 1] & 0xFF) << 8) + (byt[endpos] & 0xFF));
// Add the character to the array
chars[cpos++] = curChar;
// Update the buffer pointer
endpos += 2;
} while (curChar != 0 && endpos < maxpos);
// Check if we reached the end of the buffer
if (endpos <= maxpos) {
if (curChar == 0)
cpos--;
return new String(chars, 0, cpos);
}
return null;
}
/**
* Pack a 32-bit integer into the supplied byte buffer.
*
* @param val Integer value to be packed.
* @param bytarray Byte buffer to pack the integer value into.
* @param pos Offset to start packing the integer value.
* @throws IndexOutOfBoundsException If the buffer does not have enough space.
*/
public final static void putInt(int val, byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the int
if (bytarray.length < pos + 3)
throw new IndexOutOfBoundsException();
// Pack the integer value
bytarray[pos] = (byte) ((val >> 24) & 0xFF);
bytarray[pos + 1] = (byte) ((val >> 16) & 0xFF);
bytarray[pos + 2] = (byte) ((val >> 8) & 0xFF);
bytarray[pos + 3] = (byte) (val & 0xFF);
}
/**
* Pack an 32-bit integer value in Intel format.
*
* @param val Integer value to be packed.
* @param bytarray Byte array to pack the value into.
* @param pos Offset to start packing the integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putIntelInt(int val, byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the int
if (bytarray.length < pos + 3)
throw new IndexOutOfBoundsException();
// Store the int value in the byte array
bytarray[pos + 3] = (byte) ((val >> 24) & 0xFF);
bytarray[pos + 2] = (byte) ((val >> 16) & 0xFF);
bytarray[pos + 1] = (byte) ((val >> 8) & 0xFF);
bytarray[pos] = (byte) (val & 0xFF);
}
/**
* Pack a 64-bit integer value into the buffer
*
* @param val Integer value to be packed.
* @param bytarray Byte array to pack the value into.
* @param pos Offset to start packing the integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putLong(long val, byte[] bytarray, int pos)
throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the int
if (bytarray.length < pos + 7)
throw new IndexOutOfBoundsException();
// Store the long value in the byte array
bytarray[pos] = (byte) ((val >> 56) & 0xFF);
bytarray[pos + 1] = (byte) ((val >> 48) & 0xFF);
bytarray[pos + 2] = (byte) ((val >> 40) & 0xFF);
bytarray[pos + 3] = (byte) ((val >> 32) & 0xFF);
bytarray[pos + 4] = (byte) ((val >> 24) & 0xFF);
bytarray[pos + 5] = (byte) ((val >> 16) & 0xFF);
bytarray[pos + 6] = (byte) ((val >> 8) & 0xFF);
bytarray[pos + 7] = (byte) (val & 0xFF);
}
/**
* Pack a 64-bit integer value in Intel format.
*
* @param val Integer value to be packed.
* @param bytarray Byte array to pack the value into.
* @param pos Offset to start packing the integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putIntelLong(long val, byte[] bytarray, int pos)
throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the int
if (bytarray.length < pos + 7)
throw new IndexOutOfBoundsException();
// Store the long value in the byte array
bytarray[pos + 7] = (byte) ((val >> 56) & 0xFF);
bytarray[pos + 6] = (byte) ((val >> 48) & 0xFF);
bytarray[pos + 5] = (byte) ((val >> 40) & 0xFF);
bytarray[pos + 4] = (byte) ((val >> 32) & 0xFF);
bytarray[pos + 3] = (byte) ((val >> 24) & 0xFF);
bytarray[pos + 2] = (byte) ((val >> 16) & 0xFF);
bytarray[pos + 1] = (byte) ((val >> 8) & 0xFF);
bytarray[pos] = (byte) (val & 0xFF);
}
/**
* Pack a 64-bit integer value in Intel format.
*
* @param val Integer value to be packed.
* @param bytarray Byte array to pack the value into.
* @param pos Offset to start packing the integer value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putIntelLong(int val, byte[] bytarray, int pos)
throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the int
if (bytarray.length < pos + 7)
throw new IndexOutOfBoundsException();
// Store the int value in the byte array
bytarray[pos + 7] = (byte) 0;
bytarray[pos + 6] = (byte) 0;
bytarray[pos + 5] = (byte) 0;
bytarray[pos + 4] = (byte) 0;
bytarray[pos + 3] = (byte) ((val >> 24) & 0xFF);
bytarray[pos + 2] = (byte) ((val >> 16) & 0xFF);
bytarray[pos + 1] = (byte) ((val >> 8) & 0xFF);
bytarray[pos] = (byte) (val & 0xFF);
}
/**
* Pack a 16 bit value in Intel byte order.
*
* @param val Short value to be packed.
* @param bytarray Byte array to pack the short value into.
* @param pos Offset to start packing the short value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putIntelShort(int val, byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the short
if (bytarray.length < pos + 1)
throw new IndexOutOfBoundsException();
// Pack the short value
bytarray[pos + 1] = (byte) ((val >> 8) & 0xFF);
bytarray[pos] = (byte) (val & 0xFF);
}
/**
* Pack a 16-bit value into the supplied byte buffer.
*
* @param val Short value to be packed.
* @param bytarray Byte array to pack the short value into.
* @param pos Offset to start packing the short value.
* @throws IndexOutOfBoundsException If there is not enough data in the buffer.
*/
public final static void putShort(int val, byte[] bytarray, int pos) throws IndexOutOfBoundsException {
// Check if the byte array is long enough to store the short
if (bytarray.length < pos + 1)
throw new IndexOutOfBoundsException();
// Pack the short value
bytarray[pos] = (byte) ((val >> 8) & 0xFF);
bytarray[pos + 1] = (byte) (val & 0xFF);
}
/**
* Pack a string into a data buffer
*
* @param str String to be packed into the buffer
* @param bytarray Byte array to pack the string into
* @param pos Position to start packing the string
* @param nullterm true if the string should be null terminated, else false
* @return The ending buffer position
*/
public final static int putString(String str, byte[] bytarray, int pos, boolean nullterm) {
// Get the string as a byte array
byte[] byts = str.getBytes();
// Pack the data bytes
int bufpos = pos;
for (int i = 0; i < byts.length; i++)
bytarray[bufpos++] = byts[i];
// Null terminate the string, if required
if (nullterm == true)
bytarray[bufpos++] = 0;
// Return the next free buffer position
return bufpos;
}
/**
* Pack a string into a data buffer
*
* @param str String to be packed into the buffer
* @param fldLen Field length, will be space padded if short
* @param bytarray Byte array to pack the string into
* @param pos Position to start packing the string
* @return The ending buffer position
*/
public final static int putString(String str, int fldLen, byte[] bytarray, int pos) {
// Get the string as a byte array
byte[] byts = str.getBytes();
// Pack the data bytes
int bufpos = pos;
int idx = 0;
while (idx < fldLen) {
if (idx < byts.length)
bytarray[bufpos++] = byts[idx];
else
bytarray[bufpos++] = (byte) 0;
idx++;
}
// Return the next free buffer position
return bufpos;
}
/**
* Pack a string into a data buffer. The string may be ASCII or V1Unicode.
*
* @param str String to be packed into the buffer
* @param bytarray Byte array to pack the string into
* @param pos Position to start packing the string
* @param nullterm true if the string should be null terminated, else false
* @param isUni true if the string should be packed as V1Unicode, false to pack as ASCII
* @return The ending buffer position
*/
public final static int putString(String str, byte[] bytarray, int pos, boolean nullterm, boolean isUni) {
// Pack the string
int newpos = -1;
if (isUni)
newpos = putUnicodeString(str, bytarray, pos, nullterm);
else
newpos = putString(str, bytarray, pos, nullterm);
// Return the end of string buffer position
return newpos;
}
/**
* Pack a V1Unicode string into a data buffer
*
* @param str String to be packed into the buffer
* @param bytarray Byte array to pack the string into
* @param pos Position to start packing the string
* @param nullterm true if the string should be null terminated, else false
* @return The ending buffer position
*/
public final static int putUnicodeString(String str, byte[] bytarray, int pos, boolean nullterm) {
// Pack the data bytes
int bufpos = pos;
for (int i = 0; i < str.length(); i++) {
// Get the current character from the string
char ch = str.charAt(i);
// Pack the unicode character
bytarray[bufpos++] = (byte) (ch & 0xFF);
bytarray[bufpos++] = (byte) ((ch & 0xFF00) >> 8);
}
// Null terminate the string, if required
if (nullterm == true) {
bytarray[bufpos++] = 0;
bytarray[bufpos++] = 0;
}
// Return the next free buffer position
return bufpos;
}
/**
* Pack nulls into the buffer.
*
* @param buf Buffer to pack data into.
* @param pos Position to start packing.
* @param cnt Number of nulls to pack.
* @throws ArrayIndexOutOfBoundsException If the buffer does not have enough space.
*/
public final static void putZeros(byte[] buf, int pos, int cnt) throws ArrayIndexOutOfBoundsException {
// Check if the buffer is big enough
if (buf.length < (pos + cnt))
throw new ArrayIndexOutOfBoundsException();
// Pack the nulls
for (int i = 0; i < cnt; i++)
buf[pos + i] = 0;
}
/**
* Align a buffer offset on a word boundary
*
* @param pos int
* @return int
*/
public final static int wordAlign(int pos) {
return (pos + 1) & 0xFFFFFFFE;
}
/**
* Align a buffer offset on an int boundary
*
* @param pos int
* @return int
*/
public final static int intAlign(int pos) {
return (pos + 3) & 0xFFFFFFFC;
}
/**
* Align a buffer offset on a longword boundary
*
* @param pos int
* @return int
*/
public final static int longwordAlign(int pos) {
return (pos + 7) & 0xFFFFFFF8;
}
/**
* Calculate the string length in bytes
*
* @param str String
* @param uni boolean
* @param nul boolean
* @return int
*/
public final static int getStringLength(String str, boolean uni, boolean nul) {
// Calculate the string length in bytes
int len = str.length();
if (nul)
len += 1;
if (uni)
len *= 2;
return len;
}
/**
* Calculate the new buffer position after the specified string and encoding (ASCII or V1Unicode)
*
* @param pos int
* @param str String
* @param uni boolean
* @param nul boolean
* @return int
*/
public final static int getBufferPosition(int pos, String str, boolean uni, boolean nul) {
// Calculate the new buffer position
int len = str.length();
if (nul)
len += 1;
if (uni)
len *= 2;
return pos + len;
}
}