package org.maachang.util;

import java.nio.ByteBuffer;

/**
 * バイナリ配列.
 * 
 * @version 2008/03/25
 * @author masahito suzuki
 * @since MaachangBase 1.00
 */
public class ArrayBinary {
    private static final int BUFFER = 4096 ;
    private byte[] binary = null ;
    private int baseLength = 0 ;
    private int length = 0 ;
    
    public ArrayBinary() {
        this( -1 ) ;
    }
    
    public ArrayBinary( int size ) {
        if( size <= 0 ) {
            size = BUFFER ;
        }
        this.baseLength = size ;
        this.binary = new byte[ size ] ;
        this.length = 0 ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    public void destroy() {
        this.binary = null ;
        this.length = 0 ;
        this.baseLength = 0 ;
    }
    
    public void reset() {
        if( this.binary.length == baseLength ) {
            this.length = 0 ;
        }
        else {
            this.binary = new byte[ baseLength ] ;
            this.length = 0 ;
        }
    }
    
    public void write( int b ) throws Exception {
        addLimit( 1 ) ;
        binary[ length ] = ( byte )( b & 0x000000ff ) ;
        length ++ ;
    }
    
    public void write( byte[] bin ) throws Exception {
        if( bin == null || bin.length <= 0 ) {
            return ;
        }
        write( bin,-1 ) ;
    }
    
    public void write( byte[] bin,int len ) throws Exception {
        if( bin == null || bin.length <= 0 ) {
            return ;
        }
        if( len <= 0 || bin.length <= len ) {
            len = bin.length ;
        }
        addLimit( len ) ;
        int off = this.length ;
        System.arraycopy( bin,0,this.binary,off,len ) ;
        this.length += len ;
    }
    
    public void write( ByteBuffer buf ) throws Exception {
        int len = buf.limit() ;
        addLimit( len ) ;
        int off = this.length ;
        buf.get( this.binary,off,len ) ;
        this.length += len ;
    }
    
    public byte getByte( int no ) {
        return binary[ no ] ;
    }
    
    public byte[] getRawBinary() {
        return binary ;
    }
    
    public byte[] getBinary() {
        return getBinary( 0 ) ;
    }
    
    public byte[] getBinary( int length ) {
        if( length <= 0 ) {
            length = this.length ;
        }
        if( this.length < length ) {
            length = this.length ;
        }
        byte[] ret = new byte[ length ] ;
        System.arraycopy( this.binary,0,ret,0,length ) ;
        return ret ;
    }
    
    public int length() {
        return length ;
    }
    
    private void addLimit( int len ) {
        if( binary.length <= length + len ) {
            byte[] t = binary ;
            int iLen = ( t.length * 2 ) + len ;
            binary = new byte[ iLen ] ;
            System.arraycopy( t,0,binary,0,t.length ) ;
            t = null ;
        }
    }
}
