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.IOException; 022import java.io.OutputStream; 023import java.io.UnsupportedEncodingException; 024import java.io.Writer; 025 026 027/** 028 * class to handle characters, similar to StringBuffer, but dont copy big blocks of char arrays. 029 */ 030public class CharBuffer { 031 032 private final static int BLOCK_LENGTH = 1024; 033 private char 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 039 /** 040 * default constructor 041 */ 042 public CharBuffer() { 043 this(BLOCK_LENGTH); 044 } 045 046 /** 047 * constructor with size of the buffer 048 * @param size 049 */ 050 public CharBuffer(int size) { 051 buffer = new char[size]; 052 } 053 054 public void append(char c) { 055 append(new char[]{c}); 056 } 057 058 /** 059 * method to appennd a charr array to the buffer 060 * @param c char array to append 061 */ 062 public void append(char c[]) { 063 int maxlength=buffer.length-pos; 064 if(c.length<maxlength) { 065 System.arraycopy(c, 0, buffer, pos, c.length); 066 pos+=c.length; 067 } 068 else { 069 System.arraycopy(c, 0, buffer, pos, maxlength); 070 curr.next=new Entity(buffer); 071 curr=curr.next; 072 length+=buffer.length; 073 buffer=new char[(buffer.length>c.length-maxlength)?buffer.length:c.length-maxlength]; 074 if(c.length>maxlength) { 075 System.arraycopy(c, maxlength, buffer, 0, c.length-maxlength); 076 pos=c.length-maxlength; 077 } 078 else { 079 pos=0; 080 } 081 } 082 } 083 084 /** 085 * method to append a part of a char array 086 * @param c char array to get part from 087 * @param off start index on the char array 088 * @param len length of the sequenz to get from array 089 */ 090 public void append(char c[], int off, int len) { 091 int restLength=buffer.length-pos; 092 if(len<restLength) { 093 System.arraycopy(c, off, buffer, pos, len); 094 pos+=len; 095 } 096 else { 097 System.arraycopy(c, off, buffer, pos, restLength); 098 curr.next=new Entity(buffer); 099 curr=curr.next; 100 length+=buffer.length; 101 buffer=new char[(buffer.length>len-restLength)?buffer.length:len-restLength]; 102 103 System.arraycopy(c, off+restLength, buffer, 0, len-restLength); 104 pos=len-restLength; 105 106 } 107 } 108 109 /** 110 * Method to append a string to char buffer 111 * @param str String to append 112 */ 113 public void append(String str) { 114 if(str==null)return; 115 int restLength=buffer.length-pos; 116 if(str.length()<restLength) { 117 str.getChars(0,str.length(),buffer,pos); 118 pos+=str.length(); 119 } 120 else { 121 str.getChars(0,restLength,buffer,pos); 122 curr.next=new Entity(buffer); 123 curr=curr.next; 124 length+=buffer.length; 125 buffer=new char[(buffer.length>str.length()-restLength)?buffer.length:str.length()-restLength]; 126 127 str.getChars(restLength,str.length(),buffer,0); 128 pos=str.length()-restLength; 129 130 } 131 } 132 133 /** 134 * method to append a part of a String 135 * @param str string to get part from 136 * @param off start index on the string 137 * @param len length of the sequenz to get from string 138 */ 139 public void append(String str, int off, int len) { 140 int restLength=buffer.length-pos; 141 if(len<restLength) { 142 str.getChars(off,off+len,buffer,pos); 143 pos+=len; 144 } 145 else { 146 str.getChars(off,off+restLength,buffer,pos); 147 curr.next=new Entity(buffer); 148 curr=curr.next; 149 length+=buffer.length; 150 buffer=new char[(buffer.length>len-restLength)?buffer.length:len-restLength]; 151 152 str.getChars(off+restLength,off+len,buffer,0); 153 pos=len-restLength; 154 155 } 156 } 157 158 /** 159 * method to writeout content of the char buffer in a writer, 160 * this is faster than get char array with (toCharArray()) and write this 161 in writer. 162 * @param writer writer to write inside 163 * @throws IOException 164 */ 165 public void writeOut(Writer writer) throws IOException { 166 167 Entity e=root; 168 while(e.next!=null) { 169 e=e.next; 170 writer.write(e.data); 171 } 172 writer.write(buffer, 0, pos); 173 } 174 public void writeOut(OutputStream os, String charset) throws IOException { 175 Entity e=root; 176 while(e.next!=null) { 177 e=e.next; 178 os.write(new String(e.data).getBytes(charset)); 179 } 180 os.write(new String(buffer, 0, pos).getBytes(charset)); 181 } 182 183 184 /** 185 * return content of the Char Buffer as char array 186 * @return char array 187 */ 188 public char[] toCharArray() { 189 Entity e=root; 190 char[] chrs=new char[size()]; 191 int off=0; 192 while(e.next!=null) { 193 e=e.next; 194 System.arraycopy(e.data,0,chrs,off,e.data.length); 195 off+=e.data.length; 196 } 197 System.arraycopy(buffer,0,chrs,off,pos); 198 return chrs; 199 } 200 201 @Override 202 public String toString() { 203 return new String(toCharArray()); 204 } 205 206 /** 207 * clear the content of the buffer 208 */ 209 public void clear() { 210 if(size()==0)return; 211 buffer = new char[buffer.length]; 212 root.next=null; 213 pos = 0; 214 length=0; 215 curr=root; 216 } 217 218 /** 219 * @return returns the size of the content of the buffer 220 */ 221 public int size() { 222 return length+pos; 223 } 224 225 226 private class Entity { 227 private char[] data; 228 private Entity next; 229 230 private Entity(char[] data) { 231 this.data=data; 232 } 233 } 234 235 236 public byte[] getBytes(String characterEncoding) throws UnsupportedEncodingException { 237 238 239 return toString().getBytes(characterEncoding); 240 241 } 242 243 244 /*public static void main(String[] args) { 245 CharBuffer cb=new CharBuffer(3); 246 cb.append("12"); 247 cb.append("34"); 248 cb.append("5"); 249 cb.append("6"); 250 cb.append("7"); 251 cb.append("890-"); 252 cb.append("1234567890-1234567890-"); 253 254 cb=new CharBuffer(3); 255 cb.append("12",0,2); 256 cb.append("34",0,2); 257 cb.append("5",0,1); 258 cb.append("xxx6ggg",3,1); 259 cb.append("7zzz",0,1); 260 cb.append("890-",0,4); 261 cb.append("1234567890-1234567890-",0,22); 262 //System.out.println(cb+"->"+cb.size()); 263 264 265 cb=new CharBuffer(3); 266 cb.append(new char[]{'1','2'}); 267 cb.append(new char[]{'3','4'}); 268 cb.append(new char[]{'5'}); 269 cb.append(new char[]{'6'}); 270 cb.append(new char[]{'7'}); 271 cb.append(new char[]{'8','9','0','-'}); 272 cb.append(new char[]{'1','2','3','4','5','6','7','8','9','0','-','1','2','3','4','5','6','7','8','9','0','-'}); 273 System.out.println(cb+"->"+cb.size()); 274 275 276 277 cb=new CharBuffer(3); 278 cb.append(new char[]{'X','1','2','X'},1,2); 279 cb.append(new char[]{'3','4'},0,2); 280 cb.append(new char[]{'5'},0,1); 281 cb.append(new char[]{'6'},0,1); 282 cb.append(new char[]{'7'},0,1); 283 cb.append(new char[]{'8','9','0','-'},0,4); 284 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); 285 System.out.println(cb+"->"+cb.size()); 286 287 288 }*/ 289}