mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-02 17:35:18 +00:00
svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3876 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3925 . git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3927 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
858 lines
19 KiB
Java
858 lines
19 KiB
Java
/*
|
|
* Copyright (C) 2005 Alfresco, Inc.
|
|
*
|
|
* Licensed under the Mozilla Public License version 1.1
|
|
* with a permitted attribution clause. You may obtain a
|
|
* copy of the License at
|
|
*
|
|
* http://www.alfresco.org/legal/license.txt
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
* either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the
|
|
* License.
|
|
*/
|
|
package org.alfresco.filesys.util;
|
|
|
|
/**
|
|
* Data Buffer Class
|
|
* <p>
|
|
* Dynamic buffer for getting/setting data blocks.
|
|
*/
|
|
public class DataBuffer
|
|
{
|
|
|
|
// Constants
|
|
|
|
private static final int DefaultBufferSize = 256;
|
|
|
|
// Data buffer, current position and offset
|
|
|
|
private byte[] m_data;
|
|
private int m_pos;
|
|
private int m_endpos;
|
|
private int m_offset;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public DataBuffer()
|
|
{
|
|
m_data = new byte[DefaultBufferSize];
|
|
m_pos = 0;
|
|
m_offset = 0;
|
|
}
|
|
|
|
/**
|
|
* Create a data buffer to write data to
|
|
*
|
|
* @param siz int
|
|
*/
|
|
public DataBuffer(int siz)
|
|
{
|
|
m_data = new byte[siz];
|
|
m_pos = 0;
|
|
m_offset = 0;
|
|
}
|
|
|
|
/**
|
|
* Create a data buffer to read data from
|
|
*
|
|
* @param buf byte[]
|
|
* @param off int
|
|
* @param len int
|
|
*/
|
|
public DataBuffer(byte[] buf, int off, int len)
|
|
{
|
|
m_data = buf;
|
|
m_offset = off;
|
|
m_pos = off;
|
|
m_endpos = off + len;
|
|
}
|
|
|
|
/**
|
|
* Return the data buffer
|
|
*
|
|
* @return byte[]
|
|
*/
|
|
public final byte[] getBuffer()
|
|
{
|
|
return m_data;
|
|
}
|
|
|
|
/**
|
|
* Return the data length
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getLength()
|
|
{
|
|
if (m_endpos != 0)
|
|
return m_endpos - m_offset;
|
|
return m_pos - m_offset;
|
|
}
|
|
|
|
/**
|
|
* Return the data length in words
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getLengthInWords()
|
|
{
|
|
return getLength() / 2;
|
|
}
|
|
|
|
/**
|
|
* Return the available data length
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getAvailableLength()
|
|
{
|
|
if (m_endpos == 0)
|
|
return -1;
|
|
return m_endpos - m_pos;
|
|
}
|
|
|
|
/**
|
|
* Return the displacement from the start of the buffer to the current buffer position
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getDisplacement()
|
|
{
|
|
return m_pos - m_offset;
|
|
}
|
|
|
|
/**
|
|
* Return the buffer base offset
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getOffset()
|
|
{
|
|
return m_offset;
|
|
}
|
|
|
|
/**
|
|
* Get a byte from the buffer
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getByte()
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
if (m_data.length - m_pos < 1)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the byte value
|
|
|
|
int bval = (int) (m_data[m_pos] & 0xFF);
|
|
m_pos++;
|
|
return bval;
|
|
}
|
|
|
|
/**
|
|
* Get a short from the buffer
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getShort()
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
if (m_data.length - m_pos < 2)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the integer value
|
|
|
|
int sval = (int) DataPacker.getIntelShort(m_data, m_pos);
|
|
m_pos += 2;
|
|
return sval;
|
|
}
|
|
|
|
/**
|
|
* Get an integer from the buffer
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getInt()
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
if (m_data.length - m_pos < 4)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the integer value
|
|
|
|
int ival = DataPacker.getIntelInt(m_data, m_pos);
|
|
m_pos += 4;
|
|
return ival;
|
|
}
|
|
|
|
/**
|
|
* Get a long (64 bit) value from the buffer
|
|
*
|
|
* @return long
|
|
*/
|
|
public final long getLong()
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
if (m_data.length - m_pos < 8)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the long value
|
|
|
|
long lval = DataPacker.getIntelLong(m_data, m_pos);
|
|
m_pos += 8;
|
|
return lval;
|
|
}
|
|
|
|
/**
|
|
* Get a string from the buffer
|
|
*
|
|
* @param uni boolean
|
|
* @return String
|
|
*/
|
|
public final String getString(boolean uni)
|
|
{
|
|
return getString(255, uni);
|
|
}
|
|
|
|
/**
|
|
* Get a string from the buffer
|
|
*
|
|
* @param maxlen int
|
|
* @param uni boolean
|
|
* @return String
|
|
*/
|
|
public final String getString(int maxlen, boolean uni)
|
|
{
|
|
|
|
// Check for Unicode or ASCII
|
|
|
|
String ret = null;
|
|
int availLen = -1;
|
|
|
|
if (uni)
|
|
{
|
|
|
|
// Word align the current buffer position, calculate the available
|
|
// length
|
|
|
|
m_pos = DataPacker.wordAlign(m_pos);
|
|
availLen = (m_endpos - m_pos) / 2;
|
|
if (availLen < maxlen)
|
|
maxlen = availLen;
|
|
|
|
ret = DataPacker.getUnicodeString(m_data, m_pos, maxlen);
|
|
if (ret != null) {
|
|
if ( ret.length() < maxlen)
|
|
m_pos += (ret.length() * 2) + 2;
|
|
else
|
|
m_pos += maxlen * 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Calculate the available length
|
|
|
|
availLen = m_endpos - m_pos;
|
|
if (availLen < maxlen)
|
|
maxlen = availLen;
|
|
|
|
// Unpack the ASCII string
|
|
|
|
ret = DataPacker.getString(m_data, m_pos, maxlen);
|
|
if (ret != null) {
|
|
if ( ret.length() < maxlen)
|
|
m_pos += ret.length() + 1;
|
|
else
|
|
m_pos += maxlen;
|
|
}
|
|
}
|
|
|
|
// Return the string
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Get a short from the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @return int
|
|
*/
|
|
public final int getShortAt(int idx)
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
int pos = m_offset + (idx * 2);
|
|
if (m_data.length - pos < 2)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the integer value
|
|
|
|
int sval = (int) DataPacker.getIntelShort(m_data, pos) & 0xFFFF;
|
|
return sval;
|
|
}
|
|
|
|
/**
|
|
* Get an integer from the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @return int
|
|
*/
|
|
public final int getIntAt(int idx)
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
int pos = m_offset + (idx * 2);
|
|
if (m_data.length - pos < 4)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the integer value
|
|
|
|
int ival = DataPacker.getIntelInt(m_data, pos);
|
|
return ival;
|
|
}
|
|
|
|
/**
|
|
* Get a long (64 bit) value from the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @return long
|
|
*/
|
|
public final long getLongAt(int idx)
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
int pos = m_offset + (idx * 2);
|
|
if (m_data.length - pos < 8)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Unpack the long value
|
|
|
|
long lval = DataPacker.getIntelLong(m_data, pos);
|
|
return lval;
|
|
}
|
|
|
|
/**
|
|
* Skip over a number of bytes
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void skipBytes(int cnt)
|
|
{
|
|
|
|
// Check if there is enough data in the buffer
|
|
|
|
if (m_data.length - m_pos < cnt)
|
|
throw new ArrayIndexOutOfBoundsException("End of data buffer");
|
|
|
|
// Skip bytes
|
|
|
|
m_pos += cnt;
|
|
}
|
|
|
|
/**
|
|
* Return the data position
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getPosition()
|
|
{
|
|
return m_pos;
|
|
}
|
|
|
|
/**
|
|
* Set the read/write buffer position
|
|
*
|
|
* @param pos int
|
|
*/
|
|
public final void setPosition(int pos)
|
|
{
|
|
m_pos = pos;
|
|
}
|
|
|
|
/**
|
|
* Set the end of buffer position, and reset the read position to the beginning of the buffer
|
|
*/
|
|
public final void setEndOfBuffer()
|
|
{
|
|
m_endpos = m_pos;
|
|
m_pos = m_offset;
|
|
}
|
|
|
|
/**
|
|
* Set the data length
|
|
*
|
|
* @param len int
|
|
*/
|
|
public final void setLength(int len)
|
|
{
|
|
m_pos = m_offset + len;
|
|
}
|
|
|
|
/**
|
|
* Append a byte value to the buffer
|
|
*
|
|
* @param bval int
|
|
*/
|
|
public final void putByte(int bval)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < 1)
|
|
extendBuffer();
|
|
|
|
// Pack the byte value
|
|
|
|
m_data[m_pos++] = (byte) (bval & 0xFF);
|
|
}
|
|
|
|
/**
|
|
* Append a short value to the buffer
|
|
*
|
|
* @param sval int
|
|
*/
|
|
public final void putShort(int sval)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < 2)
|
|
extendBuffer();
|
|
|
|
// Pack the short value
|
|
|
|
DataPacker.putIntelShort(sval, m_data, m_pos);
|
|
m_pos += 2;
|
|
}
|
|
|
|
/**
|
|
* Append an integer to the buffer
|
|
*
|
|
* @param ival int
|
|
*/
|
|
public final void putInt(int ival)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < 4)
|
|
extendBuffer();
|
|
|
|
// Pack the integer value
|
|
|
|
DataPacker.putIntelInt(ival, m_data, m_pos);
|
|
m_pos += 4;
|
|
}
|
|
|
|
/**
|
|
* Append a long to the buffer
|
|
*
|
|
* @param lval long
|
|
*/
|
|
public final void putLong(long lval)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < 8)
|
|
extendBuffer();
|
|
|
|
// Pack the long value
|
|
|
|
DataPacker.putIntelLong(lval, m_data, m_pos);
|
|
m_pos += 8;
|
|
}
|
|
|
|
/**
|
|
* Append a short value to the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @param sval int
|
|
*/
|
|
public final void putShortAt(int idx, int sval)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
int pos = m_offset + (idx * 2);
|
|
if (m_data.length - pos < 2)
|
|
extendBuffer();
|
|
|
|
// Pack the short value
|
|
|
|
DataPacker.putIntelShort(sval, m_data, pos);
|
|
}
|
|
|
|
/**
|
|
* Append an integer to the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @param ival int
|
|
*/
|
|
public final void putIntAt(int idx, int ival)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
int pos = m_offset = (idx * 2);
|
|
if (m_data.length - pos < 4)
|
|
extendBuffer();
|
|
|
|
// Pack the integer value
|
|
|
|
DataPacker.putIntelInt(ival, m_data, pos);
|
|
}
|
|
|
|
/**
|
|
* Append a long to the buffer at the specified index
|
|
*
|
|
* @param idx int
|
|
* @param lval long
|
|
*/
|
|
public final void putLongAt(int idx, int lval)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
int pos = m_offset = (idx * 2);
|
|
if (m_data.length - pos < 8)
|
|
extendBuffer();
|
|
|
|
// Pack the long value
|
|
|
|
DataPacker.putIntelLong(lval, m_data, pos);
|
|
}
|
|
|
|
/**
|
|
* Append a string to the buffer
|
|
*
|
|
* @param str String
|
|
* @param uni boolean
|
|
*/
|
|
public final void putString(String str, boolean uni)
|
|
{
|
|
putString(str, uni, true);
|
|
}
|
|
|
|
/**
|
|
* Append a string to the buffer
|
|
*
|
|
* @param str String
|
|
* @param uni boolean
|
|
* @param nulTerm boolean
|
|
*/
|
|
public final void putString(String str, boolean uni, boolean nulTerm)
|
|
{
|
|
|
|
// Check for Unicode or ASCII
|
|
|
|
if (uni)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
int bytLen = str.length() * 2;
|
|
if ( nulTerm)
|
|
bytLen += 2;
|
|
if ((m_data.length - m_pos) < (bytLen + 4))
|
|
extendBuffer(bytLen + 4);
|
|
|
|
// Word align the buffer position, pack the Unicode string
|
|
|
|
m_pos = DataPacker.wordAlign(m_pos);
|
|
DataPacker.putUnicodeString(str, m_data, m_pos, nulTerm);
|
|
m_pos += (str.length() * 2);
|
|
if (nulTerm)
|
|
m_pos += 2;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < str.length())
|
|
extendBuffer(str.length() + 2);
|
|
|
|
// Pack the ASCII string
|
|
|
|
DataPacker.putString(str, m_data, m_pos, nulTerm);
|
|
m_pos += str.length();
|
|
if (nulTerm)
|
|
m_pos++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Append a fixed length string to the buffer
|
|
*
|
|
* @param str String
|
|
* @param len int
|
|
*/
|
|
public final void putFixedString(String str, int len)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < str.length())
|
|
extendBuffer(str.length() + 2);
|
|
|
|
// Pack the ASCII string
|
|
|
|
DataPacker.putString(str, len, m_data, m_pos);
|
|
m_pos += len;
|
|
}
|
|
|
|
/**
|
|
* Append a string to the buffer at the specified buffer position
|
|
*
|
|
* @param str String
|
|
* @param pos int
|
|
* @param uni boolean
|
|
* @param nulTerm boolean
|
|
* @return int
|
|
*/
|
|
public final int putStringAt(String str, int pos, boolean uni, boolean nulTerm)
|
|
{
|
|
|
|
// Check for Unicode or ASCII
|
|
|
|
int retPos = -1;
|
|
|
|
if (uni)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
int bytLen = str.length() * 2;
|
|
if (m_data.length - pos < bytLen)
|
|
extendBuffer(bytLen + 4);
|
|
|
|
// Word align the buffer position, pack the Unicode string
|
|
|
|
pos = DataPacker.wordAlign(pos);
|
|
retPos = DataPacker.putUnicodeString(str, m_data, pos, nulTerm);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - pos < str.length())
|
|
extendBuffer(str.length() + 2);
|
|
|
|
// Pack the ASCII string
|
|
|
|
retPos = DataPacker.putString(str, m_data, pos, nulTerm);
|
|
}
|
|
|
|
// Return the end of string buffer position
|
|
|
|
return retPos;
|
|
}
|
|
|
|
/**
|
|
* Append a fixed length string to the buffer at the specified position
|
|
*
|
|
* @param str String
|
|
* @param len int
|
|
* @param pos int
|
|
* @return int
|
|
*/
|
|
public final int putFixedStringAt(String str, int len, int pos)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - pos < str.length())
|
|
extendBuffer(str.length() + 2);
|
|
|
|
// Pack the ASCII string
|
|
|
|
return DataPacker.putString(str, len, m_data, pos);
|
|
}
|
|
|
|
/**
|
|
* Append a string pointer to the specified buffer offset
|
|
*
|
|
* @param off int
|
|
*/
|
|
public final void putStringPointer(int off)
|
|
{
|
|
|
|
// Calculate the offset from the start of the data buffer to the string
|
|
// position
|
|
|
|
DataPacker.putIntelInt(off - m_offset, m_data, m_pos);
|
|
m_pos += 4;
|
|
}
|
|
|
|
/**
|
|
* Append zero bytes to the buffer
|
|
*
|
|
* @param cnt int
|
|
*/
|
|
public final void putZeros(int cnt)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < cnt)
|
|
extendBuffer(cnt);
|
|
|
|
// Pack the zero bytes
|
|
|
|
for (int i = 0; i < cnt; i++)
|
|
m_data[m_pos++] = 0;
|
|
}
|
|
|
|
/**
|
|
* Word align the buffer position
|
|
*/
|
|
public final void wordAlign()
|
|
{
|
|
m_pos = DataPacker.wordAlign(m_pos);
|
|
}
|
|
|
|
/**
|
|
* Longword align the buffer position
|
|
*/
|
|
public final void longwordAlign()
|
|
{
|
|
m_pos = DataPacker.longwordAlign(m_pos);
|
|
}
|
|
|
|
/**
|
|
* Append a raw data block to the data buffer
|
|
*
|
|
* @param buf byte[]
|
|
* @param off int
|
|
* @param len int
|
|
*/
|
|
public final void appendData(byte[] buf, int off, int len)
|
|
{
|
|
|
|
// Check if there is enough space in the buffer
|
|
|
|
if (m_data.length - m_pos < len)
|
|
extendBuffer(len);
|
|
|
|
// Copy the data to the buffer and update the current write position
|
|
|
|
System.arraycopy(buf, off, m_data, m_pos, len);
|
|
m_pos += len;
|
|
}
|
|
|
|
/**
|
|
* Copy all data from the data buffer to the user buffer, and update the read position
|
|
*
|
|
* @param buf byte[]
|
|
* @param off int
|
|
* @return int
|
|
*/
|
|
public final int copyData(byte[] buf, int off)
|
|
{
|
|
return copyData(buf, off, getLength());
|
|
}
|
|
|
|
/**
|
|
* Copy data from the data buffer to the user buffer, and update the current read position.
|
|
*
|
|
* @param buf byte[]
|
|
* @param off int
|
|
* @param cnt int
|
|
* @return int
|
|
*/
|
|
public final int copyData(byte[] buf, int off, int cnt)
|
|
{
|
|
|
|
// Check if there is any more data to copy
|
|
|
|
if (m_pos == m_endpos)
|
|
return 0;
|
|
|
|
// Calculate the amount of data to copy
|
|
|
|
int siz = m_endpos - m_pos;
|
|
if (siz > cnt)
|
|
siz = cnt;
|
|
|
|
// Copy the data to the user buffer and update the current read position
|
|
|
|
System.arraycopy(m_data, m_pos, buf, off, siz);
|
|
m_pos += siz;
|
|
|
|
// Return the amount of data copied
|
|
|
|
return siz;
|
|
}
|
|
|
|
/**
|
|
* Extend the data buffer by the specified amount
|
|
*
|
|
* @param ext int
|
|
*/
|
|
private final void extendBuffer(int ext)
|
|
{
|
|
|
|
// Create a new buffer of the required size
|
|
|
|
byte[] newBuf = new byte[m_data.length + ext];
|
|
|
|
// Copy the data from the current buffer to the new buffer
|
|
|
|
System.arraycopy(m_data, 0, newBuf, 0, m_data.length);
|
|
|
|
// Set the new buffer to be the main buffer
|
|
|
|
m_data = newBuf;
|
|
}
|
|
|
|
/**
|
|
* Extend the data buffer, double the currently allocated buffer size
|
|
*/
|
|
private final void extendBuffer()
|
|
{
|
|
extendBuffer(m_data.length * 2);
|
|
}
|
|
|
|
/**
|
|
* Return the data buffer details as a string
|
|
*
|
|
* @return String
|
|
*/
|
|
public String toString()
|
|
{
|
|
StringBuffer str = new StringBuffer();
|
|
|
|
str.append("[data=");
|
|
str.append(m_data);
|
|
str.append(",");
|
|
str.append(m_pos);
|
|
str.append("/");
|
|
str.append(m_offset);
|
|
str.append("/");
|
|
str.append(getLength());
|
|
str.append("]");
|
|
|
|
return str.toString();
|
|
}
|
|
}
|