001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.util; 021 022 023import org.apache.directory.api.i18n.I18n; 024 025 026/** 027 * A dynamically growing byte[]. 028 * 029 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 030 */ 031public class ExpansibleByteBuffer 032{ 033 /** the default initial buffer size */ 034 private static final int DEFAULT_INITIAL_SIZE = 10; 035 036 /** the initial size of the buffer in number of bytes: also increment for allocations */ 037 private final int initialSize; 038 039 /** the position into the buffer */ 040 private int pos = 0; 041 042 /** the bytes of the buffer */ 043 private byte[] buf; 044 045 046 /** 047 * Create a default ExpansibleByteBuffer capable of holding 10 bytes 048 */ 049 public ExpansibleByteBuffer() 050 { 051 this( DEFAULT_INITIAL_SIZE ); 052 } 053 054 055 /** 056 * Creates a ExpansibleByteBuffer which has an initialze size 057 * 058 * @param initialSize The initial buffer size 059 */ 060 public ExpansibleByteBuffer( int initialSize ) 061 { 062 if ( initialSize <= 0 ) 063 { 064 throw new IllegalArgumentException( I18n.err( I18n.ERR_17042_INITIAL_SIZE_ABOVE_ZERO ) ); 065 } 066 067 this.initialSize = initialSize; 068 this.buf = new byte[initialSize]; 069 } 070 071 072 /** 073 * Reset the Buffer position to 0. Every new added byte will be put on position 0. 074 * Note that whatever this buffer contained before a call to the clear() method 075 * will not be removed. 076 */ 077 public final void clear() 078 { 079 pos = 0; 080 } 081 082 083 /** 084 * @return The position of the last byte in the buffer 085 */ 086 public final int position() 087 { 088 return pos; 089 } 090 091 092 /** 093 * Set the position to a specific value 094 * 095 * @param pos the new position 096 */ 097 public final void position( int pos ) 098 { 099 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}