package org.maachang.comet.net ;

/**
 * バイナリ配列.
 * 
 * @version 2008/02/08
 * @author masahito suzuki
 * @since MaachangComet 1.08
 */
class BinaryArray {
    private static final int BUFFER = 4096 ;
    private byte[] binary = null ;
    private int length = 0 ;
    private long lastAccessTime = -1L ;
    
    /**
     * コンストラクタ.
     */
    public BinaryArray() {
        this.binary = new byte[ BUFFER ] ;
        this.length = 0 ;
        this.lastAccessTime = System.currentTimeMillis() ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    /**
     * オブジェクト破棄.
     */
    public synchronized void destroy() {
        this.binary = null ;
        this.length = 0 ;
        this.lastAccessTime = -1L ;
    }
    
    /**
     * データリセット.
     */
    public synchronized void reset() {
        if( this.binary.length == BUFFER ) {
            this.length = 0 ;
        }
        else {
            this.binary = new byte[ BUFFER ] ;
            this.length = 0 ;
        }
        this.lastAccessTime = -1L ;
    }
    
    /**
     * データ出力.
     * <BR>
     * @param b 出力データを設定します.
     */
    public synchronized void write( int b ) throws Exception {
        if( binary.length <= length ) {
            byte[] t = binary ;
            int iLen = t.length * 2 ;
            binary = new byte[ iLen ] ;
            System.arraycopy( t,0,binary,0,t.length ) ;
            t = null ;
        }
        binary[ length ] = ( byte )( b & 0x000000ff ) ;
        length ++ ;
        this.lastAccessTime = System.currentTimeMillis() ;
    }
    
    /**
     * 指定位置のバイナリを取得.
     * <BR>
     * @param no 対象の項番を設定します.
     * @return int 対象位置の情報が返されます.<BR>
     *             [-1]の場合、情報は無効です.
     */
    public synchronized int getByte( int no ) {
        if( no <= -1 || no >= this.length ) {
            return -1 ;
        }
        return ( int )( binary[ no ] & 0x000000ff ) ;
    }
    
    /**
     * 管理バイナリ内容を取得.
     * <BR>
     * @return byte[] 管理されている全バイナリが返されます.
     */
    public synchronized byte[] getBinary() {
        return binary ;
    }
    
    /**
     * バイナリ情報を取得.
     * <BR>
     * @param length 指定バイナリ長を設定します.
     * @return byte[] 質得バイナリ長の情報が返されます.
     */
    public synchronized 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 ;
    }
    
    /**
     * 格納バイナリ長を取得.
     * <BR>
     * @return int 格納バイナリ長が返されます.
     */
    public synchronized int getLength() {
        return length ;
    }
    
    /**
     * 更新時間を取得.
     * <BR>
     * @return long 更新時間が返されます.
     */
    public synchronized long getUpdateTime() {
        return lastAccessTime ;
    }
}
