001 package railo.commons.lang; 002 003 import java.io.ByteArrayOutputStream; 004 import java.io.IOException; 005 import java.io.OutputStream; 006 import java.io.UnsupportedEncodingException; 007 008 009 /** 010 * class to handle characters, similar to StringBuffer, but dont copy big blocks of char arrays. 011 */ 012 public class ByteBuffer { 013 014 private final static int BLOCK_LENGTH = 1024; 015 private byte buffer[]; 016 private int pos=0; 017 private int length=0; 018 private final Entity root=new Entity(null); 019 private Entity curr=root; 020 private final String charset; 021 022 /** 023 * default constructor 024 */ 025 public ByteBuffer(String charset) { 026 this(charset,BLOCK_LENGTH); 027 } 028 029 /** 030 * constructor with size of the buffer 031 * @param size 032 */ 033 public ByteBuffer(String charset,int size) { 034 buffer = new byte[size]; 035 this.charset=charset; 036 } 037 038 public void append(char c) throws IOException { 039 append(new String(new char[]{c})); 040 } 041 042 /** 043 * method to appennd a charr array to the buffer 044 * @param c char array to append 045 * @throws IOException 046 */ 047 public void append(char c[]) throws IOException { 048 append(new String(c)); 049 } 050 051 public void append(byte c[]) { 052 int maxlength=buffer.length-pos; 053 if(c.length<maxlength) { 054 System.arraycopy(c, 0, buffer, pos, c.length); 055 pos+=c.length; 056 } 057 else { 058 System.arraycopy(c, 0, buffer, pos, maxlength); 059 curr.next=new Entity(buffer); 060 curr=curr.next; 061 length+=buffer.length; 062 buffer=new byte[(buffer.length>c.length-maxlength)?buffer.length:c.length-maxlength]; 063 if(c.length>maxlength) { 064 System.arraycopy(c, maxlength, buffer, 0, c.length-maxlength); 065 pos=c.length-maxlength; 066 } 067 else { 068 pos=0; 069 } 070 } 071 } 072 073 /** 074 * method to append a part of a char array 075 * @param c char array to get part from 076 * @param off start index on the char array 077 * @param len length of the sequenz to get from array 078 * @throws IOException 079 */ 080 public void append(char c[], int off, int len) throws IOException { 081 append(new String(c,off,len)); 082 } 083 084 /** 085 * Method to append a string to char buffer 086 * @param str String to append 087 * @throws IOException 088 */ 089 public void append(String str) throws IOException { 090 append(str.getBytes(charset)); 091 } 092 093 /** 094 * method to append a part of a String 095 * @param str string to get part from 096 * @param off start index on the string 097 * @param len length of the sequenz to get from string 098 * @throws IOException 099 */ 100 public void append(String str, int off, int len) throws IOException { 101 append(str.substring(off, off+len)); 102 } 103 104 /** 105 * method to writeout content of the char buffer in a writer, 106 * this is faster than get char array with (toCharArray()) and write this 107 in writer. 108 * @param writer writer to write inside 109 * @throws IOException 110 */ 111 public void writeOut(OutputStream os) throws IOException { 112 Entity e=root; 113 while(e.next!=null) { 114 e=e.next; 115 os.write(e.data); 116 } 117 os.write(buffer,0,pos); 118 } 119 120 @Override 121 public String toString() { 122 try { 123 return new String(getBytes(),charset); 124 } catch (UnsupportedEncodingException e) { 125 return new String(getBytes()); 126 } 127 } 128 129 /** 130 * clear the content of the buffer 131 */ 132 public void clear() { 133 if(size()==0)return; 134 buffer = new byte[buffer.length]; 135 root.next=null; 136 pos = 0; 137 length=0; 138 curr=root; 139 } 140 141 /** 142 * @return returns the size of the content of the buffer 143 */ 144 public int size() { 145 return length+pos; 146 } 147 148 149 private class Entity { 150 private byte[] data; 151 private Entity next; 152 153 private Entity(byte[] data) { 154 this.data=data; 155 } 156 } 157 158 159 public byte[] getBytes() { 160 ByteArrayOutputStream baos=new ByteArrayOutputStream(); 161 try { 162 writeOut(baos); 163 } 164 catch (IOException e) {} 165 return baos.toByteArray(); 166 } 167 168 169 public static void main(String[] args) throws IOException { 170 ByteBuffer cb=new ByteBuffer("utf-8",3); 171 cb.append("12"); 172 cb.append("34"); 173 cb.append("5"); 174 cb.append("6"); 175 cb.append("7"); 176 cb.append("890-"); 177 cb.append("1234567890-1234567890-"); 178 System.out.println(cb+"->"+cb.size()); 179 180 cb=new ByteBuffer("utf-8",3); 181 cb.append("12",0,2); 182 cb.append("34",0,2); 183 cb.append("5",0,1); 184 cb.append("xxx6ggg",3,1); 185 cb.append("7zzz",0,1); 186 cb.append("890-",0,4); 187 cb.append("1234567890-1234567890-",0,22); 188 System.out.println(cb+"->"+cb.size()); 189 190 191 cb=new ByteBuffer("utf-8",3); 192 cb.append(new char[]{'1','2'}); 193 cb.append(new char[]{'3','4'}); 194 cb.append(new char[]{'5'}); 195 cb.append(new char[]{'6'}); 196 cb.append(new char[]{'7'}); 197 cb.append(new char[]{'8','9','0','-'}); 198 cb.append(new char[]{'1','2','3','4','5','6','7','8','9','0','-','1','2','3','4','5','6','7','8','9','0','-'}); 199 System.out.println(cb+"->"+cb.size()); 200 201 202 203 cb=new ByteBuffer("utf-8",3); 204 cb.append(new char[]{'X','1','2','X'},1,2); 205 cb.append(new char[]{'3','4'},0,2); 206 cb.append(new char[]{'5'},0,1); 207 cb.append(new char[]{'6'},0,1); 208 cb.append(new char[]{'7'},0,1); 209 cb.append(new char[]{'8','9','0','-'},0,4); 210 cb.append(new char[]{'1','2','3','4','5','6','7','8','9','0','-','1','2','3','4','5','6','7','8','9','0','-'},0,22); 211 System.out.println(cb+"->"+cb.size()); 212 213 cb=new ByteBuffer("utf-8",3); 214 cb.append(new char[]{'�'}); 215 System.out.println(cb+"->"+cb.size()); 216 217 } 218 }