// =====================================================================
//  $Id: TCompressObjectFilter.cc,v 1.5 2003/12/06 10:50:44 goiwai Exp $
//  $Name: CLDAQ-1-11-00 $
//  $Log: TCompressObjectFilter.cc,v $
//  Revision 1.5  2003/12/06 10:50:44  goiwai
//  可逆な圧縮フィルターです.
//  手抜きの実装なのでまだファイルにしか対応していませんが,2倍以上速度性能
//  が向上します.
//
// =====================================================================
#include "TCompressObjectFilter.hh"
#include "TStreamableObject.hh"
#include "TOutputObjectStream.hh"
#include "TObjectStream.hh"
#include "TOutputObjectFile.hh"
#include "Tsyslog.h"

static const Tint _maxbuf = 0x80000;
static Tbyte _buf[_maxbuf];
static TOutputObjectFile* _ofs = 0;

TCompressObjectFilter::TCompressObjectFilter()
  : TOutputObjectFilter(), theEncoder()
{;}

TCompressObjectFilter::~TCompressObjectFilter()
{;}

Tint TCompressObjectFilter::Filtering( TStreamableObject& object, TOutputObjectStream* stream )
{
  _ofs = (TOutputObjectFile*)stream;

  Tint totaldatasize = _ofs -> GetTotalDataSize();
  Tint nwrite = 0;
  _ofs -> SetLastDataSize( _ofs -> GetDataSize() );
  _ofs -> SetDataSize( nwrite );


  Tint recordsize = object.Serialize( _buf );
  if ( recordsize < _maxbuf && recordsize > 0 ) {
    theEncoder.Compress( _buf, recordsize );
  } else {
    Tcrit << "MAX BUFFER SIZE: " << _maxbuf << Tendl;
  }

  Tvoid* p = theEncoder.GetDeflatedData();
  Tsize_t s = (Tsize_t)theEncoder.GetSizeOfDeflatedData();
  nwrite = fwrite( p, s, 1, _ofs -> GetFileStream() );
  if ( s != 0 && nwrite != 1 ) {
    Terror << "WRITE ERROR in " << s << " BYTE RECORD" << Tendl;
  }

  Tint datasize = s * nwrite;
  _ofs -> SetDataSize( datasize );
  _ofs -> SetTotalDataSize( totaldatasize + datasize );

  return recordsize;
}

Tvoid TCompressObjectFilter::Initialize( TOutputObjectStream* stream )
{
  Tstream_t streamtype = stream -> GetStreamType();
  if ( streamtype != tFileStream ) {
    Tcrit << "Not TFileStream" << Tendl;
  }
  return;
}

Tvoid TCompressObjectFilter::Finalize( TOutputObjectStream* stream )
{
  Tstream_t streamtype = stream -> GetStreamType();
  if ( streamtype != tFileStream ) {
    Tcrit << "Not TFileStream" << Tendl;
  }

  _ofs = (TOutputObjectFile*)stream;
  if ( _ofs && !_ofs -> IsEnd() && !_ofs -> IsError() ) {

    Tint totaldatasize = _ofs -> GetTotalDataSize();
    Tint nwrite = 0;
    _ofs -> SetLastDataSize( _ofs -> GetDataSize() );
    _ofs -> SetDataSize( nwrite );

    theEncoder.Compress( 0, 0, Ttrue );
    Tvoid* p = theEncoder.GetDeflatedData();
    Tsize_t s = (Tsize_t)theEncoder.GetSizeOfDeflatedData();
    nwrite = fwrite( p, s, 1, _ofs -> GetFileStream() );
    if ( s != 0 && nwrite != 1 ) {
      Terror << "WRITE ERROR in " << s << " BYTE RECORD" << Tendl;
    }

    Tint datasize = s * nwrite;
    _ofs -> SetDataSize( datasize );
    _ofs -> SetTotalDataSize( totaldatasize + datasize );
  }

  return;
}
