/* $Id: TspDataInputStream.java,v 1.2 2006/06/04 08:33:45 erk Exp $
 * -----------------------------------------------------------------------
 * 
 * TSP Library - core components for a generic Transport Sampling Protocol.
 * 
 * Copyright (c) 2002 Yves DUFRENNE, Stephane GALLES, Eric NOULARD and Robert PAGNOT 
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * -----------------------------------------------------------------------
 * 
 * Project    : TSP
 * SubProject : jTSP
 * Maintainer : tsp@astrium-space.com
 * Component  : Consumer
 * 
 * -----------------------------------------------------------------------
 * 
 * Purpose   : 
 * 
 * -----------------------------------------------------------------------
 */

package tsp.core.common;

import java.io.FilterInputStream;

import tsp.core.config.*;
import org.acplt.oncrpc.XdrTcpDecodingStream;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;

/**
 * The TSP DataInputStream.
 */
public class TspDataInputStream implements TspDecodingStream {

    public TspDataInputStream(Socket streamingSocket) throws TspCommonException
    {
		try {
			tspStream    = streamingSocket.getInputStream();
			bufSize      = 1024;
			buffer       = new byte[bufSize];
			bufReadIndex = 0;
		}
		catch (IOException e) {
			throw new TspCommonException(e);
		}
    }

    /**
     * Verify if the stream may be able to read
     * the specified amount of byte.
     */
    public synchronized boolean available(int howmany) throws TspCommonException	
    {	
	if (howmany > bufSize) {
	    TspConfig.log(TspConfig.LOG_SEVERE,
			  "TspDataInputStream::available CANNOT ensure "+
			  howmany + "data in buffer of size " + bufSize);
	    /* FIXME throw exception */
	    return false;			  
	}

	/* we must read more on stream */
	if (this.available < howmany) {
	    getData();
	}
	return (this.available >= howmany);
    } /* end of available */

    protected synchronized void getData()
	throws TspCommonException
    {
	try {
	    /* move all data at the beginning of the buffer */
	    if (bufReadIndex != 0) {
		System.arraycopy(buffer,bufReadIndex,buffer,0,available);
		bufReadIndex = 0;
	    }
	    int n = tspStream.read(buffer,available,bufSize-available);
	    if (n<0) {
		throw new TspCommonException("End of TSP stream");
	    }
	    else {
		available += n;
	    }
	}
	catch (IOException e) {
	    /*TODO Dirty Fix
	    TspConfig.log(TspConfig.LOG_SEVERE,
			  "TspDataInputStream::getData IOException");*/
	}
    }


    public synchronized double tspDecodeDouble() throws TspCommonException 
		
    {	
	double a = 0.0;
	long  l;
	
	/* a TSP double is 8 byte long (64 bits) */
	while (!available(8)) {
	    available(8);
	}

	l = buffer[bufReadIndex++] & 0xFF;
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	l = (l << 8) + (buffer[bufReadIndex++] & 0xFF);
	available -= 8;
	a = Double.longBitsToDouble(l);

	return a;
    }
    
    public synchronized float tspDecodeFloat() throws TspCommonException 
	
    {	
	float a;
	int  i;
	
	/* a TSP float is 4 byte long (32 bits) */
	while (!available(4)) {
	    available(4);
	}
	
	i = buffer[bufReadIndex++] & 0xFF;
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);

	available -= 4;
	a = Float.intBitsToFloat(i);

	return a;
    }

    public synchronized long tspDecodeLong() 
	 throws TspCommonException
 {
	long i = 0;

	/* a TSP int is 8 byte long (64 bits) */

	while (!available(8)) {
	    available(8);
	}
	

	i = buffer[bufReadIndex++] & 0xFF;
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	

	available -= 8;	

	return i;
 }
    
    public synchronized int tspDecodeInt() 
	 throws TspCommonException
  {
	int i = 0;

	/* a TSP int is 4 byte long (32 bits) */

	while (!available(4)) {
	    available(4);
	}
	

	i = buffer[bufReadIndex++] & 0xFF;
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);

	available -= 4;	

	return i;
  }

    public synchronized char tspDecodeChar() 
	 throws TspCommonException
  {
	int i = 0;

	while (!available(4)) {
	    available(4);
	}
	

	i = buffer[bufReadIndex++] & 0xFF;
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);

	available -= 4;	

	return (char) i;
  }
    
    
    public synchronized byte tspDecodeRaw() 
	 throws TspCommonException
  {
	int i = 0;

	while (!available(4)) {
	    available(4);
	}
	

	i = buffer[bufReadIndex++] & 0xFF;
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);
	i = (i << 8) + (buffer[bufReadIndex++] & 0xFF);

	available -= 4;	

	return (byte) i;
  }
    
    protected InputStream tspStream;
    protected byte[]      buffer;
    protected int         bufSize;
    protected int         available;
    protected int         bufReadIndex;
    
} /* end of TspDataInputStream */
