// ///////////////////////////////////////////////////////////////////
//
//  File:      TFHeader.cxx
//
//  Version:   1.0
//
//  Author:    Reiner Rohlfs (GADC)
//
//  History:   1.0   11.07.03  first released version
//
// ///////////////////////////////////////////////////////////////////
#include "TClass.h"

#include "TFHeader.h"
#include "TFError.h"

#ifndef TF_CLASS_IMP
#define TF_CLASS_IMP
ClassImp(TFBaseAttr)
ClassImp2T(TFAttr, T, F)
ClassImp(TFHeader)
ClassImp(TFAttrIter)
#endif

typedef std::list<TFBaseAttr*>::const_iterator I_Attr;

#ifndef ERRMSG_H   // Sun compiler includes this file several times
#define ERRMSG_H
static const char * errmsg_h[] = 
{ "Attribute with name %s does not exit in header (index = %u)"};
#endif

//_____________________________________________________________________________
// TFHeader:
//    TFHeader is a header for data organized in tables or image arrays
//    It is the metadata of the data it belongs to. A TFHeader consist of
//    a list of attributes. 
//
// TFBaseAttr, TFAttr:
//    The base class of attributes is TFBaseAttr. An attribute consist of 
//    a name, a value, a unit and a comment. The title of TNamed is used 
//    as the unit.
//
//    Data type specific attributes are implemented as template class (TFAttr). 
//    typedef for fife data types are defined: TFBoolAttr, TFIntAttr, 
//    TFUIntAttr, TFDoubleAttr and TFStringAttr.
//
//
// TFAttrIter:
//    The iterator TFAttrIter should be used to loop through all attributes
//    of a AstroROOT container like a table, a column or an image.


TFBaseAttr::TFBaseAttr(const TFBaseAttr & attribute)
   : TNamed(attribute)
{
   fComment = attribute.fComment;
}
//_____________________________________________________________________________
TFBaseAttr & TFBaseAttr::operator = (const TFBaseAttr & attribute)
{
   TNamed::operator=(attribute);

   fComment = attribute.fComment;
   return *this;
}
//_____________________________________________________________________________
bool TFBaseAttr::operator == (const TFBaseAttr & col) const
{
   return  fName    == col.fName    &&
           fTitle   == col.fTitle   &&
           fComment == col.fComment;
}
//_____________________________________________________________________________
//_____________________________________________________________________________
TFHeader::TFHeader(const TFHeader & header)
{

   I_Attr i_attr = header.fAttr.begin();
   while (i_attr != header.fAttr.end())
      { 
      fAttr.push_back((TFBaseAttr*)(*i_attr)->Clone()); 
      i_attr++;
      }
}
//_____________________________________________________________________________
TFHeader::~TFHeader()
{
// deletes also all attributes in the header

   for (I_Attr i_attr = fAttr.begin(); i_attr != fAttr.end(); i_attr++)
      delete *i_attr;

}
//_____________________________________________________________________________
TFHeader & TFHeader::operator = (const TFHeader & header) 
{
// deletes the attributes and copies all attributes of "header" into
// this header.

   if (this != &header)
      {
      for (I_Attr i_attr = fAttr.begin(); i_attr != fAttr.end(); i_attr++)
         delete *i_attr;
      fAttr.clear();

      I_Attr i_attr = header.fAttr.begin();
      while (i_attr != header.fAttr.end())
         { 
         fAttr.push_back((TFBaseAttr*)(*i_attr)->Clone()); 
         i_attr++;
         }
      }
   return *this;
}
//_____________________________________________________________________________
bool TFHeader::operator == (const TFHeader & header) const
{
// Return true if the number of attributes for this TFHeader and for 
// header is identical and if for each attribute of this TFHeader exist
// an identical attribute in header. The order of the attributes may
// be different.

   if (fAttr.size() != header.fAttr.size())
      return false;

   for (I_Attr i_attr1 = fAttr.begin(); i_attr1 != fAttr.end(); i_attr1++)
      {
      I_Attr i_attr2 = header.fAttr.begin();
      bool found = false;
      while (i_attr2 != header.fAttr.end())
         { 
         if ( (*i_attr1)->IsA() == (*i_attr2)->IsA()  &&
              **i_attr1 == **i_attr2)
            {
            found = true;
            break;
            }
         }
      if (!found)
         return false;
      }
   
   return true;   
}
//_____________________________________________________________________________
void TFHeader::AddAttribute(const TFBaseAttr & attr, Bool_t replace)
{
// Adds one attribute to this header. A copy of attr is added not
// attr itself. More than one attribute with the same name can be
// in the list of a header. If replace is set to kTRUE, the default 
// value, all existing attributes with the same name as attr are 
// removed. To have more than one attribute with the same name in this
// header replace has to be set to kFALSE.

   if (replace)
      DelAttribute(attr.GetName());

   fAttr.push_back((TFBaseAttr*)(attr.Clone())); 
}
//_____________________________________________________________________________
TFBaseAttr & TFHeader::GetAttribute(const char * key, UInt_t index) const
{
// Returns one attribute or throws a TFAttrException if the attribute 
// with the specified key and index is not in this header.
// If key is defined ( not NULL) only attributes with this name are
// returned. index defines the number of attributes with the name 
// "key" that are skipped before attribute is returned.
// The default value of index is 0.
// To return all attributes independent of the name a loop like this can
// be used:
//
//      try {
//         UInt_t index = 0;
//         while (1) {
//            TFBaseAttr & attr = header->GetAttribute(NULL, index);
//            // do something
//            index++;
//            }
//         }
//      catch ( TFAttrException ) {}
//
// To return all attribute of a given name a similar loop can be used, but
// GetAttribute(NULL, index) has to be replace by 
// GetAttribute("attr_name", index))
//
// Better and faster to get all attributes is the use of the  
// attribute iterator, see MakeAttrIterator()
//
// This functions either throws an exception or returns a dummy attribute 
// if the requested attribute does not exist. For more details see
// the user manual (Error Handling and Exceptions).

   UInt_t in_index = index;
   for (I_Attr i_attr = fAttr.begin(); i_attr != fAttr.end(); i_attr++)
      if (key == NULL || strcmp(key, (*i_attr)->GetName()) == 0 )
         {
         if (index == 0)
            // we found it
            return **i_attr;
         index--;
         }

   // here we have a problem: The attribute does not exist.
   // either throw an exception or return an "error" - attribute
   TFError::SetError("TFHeader::GetAttribute", errmsg_h[0], key, in_index);
   char msg[100];
   sprintf(msg, "Attribute %s does not exist", key);
   static TFBoolAttr errAttr("Error", false, "", msg);
   return errAttr;
}
//_____________________________________________________________________________
void TFHeader::DelAttribute(const char * key, Int_t index)
{
// Deletes one attribute or all attributes with the name "key".
// If index < 0, the default value, all attributes with the name
// "key" are deleted. If index >= 0 only one attribute is deleted.
// index defines the number of attributes with name key that are skipped
// before one attribute is deleted.
// If key is not defined ( set to NULL ) all attributes ( index < 0 ) or
// one attribute independent of its name is deleted.

   std::list<TFBaseAttr*>::iterator i_attr = fAttr.begin(); 
   while (i_attr != fAttr.end())
      {
      if (key == NULL || key[0] == 0 ||
         strcmp(key, (*i_attr)->GetName()) == 0    )
         {
         if (index <= 0)
            {
            delete *i_attr;
            i_attr = fAttr.erase(i_attr);
            if (index == 0)
               return;
            continue;
            }
         index--;
         }
      i_attr++;
      }
}
//_____________________________________________________________________________
UInt_t TFHeader::GetNumAttributes(const char * key) const
{
// Returns the number of attributes in this header with the name "key"
// If key is NULL (the default) the number of all attributes is returned.

   if (key == NULL)
      return fAttr.size();

   UInt_t   num = 0;
   for (I_Attr i_attr = fAttr.begin(); i_attr != fAttr.end(); i_attr++)
      if (strcmp(key, (*i_attr)->GetName()) == 0)
         num++;

   return num;
}
//_____________________________________________________________________________
TFAttrIter TFHeader::MakeAttrIterator() const
{
// Returns an iterator for all attributes. This iterater can be used if the 
// names of the attributes are not known to get all attributes.
// This method is faster than GetAttributes(). For more information about
// iterators see user manual (Iterators)
// 

   return TFAttrIter(&fAttr);
}
//_____________________________________________________________________________
void TFHeader::PrintH(const Option_t* option) const
{
// prints all attributes with name, value, unit and comment of this header
// if "h" or "H" is part of option


// this function cannot be called Print() g++ versin 2.95.3 would have an
// internal compiler error

   if (strchr(option, 'h') == NULL &&
       strchr(option, 'H') == NULL    )
      // do nothing 
      return;

   TFAttrIter i_header = MakeAttrIterator();
   char hstr[500];
   while (i_header.Next())
      {
      printf("%-16s : %20s %-5s | %s\n",
               i_header->GetName(),
               i_header->GetStringValue(hstr),
               i_header->GetUnit(),
               i_header->GetComment() );
      }
}
//_____________________________________________________________________________
Bool_t TFAttrIter::Next()          
{
// Moves to the next attribute in the header. 
// Returns kFALSE if there is no further attribute, else kTRUE.

   if (i_attr == fAttr->end()) return kFALSE;
   fAttribute = *i_attr; 
   i_attr++; 
   return kTRUE;
}


Last update: Fri Mar 14 13:55:08 2008

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.