package uk.co.mmscomputing.device.capi;
import java.io.*;
import uk.co.mmscomputing.device.capi.ncc.DataB3Ind;
import uk.co.mmscomputing.device.capi.ncc.DataB3Resp;
import uk.co.mmscomputing.device.capi.exception.CapiException;
import uk.co.mmscomputing.concurrent.Semaphore;
public class CapiInputStream extends InputStream{
private CapiNCC ncc;
private boolean isopen=true;
private byte[] buf=null;
private int count=0,max=0;
private int available=0;
private Semaphore blocker=new Semaphore(0,true);
private int indexOut=0,indexIn=0;
private DataB3Ind[] dataB3Inds=new DataB3Ind[8];
// ---- Capi Thread Methods ----
public CapiInputStream(CapiNCC ncc){
this.ncc=ncc;
}
void received(DataB3Ind msg)throws CapiException{ // called from NCC
if(isopen){
synchronized(dataB3Inds){
dataB3Inds[indexIn]=msg;
indexIn=(indexIn+1)%8;
available+=msg.getPayloadLength();
}
blocker.release();
}else{ // if not open waste data
sendDataResp(msg.appid,msg.lineid,msg.getHandle());
}
}
void disconnect(){ // called from NCC -> close input stream
if(isopen){
isopen=false;
blocker.release(); // release read thread, if blocked
}
}
// ---- Inputstream Thread Methods ----
void sendDataResp(int appid,int lineid,int handle)throws CapiException{
ncc.sendDataResp(new DataB3Resp(appid,lineid,handle));
}
private byte[] readNextBuffer()throws IOException{ // InputStream Thread
if(!isopen){return null;}
try{
blocker.acquire(); // wait for data
}catch(InterruptedException ie){
isopen=false;
}
if(!isopen){blocker.release();return null;} // still open ?
DataB3Ind msg;
synchronized(dataB3Inds){
msg=dataB3Inds[indexOut];
indexOut=(indexOut+1)%8;
count=0; // reset counter
max=msg.getPayloadLength(); // number of data bytes
available-=max;
}
buf=msg.getPayload(buf); // get payload
sendDataResp(msg.appid,msg.lineid,msg.getHandle()); // tell capi we are done with data buffer
return buf;
}
public int read()throws IOException{
if(count==max){
buf=readNextBuffer();
if(buf==null){return -1;} // reached EOS
}
return 0x000000FF & buf[count++];
}
public int read(byte[] b, int off, int len)throws IOException{
if(b==null){
throw new NullPointerException(getClass().getName()+".read(byte[] b, int off, int len): b is null");
}
if((off<0)||(len<0)||(b.length<(off+len))){
throw new IndexOutOfBoundsException(getClass().getName()+".read(byte[] b, int off, int len): index off ["+off+"] or len ["+len+"] out of bounds ["+b.length+"].");
}
int written=0;
while(written<len){
if(count==max){
buf=readNextBuffer();
if(buf==null){
return(written!=0)?written:-1; // written==0 => reached EOS
}
}
int maxblen=len-written;
int maxbuflen=max-count;
int bytesToWrite=(maxblen<maxbuflen)?maxblen:maxbuflen;
System.arraycopy(buf,count,b,off+written,bytesToWrite);
written+=bytesToWrite;
count+=bytesToWrite;
}
return written;
}
public synchronized int available()throws IOException{
return available+max-count;
}
public boolean isOpen(){return isopen;}
public void close()throws IOException{
if(isopen){
isopen=false;
blocker.release(); // release read thread, if blocked
ncc.closedInput(); // signal NCC input stream is closed
}
}
/*
protected void finalize()throws Throwable{
System.err.println(getClass().getName()+".finalize");
super.finalize();
}
*/
}