This is tmb_tree, version p16-br-05 | See all available versions

// @(#)root/meta:$Name: p16-br-05 $:$Id: TClassRef.cpp,v 1.1 2003/01/09 18:09:58 axel Exp $
// Author: Axel Naumann <mailto:axel@fnal.gov>  01/08/2002

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "tmb_tree/TClassRef.hpp"
#include "TROOT.h"
#include "TClass.h"


/////////////////////////////////////////////////////////////
//  Persistent reference to a TClass.
//  (TClass itself is not persistent.)
//
//  Implements Compare(), IsEqual() and Hash() (mostly 
//  by forwarding to TClass), and can thus be used e.g. 
//  as a key for TMap.
//
//  Example application: 
//  A TMap which stores objects of different types, not 
//  necessarily known during compile time. The objects' 
//  TClass can be used to access the objects in the map. 
//  Thus at compile time the container does not need to 
//  know the type of the objects stored.
//
//  Let's assume one wants to store these classes:
//
//    class TSomeObject:  public TCommonBase {...};
//    class TOtherObject: public TCommonBase {...};
//
//  Instead of
//
//    class THasObjects {
//    public:
//       TSomeObject*  GetSomeObject()  { return fObjects[0]; }
//       TOtherObject* GetOtherObject() { return fObjects[1]; }
//    private:
//       TCommonBase*  fObjects; // array of objects
//    };
//
//  (which can't be extended in a modular way or at 
//  runtime to allow for additional objects) one could 
//  use:
//
//    class TClassMap {
//    public:
//       TClassMap(){ fMap.SetOwner(); }
//       TObject* GetValue(TClass* cl) {
//          TClassRef cr(cl);
//          return fMap.GetValue(&cr);
//       }
//       void Add(TObject* obj) {
//          fMap.Add(new TClassRef(obj->IsA()), obj);
//       }
//    private:
//       TMap fMap;
//    };
//
//  Here, TClassMap does not know anything about the objects 
//  it contains. TCommonBase class could access them like
//  this:
//
//    class TCommonBase: TObject {
//       TCommonBase* LookMeUp(TClassMap* cm) {
//         return (TCommonBase*) cm->GetValue(IsA());
//       }
//    };
//
//  Objects of class TClassMap can be stored as its TMap
//  contains keys of class TClassRef instead of class TClass.
//
////////////////////////////////////////////////////////////

ClassImp(TClassRef)
// Tag used as "class name" to indicate a TClassRef's 
// fClass was uninitialized when written.
// Use invalid C(++) characters to ensure no class 
// can ever have this name and that this class name's 
// TClass can never be found. 
#define UNDEFINED_CLASS_TAG ("@ @")
 Int_t TClassRef::Compare(const TObject * obj) const
{
// Compare two TClassRefs or a TClassRef with a TClass
// Forwards the implementation to the referenced TClass::Compare()

   if (!fClass) {
      Warning("Compare", "Class not set, nothing to compare.");
      return 0;
   }

   if (obj->InheritsFrom(TClass::Class()))
      return fClass->Compare(obj);
   else if (obj->InheritsFrom(TClassRef::Class()))
      return fClass->Compare(((TClassRef *) obj)->GetClass());

   Warning("Compare", "Can't compare TClassRef to %s!",
           obj->IsA()->GetName());
   return 0;
}

 ULong_t TClassRef::Hash() const
{
// Creates a hash value. 
// Forwarded to TClass->Hash() if a referenced class is set,
// otherwise fallback to TObject::Hash()

   return (fClass ? fClass->Hash() : TObject::Hash());
}

 void TClassRef::SetClass(const char *clname)
{
// Sets clname to be the referenced class.
// A warning is issued if the class is unknown, and the class
// returned by GetClass() is set to NULL.

   fClass = gROOT->GetClass(clname, kTRUE);
   if (!fClass)
      if (strcmp(clname, UNDEFINED_CLASS_TAG) == 0)
         Warning("TClassRef",
                 "Referenced class was undefined when writing!");
      else
         Warning("TClassRef", "Class '%s' unknown!", clname);
}

 void TClassRef::Streamer(TBuffer & R__b)
{
// Stream an object of class TClassRef.

// Format:
//   UInt_t string len of classname
//   0 terminated char* classname

   // first stream the base class
   TObject::Streamer(R__b);

   if (R__b.IsReading()) {
      // allocate a heap char[] if the classname 
      // is too big to fit into the static char[].
#define      staticstrlen  4096
      static char clnamestatic[staticstrlen];
      char *clname = clnamestatic;
      UInt_t len;

      R__b >> len;
      if (len > staticstrlen)
         clname = new char[len + 1];	// static char[] is not big enough
      R__b.ReadString(clname, -1);	// disable size check, we know the length

      SetClass(clname);         // initialize *this

      if (len > staticstrlen)
         delete[]clname;
   } else {
      if (!fClass)
         Warning("Streamer", "Writing TClassRef to undefined class!");
      const char *clname;
      if (fClass)
         clname = fClass->GetName();
      else
         clname = UNDEFINED_CLASS_TAG;

      R__b << (UInt_t) strlen(clname);
      R__b.WriteString(clname);
   }
}


ROOT page - Class index - Class Hierarchy - Top of the page

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.