/*=====================================================================*/
/*    .../prgm/project/bigloo/runtime/Jlib/input_socket_port.java      */
/*    -------------------------------------------------------------    */
/*    Author      :  Manuel Serrano                                    */
/*    Creation    :  Tue Dec  5 11:53:13 2000                          */
/*    Last change :  Fri May  2 16:19:54 2003 (serrano)                */
/*    Copyright   :  2000-03 Manuel Serrano                            */
/*    -------------------------------------------------------------    */
/*    JVM Socket input ports implementation.                           */
/*=====================================================================*/
package bigloo;
import bigloo.foreign;
import java.io.*;

/*---------------------------------------------------------------------*/
/*    INPUT_SOCKET_PORT                                                */
/*---------------------------------------------------------------------*/
public class input_socket_port extends input_port
{
  /*--- private fields --------------------------------------------------*/
  public final InputStream in;

  /*--- constructors ----------------------------------------------------*/
  public input_socket_port( final InputStream  stream,
                            final boolean      b )
  {
    super( "[socket]", b ? (int)bigloo.foreign.default_io_bufsiz : 1 );
    in= stream;
  }

  /*--- public methods --------------------------------------------------*/
  public void close()
    throws IOException
  {
    eof= true;
    buffer= null;
    in.close();
  }

  public boolean rgc_charready()
  {
    try
    {
      return (   (forward+1) < abufsiz)
              || (0 < in.available());
    }
    catch (final Exception _)
    {
      return false;
    }
  }

  public boolean rgc_fill_buffer()
    throws IOException
  {
    final int           bufsize= this.bufsiz;
    int                 abufsize= this.abufsiz;
    final int           matchstart= this.matchstart;

    // if the buffer is not full, we fill it */
    if (abufsize < bufsize)
      return rgc_size_fill_con_buffer( abufsize, bufsize-abufsize );

    if (0 < matchstart)
    {
      // we shift the buffer left and we fill the buffer */
      final byte[]      buffer= this.buffer;
      final int         movesize= abufsize-matchstart;

      for ( int i= 0 ; i < movesize ; ++i )
        buffer[i]= buffer[matchstart+i];

      abufsize-= matchstart;
      this.matchstart= 0;
      this.matchstop-= matchstart;
      this.forward-= matchstart;
      this.lastchar= buffer[matchstart-1];

      return rgc_size_fill_con_buffer( abufsize, bufsize-abufsize );
    }

    // we current token is too large for the buffer */
    // we have to enlarge it.                       */
    rgc_double_buffer();

    return rgc_fill_buffer();
  }

  final boolean rgc_size_fill_con_buffer( int        abufsize,
                                          final int  size )
    throws IOException
  {
    // we start reading at ABUFSIZE - 1 because we have */
    // to remove the '\0' sentinel that ends the buffer */
    final byte[]        buffer= this.buffer;
    final int           nbread= in.read( buffer, abufsize-1, size );

    if (nbread == -1)
      eof= true;
    else
      abufsize+= nbread;

    buffer[abufsize-1]= (byte)'\0';
    this.abufsiz= abufsize;
    return (0 < abufsiz);
  }
}
