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    }