// =====================================================================
//  $Id: TDataDeflation.cc,v 1.5 2004/03/07 16:56:04 goiwai Exp $
//  $Name: CLDAQ-1-14-06 $
//  $Log: TDataDeflation.cc,v $
//  Revision 1.5  2004/03/07 16:56:04  goiwai
//  *** empty log message ***
//
//  Revision 1.4  2004/03/07 10:30:34  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.3  2003/10/06 16:38:26  goiwai
//  *** empty log message ***
//
//  Revision 1.2  2003/07/30 16:21:20  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#ifdef __CLDAQ_ZLIB_USE
#include "TDataDeflation.hh"

TDataDeflation::TDataDeflation( Tint bufsize, Tint level )
  : theDeflationStream(), theCompressionLevel( level ),
    theStatus( Z_OK ), 
    theOutputBuffer( 0 ), theSizeOfOutputBuffer( bufsize ),
    theDeflatedData( 0 ), theSizeOfDeflatedData( -1 )
{
  theDeflationStream.zalloc = Z_NULL;
  theDeflationStream.zfree = Z_NULL;
  theDeflationStream.opaque = Z_NULL;

  theDeflationStream.next_in = Z_NULL;
  theDeflationStream.avail_in = 0;
  theDeflationStream.next_out = Z_NULL;
  theDeflationStream.avail_out = 0;

  theStatus = deflateInit( &theDeflationStream, theCompressionLevel );
  if ( theStatus != Z_OK ) {
    Tcerr << "TDataDeflation::TDataDeflation: ";
    Tcerr << theDeflationStream.msg << ", status: " << theStatus << Tendl;
  }

  SetOutputBuffer( theSizeOfOutputBuffer );
}

TDataDeflation::TDataDeflation( const TDataDeflation& right )
  : theDeflationStream(), theCompressionLevel( right.theCompressionLevel ),
    theStatus( Z_OK ), 
    theOutputBuffer( 0 ), theSizeOfOutputBuffer( right.theSizeOfOutputBuffer ),
    theDeflatedData( 0 ), theSizeOfDeflatedData( -1 )
{
  theDeflationStream.zalloc = Z_NULL;
  theDeflationStream.zfree = Z_NULL;
  theDeflationStream.opaque = Z_NULL;

  theDeflationStream.next_in = Z_NULL;
  theDeflationStream.avail_in = 0;
  theDeflationStream.next_out = Z_NULL;
  theDeflationStream.avail_out = 0;

  theStatus = deflateInit( &theDeflationStream, theCompressionLevel );
  if ( theStatus != Z_OK ) {
    Tcerr << "TDataDeflation::TDataDeflation: ";
    Tcerr << theDeflationStream.msg << ", status: " << theStatus << Tendl;
  }

  SetOutputBuffer( theSizeOfOutputBuffer );
}

TDataDeflation::~TDataDeflation()
{
  theStatus = deflateEnd( &theDeflationStream );
  if ( theStatus != Z_OK ) {
    Tcerr << "TDataDeflation::~TDataDeflation: ";
    Tcerr << theDeflationStream.msg << ", status: " << theStatus << Tendl;
  }

  delete [] theOutputBuffer;
}

const TDataDeflation& TDataDeflation::operator=( const TDataDeflation& right )
{
  deflateCopy( &theDeflationStream, 
	       &((Tzstream&)(right.theDeflationStream)) );
  theStatus = right.theStatus;
  if ( theCompressionLevel != right.theCompressionLevel ) {
    SetCompressionLevel( right.theCompressionLevel );
  }
  theSizeOfOutputBuffer = right.theSizeOfOutputBuffer;
  delete [] (Tbyte*)theOutputBuffer;
  theOutputBuffer = new Tbyte[ theSizeOfOutputBuffer ];
  theDeflatedData = 0;
  theSizeOfDeflatedData = -1;

  return *this;
}

Tvoid TDataDeflation::Compress( Tvoid* input, Tint nbyte, Tbool islast )
{
  static const Tstring head = "TDataDeflation::Compress: ";

  theDeflationStream.next_in = (Tbyte*)input;
  theDeflationStream.avail_in = nbyte;
  theDeflationStream.next_out = theOutputBuffer;
  theDeflationStream.avail_out = theSizeOfOutputBuffer;

  Tint flush;
  if ( islast ) {
    flush = Z_FINISH;
  } else {
    flush = Z_NO_FLUSH;
  }

  theStatus = deflate( &theDeflationStream, flush );

  theDeflatedData = theOutputBuffer;
  theSizeOfDeflatedData = theSizeOfOutputBuffer - theDeflationStream.avail_out;

  return;
}

Tvoid TDataDeflation::SetCompressionLevel( Tint level )
{
  theCompressionLevel = level;
  theStatus = deflateParams( &theDeflationStream, theCompressionLevel, Z_DEFAULT_STRATEGY );
  if ( theStatus != Z_OK ) {
    Tcerr << "TDataDeflation::TDataDeflation: ";
    Tcerr << theDeflationStream.msg << ", status: " << theStatus << Tendl;
  }
  return;
}

Tvoid TDataDeflation::SetOutputBuffer( Tint bufsize )
{
  if ( theOutputBuffer ) {
    delete [] theOutputBuffer;
  }
  theOutputBuffer = new Tbyte[ bufsize ];
  return;
}


#ifdef __CLDAQ_ROOT_DLL
    ClassImp(TDataDeflation)
#endif

#endif
