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 ist 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            /** 
121            * return the content of the buffer as string
122            * @see java.lang.Object#toString()
123            */
124            public String toString() {
125                    try {
126                            return new String(getBytes(),charset);
127                    } catch (UnsupportedEncodingException e) {
128                            return new String(getBytes());
129                    }
130            }
131    
132            /**
133            * clear the content of the buffer
134            */
135            public void clear() {
136                    if(size()==0)return;
137            buffer = new byte[buffer.length];
138                    root.next=null;
139                    pos = 0;
140                    length=0;
141                    curr=root;
142            }
143    
144            /**
145             * @return returns the size of the content of the buffer
146             */
147            public int size() {
148                    return length+pos;
149            }
150            
151            
152            private class Entity {
153                    private byte[] data;
154                    private Entity next;
155                    
156                    private Entity(byte[] data) {
157                            this.data=data;
158                    }
159            }
160    
161    
162        public byte[] getBytes() {
163            ByteArrayOutputStream baos=new ByteArrayOutputStream();
164                    try {
165                            writeOut(baos);
166                    } 
167                    catch (IOException e) {}
168            return baos.toByteArray();
169        }
170    
171            
172            public static void main(String[] args) throws IOException {
173                    ByteBuffer cb=new ByteBuffer("utf-8",3);
174                    cb.append("12");
175                    cb.append("34");
176                    cb.append("5");
177                    cb.append("6");
178                    cb.append("7");
179                    cb.append("890-");
180                    cb.append("1234567890-1234567890-");
181                    System.out.println(cb+"->"+cb.size());
182                    
183                    cb=new ByteBuffer("utf-8",3);
184                    cb.append("12",0,2);
185                    cb.append("34",0,2);
186                    cb.append("5",0,1);
187                    cb.append("xxx6ggg",3,1);
188                    cb.append("7zzz",0,1);
189                    cb.append("890-",0,4);
190                    cb.append("1234567890-1234567890-",0,22);
191                    System.out.println(cb+"->"+cb.size());
192                    
193                    
194                    cb=new ByteBuffer("utf-8",3);
195                    cb.append(new char[]{'1','2'});
196                    cb.append(new char[]{'3','4'});
197                    cb.append(new char[]{'5'});
198                    cb.append(new char[]{'6'});
199                    cb.append(new char[]{'7'});
200                    cb.append(new char[]{'8','9','0','-'});
201                    cb.append(new char[]{'1','2','3','4','5','6','7','8','9','0','-','1','2','3','4','5','6','7','8','9','0','-'});
202                    System.out.println(cb+"->"+cb.size());
203    
204                    
205                    
206                    cb=new ByteBuffer("utf-8",3);
207                    cb.append(new char[]{'X','1','2','X'},1,2);
208                    cb.append(new char[]{'3','4'},0,2);
209                    cb.append(new char[]{'5'},0,1);
210                    cb.append(new char[]{'6'},0,1);
211                    cb.append(new char[]{'7'},0,1);
212                    cb.append(new char[]{'8','9','0','-'},0,4);
213                    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);
214                    System.out.println(cb+"->"+cb.size());
215                    
216                    cb=new ByteBuffer("utf-8",3);
217                    cb.append(new char[]{'�'});
218                    System.out.println(cb+"->"+cb.size());
219                    
220            }
221    }