//
// Copyright (c) 1999 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// Permission to use, redistribute, and copy this file is granted
// without a fee so long as as the following conditions are adhered to:
//
// o The user assumes all risk for using this software. The authors of this
//   software shall be liable for no damages of any kind.
//
// o If the source code is distributed then this copyright notice must
//   remain unaltered and any modification must be noted.
//

//
//  Title:  VCL TStream to CPP iostream mapping class
//
//  Author:  John M. Miano miano@colosseumbuilders.com
//

#include "vclstrm.h"

using namespace std ;

const int BUFFERSIZE = 512 ;
//
//  Description:
//
//    Default class constructor
//
VclStreamBuffer::VclStreamBuffer (TStream *vclstream)
{
  stream = vclstream ;
  read_buffer = NULL ;
  write_buffer = NULL;
  return ;
}

//
//  Description:
//
//    Class destructor
//
VclStreamBuffer::~VclStreamBuffer ()
{
  // Flush any unwritten data from the buffer.
  if (write_buffer != NULL)
    overflow (EOF) ;
  delete [] read_buffer ; read_buffer = NULL ;
  delete [] write_buffer ; write_buffer = NULL ;
  // We do not take ownership of the stream so we do not
  // delete it here.
  stream = NULL ;
  return ;
}

//
//  Description:
//
//    Virtual function to handle buffer overflows. We handle them by
//    writing the data to the VCL stream object.
//
//  Parameters:
//
//    cc: The next character to output.
//
//  Return Value:
//
//    Always 0 (=> Sucess)
//    Write exceptions will be thrown by VCL.
//
int VclStreamBuffer::overflow (int cc)
{
  if (write_buffer == NULL)
  {
    // If this is the first call then we need to allocate the output buffer.
    write_buffer = new char [BUFFERSIZE] ;
    setp (write_buffer, &write_buffer [BUFFERSIZE]) ;
  }
  else
  {
    // Flush the output buffer.
    long length = pptr () - pbase () ;
    if (length > 0)
      stream->WriteBuffer ((void *) pbase (), length) ;
    setp (pbase (), epptr ()) ;
  }
  if (cc != EOF)
    sputc ((char) cc) ; // Store the character in the buffer
  return 0 ;
}
//
//  Description:
//
//    Virtual function for handling requests for more data.
//
//  Return Value:
//
//      EOF => End of File, no more data available.
//      Any other value is the next character in the input stream.
//
int VclStreamBuffer::underflow ()
{
  // On the first call we need to allocate an input buffer.
  if (read_buffer == NULL)
    read_buffer = new char [BUFFERSIZE] ;
  // Copy the data from the VCL stream to the C++ stream
  unsigned int count = stream->Read ((void *) read_buffer, BUFFERSIZE) ;
  // Let the stream know how much data we got and where it is located.
  setg (read_buffer, read_buffer, &read_buffer [count]) ;

  // Return the first character.
  if (count > 0)
    return read_buffer [0] ;
  else
    return EOF ;
}

//
//  Description:
//
//    Virtual function for handling flushes
//
//  Return Value:
//
//      Any value returned by overflow.
//
int VclStreamBuffer::sync ()
{
  return overflow (EOF) ;
}

