// =====================================================================
/*!
//
//  \file TDataElement.hh
//  \brief This file contains the TDataElement class.
//  \author Go IWAI <goiwai@users.sourceforge.jp>
//
//  $Id: TDataElement.hh,v 1.10 2004/03/07 10:30:30 goiwai Exp $
//  $Name: CLDAQ-1-14-06 $
//  $Log: TDataElement.hh,v $
//  Revision 1.10  2004/03/07 10:30:30  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.9  2004/01/19 21:09:39  goiwai
//  プリプロセッサの接頭辞をCLDAQ__に変更しました.
//
//  Revision 1.8  2003/12/06 10:59:11  goiwai
//  Serialize(Tvoid*) -> Serialize(const Tvoid*)に変更しました.
//  Deserialize(const Tvoid*)を追加しました.
//  手抜きの実装なので,バッファオーバーフローの可能性があります.
//  Reallocate()とかするような仕組みが必要です.
//
//  Revision 1.7  2003/11/24 06:57:19  goiwai
//  Size()メンバ関数を追加しました.
//  抱えているプリミティブ型の数を返します.
//
//  Revision 1.6  2003/11/04 12:03:05  goiwai
//  ==演算子と!=演算子を実装しました.具体的には
//  if ( record == "String" ) {
//    hoeghoge;
//  }
//  のような使い方が出来ます.単純に theID メンバとを比較して結果を返します.
//
//  Revision 1.5  2003/11/03 08:35:12  goiwai
//  Doxygen用のタグとコメントをうちこんでいく試みを開始しました.
//
//  Revision 1.4  2003/10/06 16:42:19  goiwai
//  *** empty log message ***
//
//  Revision 1.3  2003/08/20 21:49:02  goiwai
//  TDataElementクラスにStorePrimitive()メソッドを追加しました.
//  StorePrimitives()という似たようなメソッドもありますが,こちらは,1つ以上
//  プリミティブデータを取得するメソッドであるのに対して,この
//  StorePrimitive()メソッドは1つのデータのみ取得します.
//
//    type data;
//    element.StorePrimitives( &data );
//    // ----
//    type data;
//    element.StorePrimitive( data );
//
//  上のふたつの処理は同じ動作をします.
//  型は内部で解決される(その分遅い)ので,特に気にする必要はありません.
//
//  Revision 1.2  2003/07/30 16:17:51  goiwai
//  ファイルにコミットログをつけることにしました.
//
*/
// =====================================================================
#ifndef CLDAQ__TDATAELEMENT_HH
#define CLDAQ__TDATAELEMENT_HH

#include "Tglobals.h"
#include "TStreamableObject.hh"

class TOutputObjectStream;
class TOutputObjectFile;
class TOutputObjectSocket;
class TOutputObjectSharedMemory;


/*!
// \example
//
// If example code exists.
//
*/

/*!
// \class TDataElement
// \brief This is the TDataElement class.
// \author Go IWAI <goiwai@users.sourceforge.jp>
//
// The TDataElement class detail description.
// Write it down ASAP!
//
// \todo None?
// \bug None?
// \ingroup DatarecordCategory
*/
class TDataElement
  : public TStreamableObject
{

  private:
    Tvoid* theData;
    Telement_t theElementType;
    Tint theNumberOfPrimitives;

  public:
    TDataElement( Telement_t type = tTypeUnknown, const Tstring& id = TunknownID );
    TDataElement( Tvoid* data, Telement_t type, const Tstring& id = TunknownID, Tint ndata = 1 );
    TDataElement( const TDataElement& right );
    ~TDataElement();

  public:
    Tint Record( TOutputObjectStream* output );
    Tint GetRecordSize();
    Tvoid FillData( Tvoid* data, Telement_t elementtype, Tint ndata = 1 );
    Tvoid FillData( Tvoid* data, Tint ndata = 1 );
    Tvoid Clear();
    Tint Serialize( const Tvoid* buffer );
    Tint Deserialize( const Tvoid* buffer );

    //! GetNumberOfPrimitives() と同じ
    Tint Size() const;

  public:
    Tint* GetIntData() const;
    Tstring* GetStringData() const;
    Tdouble* GetDoubleData() const;
    Tfloat* GetFloatData() const;
    TUshort* GetUnsignedShortData() const;
    Tshort* GetShortData() const;
    Tlong* GetLongData() const;
    TUlong* GetUnsignedLongData() const;
    TUint* GetUnsignedIntData() const;

  public:
    Tvoid* GetData() const;
    Telement_t GetElementType() const;
    Tint GetNumberOfPrimitives() const;
    Tvoid SetData( Tvoid* data );
    Tvoid SetElementType( Telement_t elementtype );
    Tvoid SetNumberOfPrimitives( Tint nprimitives );

  public:
    Tint StorePrimitives( Tint* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( Tstring* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( Tdouble* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( Tfloat* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( TUshort* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( Tshort* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( Tlong* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( TUlong* buffer, Tint narray = 0 ) const;
    Tint StorePrimitives( TUint* buffer, Tint narray = 0 ) const;
    Tvoid StorePrimitive( Tint& buffer ) const;
    Tvoid StorePrimitive( Tstring& buffer ) const;
    Tvoid StorePrimitive( Tdouble& buffer ) const;
    Tvoid StorePrimitive( Tfloat& buffer ) const;
    Tvoid StorePrimitive( TUshort& buffer ) const;
    Tvoid StorePrimitive( Tshort& buffer ) const;
    Tvoid StorePrimitive( Tlong& buffer ) const;
    Tvoid StorePrimitive( TUlong& buffer ) const;
    Tvoid StorePrimitive( TUint& buffer ) const;

  public:
    const TDataElement& operator=( const TDataElement& right );
    Tbool operator==( const TDataElement& right ) const;
    Tbool operator!=( const TDataElement& right ) const;
    Tbool operator==( const Tstring& right ) const;
    Tbool operator!=( const Tstring& right ) const;
    friend Tostream& operator<<( Tostream& tos, const TDataElement& right );

  private:
    Tvoid freeDataSpace();
    Tvoid allocateDataSpace( Tvoid* data );
    Tint record( TOutputObjectFile* ofile );
    Tint record( TOutputObjectSocket* osocket );
    Tint record( TOutputObjectSharedMemory* omemory );

#ifdef __CLDAQ_ROOT_DLL
    ClassDef(TDataElement,0)
#endif

};

inline Tvoid* TDataElement::GetData() const
{
  return theData;
}

inline Tvoid TDataElement::SetData( Tvoid* data )
{
  theData = data;
  return;
}

inline Telement_t TDataElement::GetElementType() const
{
  return theElementType;
}

inline Tvoid TDataElement::SetElementType( Telement_t elementtype )
{
  theElementType = elementtype;
  return;
}

inline Tint TDataElement::GetNumberOfPrimitives() const
{
  return theNumberOfPrimitives;
}

inline Tvoid TDataElement::SetNumberOfPrimitives( Tint nprimitives )
{
  theNumberOfPrimitives = nprimitives;
  return;
}

inline Tint* TDataElement::GetIntData() const
{
  return (Tint*)theData;
}

inline Tstring* TDataElement::GetStringData() const
{
  return (Tstring*)theData;
}

inline Tdouble* TDataElement::GetDoubleData() const
{
  return (Tdouble*)theData;
}

inline Tfloat* TDataElement::GetFloatData() const
{
  return (Tfloat*)theData;
}

inline TUshort* TDataElement::GetUnsignedShortData() const
{
  return (TUshort*)theData;
}

inline Tshort* TDataElement::GetShortData() const
{
  return (Tshort*)theData;
}

inline Tlong* TDataElement::GetLongData() const
{
  return (Tlong*)theData;
}

inline TUlong* TDataElement::GetUnsignedLongData() const
{
  return (TUlong*)theData;
}

inline TUint* TDataElement::GetUnsignedIntData() const
{
  return (TUint*)theData;
}

inline Tvoid TDataElement::FillData( Tvoid* data, Telement_t elementtype, Tint ndata )
{
  freeDataSpace();
  theElementType = elementtype;
  theNumberOfPrimitives = ndata;
  allocateDataSpace( data );
  return;
}

inline Tvoid TDataElement::FillData( Tvoid* data, Tint ndata )
{
  return FillData( data, theElementType, ndata );
}

inline Tint TDataElement::Size() const
{
  return GetNumberOfPrimitives();
}

#endif
