//
//  Title:  PngInputFileStream Implementation
//
//  Copyright 1997-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.
//
//  Author:  John M. Miano (miano@colosseumbuilders.com)
//
//  Date:    March 15, 1999
//
//  Version: 1
//
//  Description:
//
//    PngInputFileStream implements PNG input through a file.
//
//  Revision History:
//
//

#include "pnginputfilestream.h"

using namespace std ;

namespace Colosseum
{
//
//  Description:
//
//    Class [Default] Constructor
//
//  Parameters:
//
//    buffersize : Size of the size of the input buffer to create.
//
PngInputFileStream::PngInputFileStream (unsigned int buffersize)
: buffer_size (buffersize),
  input_buffer (new UBYTE1 [buffersize])
{
  return ;
}
//
//  Description:
//
//    Class Destructor
//
PngInputFileStream::~PngInputFileStream ()
{
  delete [] input_buffer ; input_buffer = 0 ;
  return ;
}
//
//  Description:
//
//    This function reads and returns the chunk length
//    from the input stream.
//
//  Return Value:
//
//    The length of the next chunk in system format.
//
UBYTE4 PngInputFileStream::readChunkLength ()
{
  UBYTE4 result ;
  input_stream.read (reinterpret_cast<char*>(&result),
                     sizeof (result)) ;
  if (input_stream.gcount () != sizeof (result))
    throw StreamError ("Premature End of File") ;
  result = BigEndianToSystem (result) ;
  return result ;
}
//
//  Description:
//
//    This function reads the chunk data from the input file.
//
//  Parameters:
//
//    length : Number of bytes to read
//    buffer (out) : Returns a pointer to the buffer containing the data.
//
void PngInputFileStream::readChunkData (UBYTE4 length, UBYTE1 *&buffer)
{
  if (length > buffer_size)
  {
    delete [] input_buffer ;
    input_buffer = new UBYTE1 [length] ;
    buffer_size = length ;
  }
  input_stream.read (reinterpret_cast<char*>(input_buffer), length) ;
  int count = input_stream.gcount () ;
  if (count != length)
    throw StreamError ("Premature End of File") ;
  buffer = input_buffer ;
  return ;
}

//
//  Description:
//
//    This function reads the chunk CRC from the input file.
//
//  Return Value:
//
//    The chunk CRC
//
UBYTE4 PngInputFileStream::readCrc ()
{
  UBYTE4 result ;
  input_stream.read (reinterpret_cast<char*>(&result),
                     sizeof (result)) ;
  if (input_stream.gcount () != sizeof (result))
    throw StreamError ("Premature End of File") ;
  result = BigEndianToSystem (result) ;
  return result ;
}
//
//  Description:
//
//    This function tells the caller if the end of the 
//    file has been reached.
//
//  Return Value:
//
//    true => The end of file has been reached.
//    false => There is more data in the file.
//
bool PngInputFileStream::endReached ()
{
  bool result = input_stream.eof () ;
  return result ;
}

//
//  Description:
//
//    This function returns the state of the input stream.
//
//  Return Value:
//
//    The state ofthe output stream.
//
PngInputFileStream::operator bool ()
{
#if defined (_MSC_VER)
  bool result = static_cast<void*> (input_stream) != 0 ? true : false ;
#else
  bool result = static_cast<bool> (input_stream) ;
#endif
  return result ;
}
//
//  Description:
//
//    This function opens the input file.
//
//  Parameters:
//
//    filename : The name of the file to open
//
void PngInputFileStream::open (const std::string &filename)
{
  input_stream.open (filename.c_str (), ios::binary) ;
  return ;
}
//
//  Description:
//
//    This function closes the output file.
//
void PngInputFileStream::close ()
{
  input_stream.close () ;
  return ;
}
//
//  Description:
//
//    This function reads raw bytes from the input file.
//
//
//  Parameters:
//
//    count : The number of bytes to read
//    buffer (out) : A pointer to the data read.
//  
void PngInputFileStream::readRaw (unsigned int count, UBYTE1 *&buffer)
{
  if (count > buffer_size)
  {
    delete [] input_buffer ;
    input_buffer = new UBYTE1 [count] ;
    buffer_size = count ;
  }

  input_stream.read (reinterpret_cast<char*>(input_buffer), count) ;
  if (input_stream.gcount () != count)
    throw StreamError ("Premature End of File") ;
  buffer = input_buffer ;
  return ;
}


} // End Namespace 
