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 *    http://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.shared.util;
021
022import org.apache.directory.shared.i18n.I18n;
023
024
025/**
026 * A dynamically growing byte[]. 
027 *
028 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
029 */
030public class ByteBuffer
031{
032    /** the default initial buffer size */
033    private static final int DEFAULT_INITIAL_SIZE = 10;
034    
035    /** the initial size of the buffer in number of bytes: also increment for allocations */
036    private final int initialSize;
037    /** the position into the buffer */
038    private int pos = 0;
039    /** the bytes of the buffer */
040    private byte[] buf;
041    
042    
043    public ByteBuffer()
044    {
045        this ( DEFAULT_INITIAL_SIZE );
046    }
047    
048    
049    public ByteBuffer( int initialSize )
050    {
051        if ( initialSize <= 0 )
052        {
053            throw new IllegalArgumentException( I18n.err( I18n.ERR_04354 ) );
054        }
055        this.initialSize = initialSize;
056        this.buf = new byte[initialSize];
057    }
058    
059    
060    public final void clear()
061    {
062        pos = 0;
063    }
064    
065    
066    public final int position()
067    {
068        return pos;
069    }
070    
071    
072    public final int capacity()
073    {
074        return buf.length;
075    }
076    
077    
078    public final byte get( int ii )
079    {
080        return buf[ii];
081    }
082    
083    
084    /**
085     * Get's the bytes, the backing store for this buffer.  Note
086     * that you need to use the position index to determine where
087     * to stop reading from this buffer.
088     */
089    public final byte[] buffer()
090    {
091        return buf;
092    }
093    
094    
095    /**
096     * Get's a copy of the bytes used.
097     */
098    public final byte[] copyOfUsedBytes()
099    {
100        byte[] copy = new byte[pos];
101        System.arraycopy( buf, 0, copy, 0, pos );
102        return copy;
103    }
104    
105    
106    /**
107     * Appends the bytes to this buffer.
108     */
109    public final void append( byte[] bytes )
110    {
111        for ( byte b : bytes )
112        {
113            append( b );
114        }
115    }
116    
117    
118    /**
119     * Appends a byte to this buffer.
120     */
121    public final void append( byte bite )
122    {
123        if ( pos >= buf.length )
124        {
125            growBuffer();
126        }
127        
128        buf[pos] = bite;
129        pos++;
130    }
131    
132    
133    /**
134     * Appends an int to this buffer.  WARNING: the int is truncated to 
135     * a byte value.
136     */
137    public final void append( int val )
138    {
139        if ( pos >= buf.length )
140        {
141            growBuffer();
142        }
143        
144        buf[pos] = ( byte ) val;
145        pos++;
146    }
147    
148    
149    private void growBuffer()
150    {
151        byte[] copy = new byte[buf.length+initialSize];
152        System.arraycopy( buf, 0, copy, 0, pos );
153        this.buf = copy;
154    }
155}