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   *    https://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 ExpansibleByteBuffer
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      /**
47       * Create a default ExpansibleByteBuffer capable of holding 10 bytes
48       */
49      public ExpansibleByteBuffer()
50      {
51          this( DEFAULT_INITIAL_SIZE );
52      }
53  
54  
55      /**
56       * Creates a ExpansibleByteBuffer which has an initialze size
57       *  
58       * @param initialSize The initial buffer size
59       */
60      public ExpansibleByteBuffer( int initialSize )
61      {
62          if ( initialSize <= 0 )
63          {
64              throw new IllegalArgumentException( I18n.err( I18n.ERR_17042_INITIAL_SIZE_ABOVE_ZERO ) );
65          }
66  
67          this.initialSize = initialSize;
68          this.buf = new byte[initialSize];
69      }
70  
71  
72      /**
73       * Reset the Buffer position to 0. Every new added byte will be put on position 0.
74       * Note that whatever this buffer contained before a call to the clear() method
75       * will not be removed.
76       */
77      public final void clear()
78      {
79          pos = 0;
80      }
81  
82  
83      /**
84       * @return The position of the last byte in the buffer
85       */
86      public final int position()
87      {
88          return pos;
89      }
90  
91  
92      /**
93       * Set the position to a specific value
94       * 
95       * @param pos the new position
96       */
97      public final void position( int pos )
98      {
99          this.pos = pos;
100     }
101 
102 
103     /**
104      * @return The number of bytes that can be added into this buffer
105      */
106     public final int capacity()
107     {
108         return buf.length;
109     }
110 
111 
112     /**
113      * Returns the byte at a given position. Note that no control is done
114      * on the position validity.
115      * 
116      * @param i The position
117      * @return The byte at the given position in the buffer
118      */
119     public final byte get( int i )
120     {
121         return buf[i];
122     }
123 
124 
125     /**
126      * Get's the bytes, the backing store for this buffer.  Note
127      * that you need to use the position index to determine where
128      * to stop reading from this buffer.
129      * 
130      * @return The interned Byte[]
131      */
132     public final byte[] buffer()
133     {
134         return buf;
135     }
136 
137 
138     /**
139      * Get's a copy of the bytes used.
140      * 
141      * @return A copy of the interned Byte[]
142      */
143     public final byte[] copyOfUsedBytes()
144     {
145         byte[] copy = new byte[pos];
146         System.arraycopy( buf, 0, copy, 0, pos );
147         return copy;
148     }
149 
150 
151     /**
152      * Appends the bytes to this buffer.
153      * 
154      * @param bytes The byte[] to append to the buffer
155      */
156     public final void append( byte[] bytes )
157     {
158         if ( pos + bytes.length > buf.length )
159         {
160             growBuffer( bytes.length );
161         }
162 
163         System.arraycopy( bytes, 0, buf, pos, bytes.length );
164         pos += bytes.length;
165     }
166 
167 
168     /**
169      * Appends a byte to this buffer.
170      * 
171      * @param b The byte to append to the buffer
172      */
173     public final void append( byte b )
174     {
175         if ( pos >= buf.length )
176         {
177             growBuffer();
178         }
179 
180         buf[pos] = b;
181         pos++;
182     }
183 
184 
185     /**
186      * Appends an int to this buffer.  WARNING: the int is truncated to 
187      * a byte value.
188      * 
189      * @param val The integer to append to the buffer
190      */
191     public final void append( int val )
192     {
193         if ( pos >= buf.length )
194         {
195             growBuffer();
196         }
197 
198         buf[pos] = ( byte ) val;
199         pos++;
200     }
201 
202 
203     private void growBuffer( int size )
204     {
205         if ( size > initialSize )
206         {
207             byte[] copy = new byte[buf.length + size];
208             System.arraycopy( buf, 0, copy, 0, pos );
209             this.buf = copy;
210         }
211         else
212         {
213             byte[] copy = new byte[buf.length + initialSize];
214             System.arraycopy( buf, 0, copy, 0, pos );
215             this.buf = copy;
216         }
217     }
218 
219 
220     private void growBuffer()
221     {
222         byte[] copy = new byte[buf.length + initialSize];
223         System.arraycopy( buf, 0, copy, 0, pos );
224         this.buf = copy;
225     }
226 }