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