package org.maachang.jni.io;

import java.io.IOException;
import java.io.InputStream;

/**
 * NativeInputStream.
 * 
 * @version 2011/01/09
 * @author  masahito suzuki
 * @since   SeabassNativeIO-1.0.2
 */
public class MemoryInputStream extends InputStream {
    
    private NativeBuffer nBuf ;
    private int offset ;
    private int length ;
    
    private MemoryInputStream() {
        
    }
    
    /**
     * コンストラクタ.
     * @param buf 対象のNativeBufferを設定します.
     */
    public MemoryInputStream( NativeBuffer buf ) {
        if( buf == null || buf.getLength() <= 0 ) {
            throw new IllegalArgumentException( "バッファ情報が正しくありません" ) ;
        }
        this.nBuf = buf ;
        this.offset = 0 ;
        this.length = buf.getLength() ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        close() ;
    }
    
    /**
     * クローズ処理.
     */
    public void close() {
        nBuf = null ;
    }
    
    /**
     * 残り容量を取得.
     * @return int 残り容量が返されます.
     * @exception IOException I/O例外.
     */
    public int available() throws IOException {
        if( nBuf == null ) {
            throw new IOException( "既にクローズしています" ) ;
        }
        return length - offset ;
    }
    
    /**
     * 読み込み処理.
     * @return int 読み込まれた情報が返されます.
     * @exception IOException I/O例外.
     */
    public int read() throws IOException {
        if( nBuf == null ) {
            throw new IOException( "既にクローズしています" ) ;
        }
        if( length <= offset ) {
            return -1 ;
        }
        return (int)( nBuf.getByte( offset++ ) & 0x000000ff ) ;
    }
    
    /**
     * 読み込み処理.
     * @param b 読み込み対象のバイナリを設定します.
     * @return int 読み込まれた情報が返されます.
     * @exception IOException I/O例外.
     */
    public int read(byte b[]) throws IOException {
        if (b == null) {
            throw new NullPointerException( "バイナリが存在しません" );
        }
        return read(b, 0, b.length);
    }
    
    /**
     * 読み込み処理.
     * @param b 対象のバイナリを設定します.
     * @param off 対象のオフセット値を設定します.
     * @param len 対象の長さを設定します.
     * @return int 読み込み長が返されます.
     * @exception IOException I/O例外.
     */
    public int read(byte b[], int off, int len) throws IOException {
        if( nBuf == null ) {
            throw new IOException( "既にクローズしています" ) ;
        }
        if( length <= offset ) {
            return -1 ;
        }
        if (b == null) {
            throw new NullPointerException( "バイナリが存在しません" );
        } else if (off < 0 || len < 0 || len+off > b.length) {
            throw new IndexOutOfBoundsException( "指定範囲が不正です" );
        } else if( len <= 0 ) {
            return 0 ;
        }
        if( length - offset < len ) {
            len = length - offset ;
        }
        nBuf.getBinary( offset,b,off,len ) ;
        offset += len ;
        return len ;
    }
    
    /**
     * markサポート.
     * @return boolean [false]が返されます.
     */
    public boolean markSupported() {
        return false ;
    }
}

