All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.util.DataPacker Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

There is a newer version: 1.4.0
Show newest version
/*
 * 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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy