View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.util;
21  
22  
23  import org.apache.directory.api.i18n.I18n;
24  
25  
26  /**
27   * A dynamically growing byte[]. 
28   *
29   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
30   */
31  public class ByteBuffer
32  {
33      /** the default initial buffer size */
34      private static final int DEFAULT_INITIAL_SIZE = 10;
35  
36      /** the initial size of the buffer in number of bytes: also increment for allocations */
37      private final int initialSize;
38  
39      /** the position into the buffer */
40      private int pos = 0;
41  
42      /** the bytes of the buffer */
43      private byte[] buf;
44  
45      /**
46       * Create a default ByteBuffer capable of holding 10 bytes
47       */
48      public ByteBuffer()
49      {
50          this( DEFAULT_INITIAL_SIZE );
51      }
52  
53  
54      /**
55       * Creates a ByteBuffer which has an initialze size
56       *  
57       * @param initialSize The initial buffer size
58       */
59      public ByteBuffer( int initialSize )
60      {
61          if ( initialSize <= 0 )
62          {
63              throw new IllegalArgumentException( I18n.err( I18n.ERR_04354 ) );
64          }
65  
66          this.initialSize = initialSize;
67          this.buf = new byte[initialSize];
68      }
69  
70  
71      /**
72       * Reset the Buffer position to 0. Every new added byte will be put on position 0.
73       * Note that whatever this buffer contained before a call to the clear() method
74       * will not be removed.
75       */
76      public final void clear()
77      {
78          pos = 0;
79      }
80  
81  
82      /**
83       * @return The current position in the buffer
84       */
85      public final int position()
86      {
87          return pos;
88      }
89  
90  
91      /**
92       * @return The number of bytes that can be added into this buffer
93       */
94      public final int capacity()
95      {
96          return buf.length;
97      }
98  
99  
100     /**
101      * Returns the byte at a given position. Note that no control is done
102      * on the position validity.
103      * 
104      * @param i The position
105      * @return The byte at the given position in the buffer
106      */
107     public final byte get( int i )
108     {
109         return buf[i];
110     }
111 
112 
113     /**
114      * Get's the bytes, the backing store for this buffer.  Note
115      * that you need to use the position index to determine where
116      * to stop reading from this buffer.
117      * 
118      * @return The interned Byte[]
119      */
120     public final byte[] buffer()
121     {
122         return buf;
123     }
124 
125 
126     /**
127      * Get's a copy of the bytes used.
128      * 
129      * @return A copy of the interned Byte[]
130      */
131     public final byte[] copyOfUsedBytes()
132     {
133         byte[] copy = new byte[pos];
134         System.arraycopy( buf, 0, copy, 0, pos );
135         return copy;
136     }
137 
138 
139     /**
140      * Appends the bytes to this buffer.
141      * 
142      * @param bytes The byte[] to append to the buffer
143      */
144     public final void append( byte[] bytes )
145     {
146         if ( pos + bytes.length > buf.length )
147         {
148             growBuffer( bytes.length );
149         }
150 
151         System.arraycopy( bytes, 0, buf, pos, bytes.length );
152         pos += bytes.length;
153     }
154 
155 
156     /**
157      * Appends a byte to this buffer.
158      * 
159      * @param b The byte to append to the buffer
160      */
161     public final void append( byte b )
162     {
163         if ( pos >= buf.length )
164         {
165             growBuffer();
166         }
167 
168         buf[pos] = b;
169         pos++;
170     }
171 
172 
173     /**
174      * Appends an int to this buffer.  WARNING: the int is truncated to 
175      * a byte value.
176      * 
177      * @param val The integer to append to the buffer
178      */
179     public final void append( int val )
180     {
181         if ( pos >= buf.length )
182         {
183             growBuffer();
184         }
185 
186         buf[pos] = ( byte ) val;
187         pos++;
188     }
189 
190 
191     private void growBuffer( int size )
192     {
193         if ( size > initialSize )
194         {
195             byte[] copy = new byte[buf.length + size];
196             System.arraycopy( buf, 0, copy, 0, pos );
197             this.buf = copy;
198         }
199         else
200         {
201             byte[] copy = new byte[buf.length + initialSize];
202             System.arraycopy( buf, 0, copy, 0, pos );
203             this.buf = copy;
204         }
205     }
206 
207 
208     private void growBuffer()
209     {
210         byte[] copy = new byte[buf.length + initialSize];
211         System.arraycopy( buf, 0, copy, 0, pos );
212         this.buf = copy;
213     }
214 }