/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 this library. If not, see <http://www.gnu.org/licenses/>.
*
**/
package lucee.commons.lang;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* class to handle characters, similar to StringBuffer, but dont copy big blocks of char arrays.
*/
public class ByteBuffer {
private final static int BLOCK_LENGTH = 1024;
private byte buffer[];
private int pos=0;
private int length=0;
private final Entity root=new Entity(null);
private Entity curr=root;
private final String charset;
/**
* default constructor
*/
public ByteBuffer(String charset) {
this(charset,BLOCK_LENGTH);
}
/**
* constructor with size of the buffer
* @param size
*/
public ByteBuffer(String charset,int size) {
buffer = new byte[size];
this.charset=charset;
}
public void append(char c) throws IOException {
append(new String(new char[]{c}));
}
/**
* method to appennd a charr array to the buffer
* @param c char array to append
* @throws IOException
*/
public void append(char c[]) throws IOException {
append(new String(c));
}
public void append(byte c[]) {
int maxlength=buffer.length-pos;
if(c.length<maxlength) {
System.arraycopy(c, 0, buffer, pos, c.length);
pos+=c.length;
}
else {
System.arraycopy(c, 0, buffer, pos, maxlength);
curr.next=new Entity(buffer);
curr=curr.next;
length+=buffer.length;
buffer=new byte[(buffer.length>c.length-maxlength)?buffer.length:c.length-maxlength];
if(c.length>maxlength) {
System.arraycopy(c, maxlength, buffer, 0, c.length-maxlength);
pos=c.length-maxlength;
}
else {
pos=0;
}
}
}
/**
* method to append a part of a char array
* @param c char array to get part from
* @param off start index on the char array
* @param len length of the sequenz to get from array
* @throws IOException
*/
public void append(char c[], int off, int len) throws IOException {
append(new String(c,off,len));
}
/**
* Method to append a string to char buffer
* @param str String to append
* @throws IOException
*/
public void append(String str) throws IOException {
append(str.getBytes(charset));
}
/**
* method to append a part of a String
* @param str string to get part from
* @param off start index on the string
* @param len length of the sequenz to get from string
* @throws IOException
*/
public void append(String str, int off, int len) throws IOException {
append(str.substring(off, off+len));
}
/**
* method to writeout content of the char buffer in a writer,
* this is faster than get char array with (toCharArray()) and write this
in writer.
* @param writer writer to write inside
* @throws IOException
*/
public void writeOut(OutputStream os) throws IOException {
Entity e=root;
while(e.next!=null) {
e=e.next;
os.write(e.data);
}
os.write(buffer,0,pos);
}
@Override
public String toString() {
try {
return new String(getBytes(),charset);
} catch (UnsupportedEncodingException e) {
return new String(getBytes());
}
}
/**
* clear the content of the buffer
*/
public void clear() {
if(size()==0)return;
buffer = new byte[buffer.length];
root.next=null;
pos = 0;
length=0;
curr=root;
}
/**
* @return returns the size of the content of the buffer
*/
public int size() {
return length+pos;
}
private class Entity {
private byte[] data;
private Entity next;
private Entity(byte[] data) {
this.data=data;
}
}
public byte[] getBytes() {
ByteArrayOutputStream baos=new ByteArrayOutputStream();
try {
writeOut(baos);
}
catch (IOException e) {}
return baos.toByteArray();
}
}