Derek Hulley d4947ef511 Merged V1.4 to HEAD
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
2006-09-26 00:02:52 +00:00

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();
}
}