001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.lang; 020 021import java.io.ByteArrayOutputStream; 022import java.io.IOException; 023import java.io.OutputStream; 024import java.io.UnsupportedEncodingException; 025 026 027/** 028 * class to handle characters, similar to StringBuffer, but dont copy big blocks of char arrays. 029 */ 030public class ByteBuffer { 031 032 private final static int BLOCK_LENGTH = 1024; 033 private byte buffer[]; 034 private int pos=0; 035 private int length=0; 036 private final Entity root=new Entity(null); 037 private Entity curr=root; 038 private final String charset; 039 040 /** 041 * default constructor 042 */ 043 public ByteBuffer(String charset) { 044 this(charset,BLOCK_LENGTH); 045 } 046 047 /** 048 * constructor with size of the buffer 049 * @param size 050 */ 051 public ByteBuffer(String charset,int size) { 052 buffer = new byte[size]; 053 this.charset=charset; 054 } 055 056 public void append(char c) throws IOException { 057 append(new String(new char[]{c})); 058 } 059 060 /** 061 * method to appennd a charr array to the buffer 062 * @param c char array to append 063 * @throws IOException 064 */ 065 public void append(char c[]) throws IOException { 066 append(new String(c)); 067 } 068 069 public void append(byte c[]) { 070 int maxlength=buffer.length-pos; 071 if(c.length<maxlength) { 072 System.arraycopy(c, 0, buffer, pos, c.length); 073 pos+=c.length; 074 } 075 else { 076 System.arraycopy(c, 0, buffer, pos, maxlength); 077 curr.next=new Entity(buffer); 078 curr=curr.next; 079 length+=buffer.length; 080 buffer=new byte[(buffer.length>c.length-maxlength)?buffer.length:c.length-maxlength]; 081 if(c.length>maxlength) { 082 System.arraycopy(c, maxlength, buffer, 0, c.length-maxlength); 083 pos=c.length-maxlength; 084 } 085 else { 086 pos=0; 087 } 088 } 089 } 090 091 /** 092 * method to append a part of a char array 093 * @param c char array to get part from 094 * @param off start index on the char array 095 * @param len length of the sequenz to get from array 096 * @throws IOException 097 */ 098 public void append(char c[], int off, int len) throws IOException { 099 append(new String(c,off,len)); 100 } 101 102 /** 103 * Method to append a string to char buffer 104 * @param str String to append 105 * @throws IOException 106 */ 107 public void append(String str) throws IOException { 108 append(str.getBytes(charset)); 109 } 110 111 /** 112 * method to append a part of a String 113 * @param str string to get part from 114 * @param off start index on the string 115 * @param len length of the sequenz to get from string 116 * @throws IOException 117 */ 118 public void append(String str, int off, int len) throws IOException { 119 append(str.substring(off, off+len)); 120 } 121 122 /** 123 * method to writeout content of the char buffer in a writer, 124 * this is faster than get char array with (toCharArray()) and write this 125 in writer. 126 * @param writer writer to write inside 127 * @throws IOException 128 */ 129 public void writeOut(OutputStream os) throws IOException { 130 Entity e=root; 131 while(e.next!=null) { 132 e=e.next; 133 os.write(e.data); 134 } 135 os.write(buffer,0,pos); 136 } 137 138 @Override 139 public String toString() { 140 try { 141 return new String(getBytes(),charset); 142 } catch (UnsupportedEncodingException e) { 143 return new String(getBytes()); 144 } 145 } 146 147 /** 148 * clear the content of the buffer 149 */ 150 public void clear() { 151 if(size()==0)return; 152 buffer = new byte[buffer.length]; 153 root.next=null; 154 pos = 0; 155 length=0; 156 curr=root; 157 } 158 159 /** 160 * @return returns the size of the content of the buffer 161 */ 162 public int size() { 163 return length+pos; 164 } 165 166 167 private class Entity { 168 private byte[] data; 169 private Entity next; 170 171 private Entity(byte[] data) { 172 this.data=data; 173 } 174 } 175 176 177 public byte[] getBytes() { 178 ByteArrayOutputStream baos=new ByteArrayOutputStream(); 179 try { 180 writeOut(baos); 181 } 182 catch (IOException e) {} 183 return baos.toByteArray(); 184 } 185}