// =====================================================================
//  $Id: TCompressObjectFilter.cc,v 1.9 2004/06/24 15:15:25 goiwai Exp $
//  $Name: CLDAQ-1-14-06 $
//  $Log: TCompressObjectFilter.cc,v $
//  Revision 1.9  2004/06/24 15:15:25  goiwai
//  たくさんの変更
//  Tcout,Tcerr,Tlogをバッファ経由にした。
//  何個かexternした。Tlog,Tcout,Tcerr,Tinfo...Tcritなど出力関係。
//
//  Revision 1.8  2004/03/07 16:52:34  goiwai
//  __CLDAQ_ZLIB_USEプロプロセッサの位置をちょっとずらしただけです。
//
//  Revision 1.7  2004/03/07 10:30:32  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.6  2004/01/19 23:01:17  goiwai
//  Tsyslog.h => TSystemLoggin.hh
//
//  Revision 1.5  2003/12/06 10:50:44  goiwai
//  可逆な圧縮フィルターです.
//  手抜きの実装なのでまだファイルにしか対応していませんが,2倍以上速度性能
//  が向上します.
//
// =====================================================================
#ifdef __CLDAQ_ZLIB_USE
#include "TCompressObjectFilter.hh"
#include "TStreamableObject.hh"
#include "TOutputObjectStream.hh"
#include "TObjectStream.hh"
#include "TOutputObjectFile.hh"

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 {
    Tcout << "MAX BUFFER SIZE: " << _maxbuf << Tendl;
    exit( EXIT_SUCCESS );
  }

  Tvoid* p = theEncoder.GetDeflatedData();
  Tsize_t s = (Tsize_t)theEncoder.GetSizeOfDeflatedData();
  nwrite = fwrite( p, s, 1, _ofs -> GetFileStream() );
  if ( s != 0 && nwrite != 1 ) {
    Tcerr << "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 ) {
    Tcout << "Not TFileStream" << Tendl;
    exit( EXIT_SUCCESS );
  }
  return;
}

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

  _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 ) {
      Tcerr << "WRITE ERROR in " << s << " BYTE RECORD" << Tendl;
    }

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

  return;
}

#ifdef __CLDAQ_ROOT_DLL
    ClassImp(TCompressObjectFilter)
#endif

#endif
