Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 1997-2004 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.io;
/**
* This class provides a byte buffer, that is unlimited in capacity.
*
* @version $Revision: 1.6 $, $Date: 2004-08-22 06:56:09 +0200 (Sun, 22 Aug 2004) $
* @author ralph
* @since antbear
* @audience wad
*/
public class ByteBuffer {
/** the total length of the valid data in the buffer */
private int length = 0;
/** the first chunk of the list */
private Chunk firstChunk;
/** the last chunk of the list */
private Chunk lastChunk;
/**
* Creates a new ByteBuffer-object
*/
public ByteBuffer() {
reset();
}
/**
* Resets this ByteBuffer and clears the internal storage.
*/
public void reset() {
firstChunk = lastChunk = new Chunk();
length=0;
}
/**
* Returns the entire buffer.
* @return a new byte buffer.
*/
public byte[] get() {
byte[] ret = new byte[length];
get(ret, 0, length);
return ret;
}
/**
* Returns up to num bytes from this ByteBuffer.
*
* @param num the number of bytes to return
* @return a new buffer with the containig bytes
*/
public byte[] get(int num) {
byte[] ret = new byte[Math.min(num, length)];
get(ret, 0, ret.length);
return ret;
}
/**
* Transferse up to num bytes to the output buffer
* starting at offset.
*
* @param output the output buffer
* @param offset the offset
* @param length the number of bytes to transfer
*
* @return the number of bytes written
*/
public int get(byte[] output, int offset, int num) {
// limit num
if (num > length) {
num = length;
}
int total = num;
// transfer bytes
while (num > 0) {
// transfer bytes from the chunk
int rd = firstChunk.get(output, offset, num);
offset+=rd;
num-=rd;
length-=rd;
if (firstChunk.isEmpty() && firstChunk.next!=null) {
firstChunk = firstChunk.next;
}
}
return total;
}
/**
* Puts length bytes from input starting at
* offset to the end of this buffer.
*
* @param input the input buffer
* @param offset the offset into the input buffer
* @param length the number of bytes to transfer
*/
public void put(byte[] input, int offset, int len) {
if (len > 0) {
lastChunk = lastChunk.put(input, offset, len);
length += len;
}
}
/**
* Puts the bytes at the end of the buffer
* @param bytes the bytes to add to the buffer
*/
public void put(byte[] bytes) {
if (bytes!=null) {
put(bytes, 0, bytes.length);
}
}
/**
* Puts one byte at the end of the buffer
* to be optimized.
*/
public void put(byte b) {
lastChunk = lastChunk.put(b);
length++;
}
/**
* Returns the number of bytes in the queue.
*/
public int length() {
return length;
}
/**
* Checks if the buffer is empty.
* @return true if the buffer is empty;
* false otherwise.
*/
public boolean isEmpty() {
return length==0;
}
/**
* Internal class that holds chunks of byte-arrays
*/
private static class Chunk {
/** the minumim size of a chunk */
private static final int SIZE = 4096;
/** the bytes in this array */
private byte[] bytes;
/** the offset to valid data */
private int start;
/** the length of valid data */
private int end;
/** the next chunk in the list */
private Chunk next;
/**
* Creates an empty Chunk.
*/
private Chunk() {
this(null, 0, 0);
}
/**
* Creates a Chunk containing one byte
*/
private Chunk(byte b) {
this(null, 0, 0);
bytes[start]=b;
end++;
}
/**
* Creates a new Chunk with the given byte array.
*
* @param input the byte array
*/
private Chunk(byte[] input) {
this(input, 0, input.length);
}
/**
* Creates a new Chunk out of a given byte array.
*
* @param input the input buffer
* @param offset the offset in the buffer
* @param len the length in the buffer
*/
private Chunk(byte[] input, int offset, int len) {
bytes = new byte[Math.max(len, SIZE)];
start = 0;
end = len;
if (len>0) {
System.arraycopy(input, offset, bytes, 0, len);
}
}
/**
* Copies at most len bytes from the beginning of the internal
* storage to the output starting at offset.
* It also adapts the internal range of valid data.
*
* @param output the output buffer
* @param offset the offset in the output buffer
* @param len the number of bytes to transfer
*
* @return the number of transfered bytes.
*/
private int get(byte[] output, int offset, int len) {
if (len > length()) {
len = length();
}
System.arraycopy(bytes, start, output, offset, len);
start += len;
if (start==end) {
start=end=0;
}
return len;
}
/**
* Copies len bytes at the end of the internal storage.
* and creates new successors if neccesairy.
*
* @param input the input buffer
* @param offset the offset in the input buffer
* @param len the length of valid data in the input buffer
*
* @return the last chunk
*/
private Chunk put(byte[] input, int offset, int len) {
if (len < bytes.length - end) {
System.arraycopy(input, offset, bytes, end, len);
end+=len;
return this;
} else {
int num = bytes.length - end;
System.arraycopy(input, offset, bytes, end, num);
end = bytes.length;
Chunk cnk = new Chunk(input, offset+num, len-num);
cnk.next = this.next;
this.next = cnk;
return cnk;
}
}
/**
* Puts one byte at the end of the internal buffer. If neccessairy, it
* create a successor to store the byte.
*
* @param b the byte to append
* @return the last chunk
*/
private Chunk put(byte b) {
if (1 < bytes.length - end) {
bytes[end++] = b;
return this;
} else {
Chunk cnk = new Chunk(b);
cnk.next = this.next;
this.next = cnk;
return cnk;
}
}
/**
* Checks if this chunk is empty.
* @return true if this chunk is empty;
* false otherwise.
*/
private boolean isEmpty() {
return start==end;
}
/**
* Returns the length of valid data in this chunk
* @return the length of this chunk
*/
private int length() {
return end-start;
}
}
}