Adding a new common utility class to hold a list of named scalars.
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 28 Oct 2010 00:33:51 +0000 (00:33 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 28 Oct 2010 00:33:51 +0000 (00:33 +0000)
HLT/BASE/AliHLTScalars.cxx [new file with mode: 0644]
HLT/BASE/AliHLTScalars.h [new file with mode: 0644]
HLT/BASE/HLTbaseLinkDef.h
HLT/BASE/test/Makefile.am
HLT/BASE/test/testAliHLTScalars.C [new file with mode: 0644]
HLT/libHLTbase.pkg

diff --git a/HLT/BASE/AliHLTScalars.cxx b/HLT/BASE/AliHLTScalars.cxx
new file mode 100644 (file)
index 0000000..1c188b6
--- /dev/null
@@ -0,0 +1,350 @@
+// $Id: $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * All rights reserved.                                                   *
+ *                                                                        *
+ * Primary Authors:                                                       *
+ *   Artur Szostak <artursz@iafrica.com>                                  *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+///  @file   AliHLTScalars.cxx
+///  @author Artur Szostak <artursz@iafrica.com>
+///  @date   28 Sep 2010
+///  @brief  Implementation of the HLT scalars class.
+///
+/// This implements the scalars class for the HLT, which is a collection of
+/// named scalar values. Searching for a named scalar is optimised by using
+/// using a hash map.
+
+#include "AliHLTScalars.h"
+#include "TString.h"
+#include "AliLog.h"
+#include "TIterator.h"
+#include "Riostream.h"
+#include <cassert>
+
+ClassImp(AliHLTScalars);
+ClassImp(AliHLTScalars::AliScalar);
+
+
+AliHLTScalars::AliHLTScalars() :
+       TObject(),
+       fScalars(AliHLTScalars::AliScalar::Class(), 128),
+       fMap(TCollection::kInitHashTableCapacity, 2)
+{
+       // Default constructor.
+       
+       fMap.SetOwner(kFALSE);
+}
+
+
+AliHLTScalars::AliHLTScalars(const AliHLTScalars& obj) :
+       TObject(obj),
+       fScalars(obj.fScalars),
+       fMap(obj.fMap.GetSize(), obj.fMap.GetRehashLevel())
+{
+       // Copy constructor performs a deep copy.
+
+       fMap.SetOwner(kFALSE);
+       fMap.AddAll(&fScalars);
+}
+
+
+AliHLTScalars::AliHLTScalars(const TClass* cl, Int_t initSize) :
+       TObject(),
+       fScalars(cl, initSize),
+       fMap(TCollection::kInitHashTableCapacity, 2)
+{
+       // Constructor to be able to specify a custom class for the fScalars TClonesArray object.
+
+       fMap.SetOwner(kFALSE);
+}
+
+
+AliHLTScalars::~AliHLTScalars()
+{
+       // Default destructor.
+       
+       Clear();
+}
+
+
+bool AliHLTScalars::Add(const char* name, const char* description, Double_t value)
+{
+       // Adds a new scalar.
+
+       AliScalar* scalar = static_cast<AliScalar*>( fMap.FindObject(name) );
+       bool exists = scalar != NULL;
+       if (not exists)
+       {
+               scalar = new (fScalars[fScalars.GetEntriesFast()]) AliScalar(name, description, value);
+               fMap.Add(scalar);
+       }
+       else
+       {
+               scalar->Value(value);
+       }
+       return exists;
+}
+
+
+bool AliHLTScalars::Remove(const char* name)
+{
+       // Removes a scalar from the list.
+
+       TNamed x(name, "");
+       TObject* scalar = fMap.Remove(&x);
+       bool existed = scalar != NULL;
+       if (existed)
+       {
+               fScalars.Remove(scalar);
+               fScalars.Compress();
+       }
+       return existed;
+}
+
+
+const AliHLTScalars::AliScalar& AliHLTScalars::GetScalar(const char* name) const
+{
+       // Fetch the named scalar object.
+
+       const TObject* scalar = fMap.FindObject(name);
+       if (scalar != NULL)
+       {
+               return *static_cast<const AliScalar*>(scalar);
+       }
+       else
+       {
+               static AliHLTScalars::AliScalar sentinel;
+               return sentinel;
+       }
+}
+
+
+AliHLTScalars::AliScalar& AliHLTScalars::GetScalar(const char* name)
+{
+       // Fetch the named scalar object for editing.
+
+       TObject* scalar = fMap.FindObject(name);
+       if (scalar == NULL)
+       {
+               scalar = new (fScalars[fScalars.GetEntriesFast()]) AliScalar(name, "", 0);
+               fMap.Add(scalar);
+       }
+       return *static_cast<AliScalar*>(scalar);
+}
+
+
+const AliHLTScalars::AliScalar& AliHLTScalars::GetScalarN(UInt_t n) const
+{
+       // Fetch the n'th scalar object.
+
+       if (n < NumberOfScalars())
+       {
+               const TObject* scalar = fScalars.UncheckedAt(Int_t(n));
+               return *static_cast<const AliScalar*>(scalar);
+       }
+       else
+       {
+               static AliHLTScalars::AliScalar sentinel;
+               return sentinel;
+       }
+}
+
+
+AliHLTScalars::AliScalar& AliHLTScalars::GetScalarN(UInt_t n)
+{
+       // Fetch the n'th scalar object for editing.
+
+       TObject* scalar = NULL;
+       if (n < NumberOfScalars())
+       {
+               scalar = fScalars.UncheckedAt(Int_t(n));
+       }
+       else
+       {
+               // We have to create all missing scalars since there cannot
+               // be gaps in the TClonesArray. This can cause segfaults during
+               // ROOT I/O of the class otherwise.
+               for (UInt_t i = NumberOfScalars(); i <= n; ++i)
+               {
+                       // Make sure the the name of the scalar is not taken.
+                       // If it is then find an unused name.
+                       TString nameToUse = Form("Scalar%d", i);
+                       if (FindObject(nameToUse.Data()) != NULL)
+                       {
+                               UInt_t m = 0;
+                               do
+                               {
+                                       nameToUse = Form("Scalar%d_%d", i, m++);
+                               }
+                               while (FindObject(nameToUse.Data()) != NULL);
+                       }
+                       scalar = new (fScalars[i]) AliScalar(nameToUse.Data(), "", 0);
+                       fMap.Add(scalar);
+               }
+       }
+       return *static_cast<AliScalar*>(scalar);
+}
+
+
+void AliHLTScalars::Reset()
+{
+       // Sets all the scalar values and rates to zero.
+       
+       for (Int_t i = 0; i < fScalars.GetEntriesFast(); ++i)
+       {
+               AliScalar* scalar = static_cast<AliScalar*>( fScalars.UncheckedAt(i) );
+               scalar->Value(0);
+       }
+}
+
+
+void AliHLTScalars::Clear(Option_t* option)
+{
+       // Clears the array of scalars.
+
+       fMap.Clear();
+       fScalars.Delete(option);
+}
+
+
+void AliHLTScalars::Copy(TObject& object) const
+{
+       // Performs a deep copy.
+       
+       if (object.IsA() != AliHLTScalars::Class())
+       {
+               AliError(Form("Cannot copy to an object of type '%s'.", object.ClassName()));
+               return;
+       }
+       AliHLTScalars* obj = static_cast<AliHLTScalars*>(&object);
+       obj->operator = (*this);
+}
+
+
+void AliHLTScalars::Print(Option_t* option) const
+{
+       // Prints the HLT trigger scalars.
+
+       TIter next(&fScalars);
+       const AliScalar* scalar = NULL;
+
+       TString opt = option;
+       if (opt == "compact")
+       {
+               scalar = static_cast<const AliScalar*>(next());
+               if (scalar != NULL) cout << scalar->Value();
+               while ((scalar = static_cast<const AliScalar*>(next())) != NULL)
+               {
+                       cout << ", " << scalar->Value();
+               }
+               cout << endl;
+               return;
+       }
+       
+       // Calculate the maximum field width required to keep things aligned.
+       int fieldwidth = 0;
+       while ((scalar = static_cast<const AliScalar*>(next())) != NULL)
+       {
+               int length = strlen(scalar->Name()) + strlen(scalar->Description()) + 3;
+               if (length > fieldwidth) fieldwidth = length;
+       }
+       if (fieldwidth > 80) fieldwidth = 80;
+       
+       cout << "HLT scalars:" << endl;
+       next.Reset();
+       while ((scalar = static_cast<const AliScalar*>(next())) != NULL)
+       {
+               TString str = scalar->Description();
+               str += " (";
+               str += scalar->Name();
+               str += ")";
+               cout << setw(fieldwidth) << str.Data() << setw(0)
+                    << " = " << scalar->Value() << setw(0)
+                    << endl;
+       }
+       if (fScalars.GetSize() == 0) cout << "(none)" << endl;
+}
+
+
+AliHLTScalars& AliHLTScalars::operator = (const AliHLTScalars& obj)
+{
+       // Performs a deep copy.
+       
+       if (this == &obj) return *this;
+       Clear();  // Remove existing scalars.
+       TObject::operator = (obj);
+       for (Int_t i = 0; i < obj.fScalars.GetEntriesFast(); ++i)
+       {
+               const AliScalar* x = static_cast<const AliScalar*>(obj.fScalars.UncheckedAt(i));
+               new (fScalars[i]) AliScalar(*x);
+       }
+       fMap.AddAll(&fScalars);
+       return *this;
+}
+
+
+Bool_t AliHLTScalars::IsEqual(const TObject *obj) const
+{
+       // Checks if two sets of scalar lists have the same scalars.
+
+       assert(obj != NULL);
+       if (obj->IsA()->GetBaseClass(AliHLTScalars::Class()) == NULL)
+       {
+               AliError(Form("Cannot compare object of type '%s'' with an object of type '%s'.",
+                             this->ClassName(), obj->ClassName()
+                       ));
+               return kFALSE;
+       }
+       const AliHLTScalars* rhs = static_cast<const AliHLTScalars*>(obj);
+       if (fScalars.GetEntriesFast() != rhs->fScalars.GetEntriesFast()) return kFALSE;
+       TIter next(&fScalars);
+       const AliScalar* scalar = NULL;
+       while ((scalar = static_cast<const AliScalar*>(next())) != NULL)
+       {
+               if (rhs->fScalars.FindObject(scalar->Name()) == NULL) return kFALSE;
+       }
+       return kTRUE;
+}
+
+
+bool AliHLTScalars::operator == (const AliHLTScalars& obj) const
+{
+       // Compares two scalar lists to see that they have the same scalar values.
+
+       if (fScalars.GetEntriesFast() != obj.fScalars.GetEntriesFast()) return false;
+       TIter next(&fScalars);
+       const AliScalar* a = NULL;
+       while ((a = static_cast<const AliScalar*>(next())) != NULL)
+       {
+               const AliScalar* b = static_cast<const AliScalar*>(
+                               obj.fScalars.FindObject(a->Name())
+                       );
+               if (b == NULL) return false;
+               if (a->Value() != b->Value()) return false;
+       }
+       return true;
+}
+
+
+void AliHLTScalars::AliScalar::Copy(TObject& object) const
+{
+       // Performs a deep copy.
+       
+       if (object.IsA() != AliHLTScalars::AliScalar::Class())
+       {
+               AliError(Form("Cannot copy to an object of type '%s'.", object.ClassName()));
+               return;
+       }
+       AliHLTScalars::AliScalar* obj = static_cast<AliHLTScalars::AliScalar*>(&object);
+       *obj = *this;
+}
diff --git a/HLT/BASE/AliHLTScalars.h b/HLT/BASE/AliHLTScalars.h
new file mode 100644 (file)
index 0000000..7d0457e
--- /dev/null
@@ -0,0 +1,272 @@
+//-*- Mode: C++ -*-
+// $Id: $
+#ifndef AliHLTSCALARS_H
+#define AliHLTSCALARS_H
+/* This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ * See cxx source for full Copyright notice                               */
+
+///  @file   AliHLTScalars.h
+///  @author Artur Szostak <artursz@iafrica.com>
+///  @date   28 Sep 2010
+///  @brief  Declares the a base class for named scalar values.
+
+#include "TObject.h"
+#include "TNamed.h"
+#include "TTimeStamp.h"
+#include "TClonesArray.h"
+#include "THashTable.h"
+
+/**
+ * @class AliHLTScalars
+ * @brief Container for named scalar values.
+ *
+ * This class contains a list of named scalars for an event as summary information.
+ * These can be used by the trigger components to perform event selection or used
+ * for monitoring purposes.
+ *
+ * \ingroup alihlt_base
+ */
+class AliHLTScalars : public TObject
+{
+public:
+       /**
+        * This class stores a single scalar value and name.
+        */
+       class AliScalar : public TNamed
+       {
+       public:
+               /// Default constructor
+               AliScalar() : TNamed(), fValue(0) {}
+               
+               /// Constructor to set the initial value.
+               AliScalar(const char* name, const char* description, Double_t value) :
+                       TNamed(name, description), fValue(value)
+               {}
+               
+               /// Default destructor
+               virtual ~AliScalar() {}
+               
+               /// Inherited from TObject. Compares two scalar names.
+               virtual Int_t Compare(const TObject *obj) const
+               {
+                       return fName.CompareTo(obj->GetName());
+               }
+               
+               /// Inherited from TObject. Returns true.
+               virtual Bool_t IsSortable() const { return kTRUE; }
+               
+               /**
+                * Inherited from TObject.
+                * Returns true if the names of the scalars are the same.
+                */
+               virtual Bool_t IsEqual(const TObject *obj) const
+               {
+                       return fName == obj->GetName();
+               }
+               
+               /// Resets the scalar value to zero.
+               virtual void Clear(Option_t* /*option*/ = "") { fValue = 0; }
+       
+               /// Inherited from TObject. Performs a deep copy.
+               virtual void Copy(TObject& object) const;
+               
+               /// Returns the value of the scalar.
+               Double_t Value() const { return fValue; }
+
+               /// Sets a new value for the scalar.
+               void Value(Double_t value) { fValue = value; }
+
+               /**
+                * Increments the scalar by a value of 'count'.
+                * \param count  The number to increment the scalar by. The default is 1.
+                */
+               void Increment(UInt_t count = 1) { fValue += count; }
+               
+               /// Returns the name of the scalar.
+               const char* Name() const { return fName.Data(); }
+               
+               /// Returns the description string for the scalar.
+               const char* Description() const { return fTitle.Data(); }
+               
+               /// Checks if two scalar objects are identical.
+               bool operator == (const AliScalar& x) const
+               {
+                       return fValue == x.fValue and fName == x.fName and fTitle == x.fTitle;
+               }
+               
+               /// Checks if two scalar objects are not identical.
+               bool operator != (const AliScalar& x) const
+               {
+                       return not (this->operator == (x));
+               }
+               
+               /// Typecast operator for returning the value directly.
+               operator Double_t () { return fValue; }
+               
+       private:
+               Double_t fValue; // The scalar's value.
+               
+               ClassDef(AliScalar, 1);  // HLT scalar value.
+       };
+       
+       /// Default constructor.
+       AliHLTScalars();
+       
+       /// The copy constructor performs a deep copy.
+       AliHLTScalars(const AliHLTScalars& obj);
+       
+       /// Default destructor.
+       virtual ~AliHLTScalars();
+       
+       /**
+        * Adds a new scalar to the end of the scalars list.
+        * If the scalar already exists then its values are updated instead.
+        * \param name  The name of the scalar.
+        * \param description  A short description of the scalar.
+        * \param value  The value of the new scalar.
+        * \returns true if the scalar already exists and false otherwise.
+        */
+       virtual bool Add(const char* name, const char* description = NULL, Double_t value = 0);
+
+       /**
+        * Removes a named scalar from the scalars list.
+        * \param name  The name of the scalar to remove.
+        * \returns true if the scalar existed and false otherwise.
+        * \note The scalars list is compressed so this method will be slow.
+        *    In addition, scalar positions will change if not removing from the end.
+        */
+       virtual bool Remove(const char* name);
+       
+       /// Checks to see if the named scalar exists.
+       bool Exists(const char* name) const { return fMap.FindObject(name) != NULL; }
+
+       /**
+        * Fetches the specified scalar object.
+        * \param name  The name of the scalar object.
+        * \returns the found scalar object, otherwise an empty sentinel object with
+        *    zeros. One can tell it is a sentinel because the name will be empty.
+        */
+       const AliScalar& GetScalar(const char* name) const;
+
+       /**
+        * Fetches the specified scalar object for editing.
+        * \param name  The name of the scalar object.
+        * \returns the found scalar object. If the scalar does not already
+        *     exist then a new one is created and returned.
+        */
+       AliScalar& GetScalar(const char* name);
+
+       /// Returns the number of scalar values.
+       UInt_t NumberOfScalars() const { return UInt_t(fScalars.GetEntriesFast()); }
+
+       // Note: the following GetScalarN methods do not use the same name as
+       // GetScalar above because the parameter type would unfortunately be
+       // ambiguous to an ISO c++ compiler.
+       
+       /**
+        * Fetches the n'th scalar object.
+        * \param n  The number of the scalar object.
+        * \returns the found scalar object, otherwise an empty sentinel object with
+        *    zeros. One can tell it is a sentinel because the name will be empty.
+        */
+       const AliScalar& GetScalarN(UInt_t n) const;
+
+       /**
+        * Fetches the n'th scalar object for editing.
+        * \param n  The number of the scalar object.
+        * \returns the found scalar object. If the scalar does not already
+        *     exist then a new one is created and returned.
+        */
+       AliScalar& GetScalarN(UInt_t n);
+       
+       /// Resets all scalar values to zero.
+       void Reset();
+       
+       /**
+        * Removes all the scalars from the internal array.
+        * \param option  This is passed onto the internal Delete method.
+        */
+       virtual void Clear(Option_t* option = "");
+       
+       /// Inherited form TObject. Performs a deep copy.
+       virtual void Copy(TObject& object) const;
+       
+       /// Finds the scalar object by name.
+       virtual TObject* FindObject(const char* name) const
+       {
+               return fMap.FindObject(name);
+       }
+       
+       /// Finds the scalar object with the same name as obj->GetName().
+       virtual TObject* FindObject(const TObject* obj) const
+       {
+               return fMap.FindObject(obj->GetName());
+       }
+       
+       /**
+        * Inherited from TObject, this prints the contents of all the scalars.
+        * \param option  Can be "compact", which will just print all the values on one line.
+        */
+       virtual void Print(Option_t* option = "") const;
+       
+       /**
+        * The assignment operator performs a deep copy.
+        */
+       AliHLTScalars& operator = (const AliHLTScalars& obj);
+       
+       /// Returns the n'th scalar or a zero sentinel if n is out of range.
+       const AliScalar& operator [] (UInt_t n) const { return GetScalarN(n); }
+
+       /// Returns the n'th scalar for editing. A new scalar is created if n is out of range.
+       AliScalar& operator [] (UInt_t n) { return GetScalarN(n); }
+
+       /// Returns the named scalar or a zero sentinel if no such scalar is found.
+       const AliScalar& operator [] (const TString& name) const { return GetScalar(name.Data()); }
+
+       /// Returns the named scalar for editing. A new scalar is created if n is out of range.
+       AliScalar& operator [] (const TString& name) { return GetScalar(name.Data()); }
+
+       /**
+        * Inherited from TObject.
+        * Returns true if the names of the two sets of scalars are the same.
+        * \note The actual values are not checked. Use the comparison operator for that.
+        */
+       virtual Bool_t IsEqual(const TObject *obj) const;
+       
+       /**
+        * Comparison operator to check if two sets of scalars have the same values.
+        * \note The description strings are not checked so they could be different
+        *   and the order of the scalars does not matter either.
+        */
+       bool operator == (const AliHLTScalars& obj) const;
+       
+       /**
+        * Comparison operator to check if two sets of scalars are different.
+        * \note The description strings are not checked, only the values are.
+        *   In addition, the order of the scalars does not matter.
+        */
+       bool operator != (const AliHLTScalars& obj) const
+       {
+               return not (this->operator == (obj));
+       }
+
+protected:
+       
+       /**
+        * Constructor that can be used by deriving classes to overload the class stored
+        * in the fScalars TClonesArray.
+        * \param cl  The class to use in the fScalars as passed to the TClonesArray constructor.
+        * \param initSize  The initial approximate number of elements in fScalars. (Default = 128).
+        */
+       AliHLTScalars(const TClass* cl, Int_t initSize = 128);
+       
+private:
+       
+       TClonesArray fScalars;  // List of scalar objects.
+       THashTable fMap;        //! Hash table of pointers to the scalars for fast lookup.
+       
+       ClassDef(AliHLTScalars, 1);  // Set of HLT scalars.
+};
+
+#endif // AliHLTSCALARS_H
index e84ad6b..4a810ba 100644 (file)
 #pragma link C++ class AliHLTRunStatistics+;
 #pragma link C++ class AliHLTMisc+;
 #pragma link C++ class AliHLTCTPData+;
+#pragma link C++ class AliHLTScalars+;
+#pragma link C++ class AliHLTScalars::AliScalar+;
 
 #pragma link C++ struct AliHLTComponentEventData+;
 #pragma link C++ struct AliHLTComponentBlockData+;
index 6b34881..bad38c4 100644 (file)
@@ -10,6 +10,7 @@ check_PROGRAMS        = testAliHLTBlockDataCollection \
                  testAliHLTCTPData \
                  testAliHLTDataBuffer \
                  testAliHLTReadoutList \
+                 testAliHLTScalars \
                  testAliHLTEventDDLBackwardCompatibility \
                  dtOperators \
                  testDefaultDataTypes
@@ -45,6 +46,13 @@ testAliHLTReadoutList_LDADD = $(top_builddir)/BASE/libHLTbase.la \
                                @ALIROOT_LDFLAGS@ \
                                @ALIROOT_LIBS@
 
+testAliHLTScalars_SOURCES = testAliHLTScalars.C
+testAliHLTScalars_LDADD = $(top_builddir)/BASE/libHLTbase.la \
+                               -L@ROOTLIBDIR@ \
+                               @ROOTLIBS@ \
+                               @ALIROOT_LDFLAGS@ \
+                               @ALIROOT_LIBS@
+
 testAliHLTEventDDLBackwardCompatibility_SOURCES = testAliHLTEventDDLBackwardCompatibility.C
 testAliHLTEventDDLBackwardCompatibility_LDADD = $(top_builddir)/BASE/libHLTbase.la \
                                -L@ROOTLIBDIR@ \
diff --git a/HLT/BASE/test/testAliHLTScalars.C b/HLT/BASE/test/testAliHLTScalars.C
new file mode 100644 (file)
index 0000000..9359ae6
--- /dev/null
@@ -0,0 +1,277 @@
+// $Id: $
+
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  for The ALICE HLT Project.                            *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/// @file   testAliHLTScalars.C
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   27 Oct 2010
+/// @brief  Test program for the AliHLTScalars class.
+///
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include "AliHLTScalars.h"
+#include "TObjArray.h"
+#include "TString.h"
+#include "Riostream.h"
+#endif
+
+/**
+ * Tests basic functionality of the AliHLTScalars::AliScalar class.
+ */
+bool CheckScalarItemClass()
+{
+       AliHLTScalars::AliScalar s1("s1", "scalar one", 1);
+       AliHLTScalars::AliScalar s2("s2", "scalar two", 2);
+       AliHLTScalars::AliScalar s3("s2", "scalar two", 3);
+       if (TString(s1.GetName()) != s1.Name())
+       {
+               cerr << "ERROR: AliHLTScalars::AliScalar::GetName() returns a different value than AliHLTScalars::AliScalar::Name()." << endl;
+               return false;
+       }
+       if (TString(s1.GetTitle()) != s1.Description())
+       {
+               cerr << "ERROR: AliHLTScalars::AliScalar::GetTitle() returns a different value than AliHLTScalars::AliScalar::Description()." << endl;
+               return false;
+       }
+       if (s2 == s3)
+       {
+               cerr << "ERROR: equals operator for AliHLTScalars::AliScalar returns the wrong value." << endl;
+               return false;
+       }
+       if (! s2.IsEqual(&s3))
+       {
+               cerr << "ERROR: AliHLTScalars::AliScalar::IsEqual returns the wrong value." << endl;
+               return false;
+       }
+       s2.Increment();
+       if (! (s2 == s3))
+       {
+               cerr << "ERROR: equals operator for AliHLTScalars::AliScalar returns the wrong value." << endl;
+               return false;
+       }
+       TObjArray list;
+       list.Add(&s2);
+       list.Add(&s1);
+       list.Sort();
+       if (TString(list.At(0)->GetName()) != "s1")
+       {
+               cerr << "ERROR: Sorting objects of type AliHLTScalars::AliScalar is not working correctly." << endl;
+               return false;
+       }
+       return true;
+}
+
+/**
+ * Tests functionality of the AliHLTScalars class.
+ */
+bool CheckScalarsListClass()
+{
+       AliHLTScalars s;
+       s.Add("a", "one", 1);
+       s.Add("b", "two", 2);
+       if (s.NumberOfScalars() != 2)
+       {
+               cerr << "ERROR: The number of added scalars is wrong for class AliHLTScalars." << endl;
+               return false;
+       }
+       if (! s.Exists("a"))
+       {
+               cerr << "ERROR: AliHLTScalars claims scalar 'a' does not exist event though it was added." << endl;
+               return false;
+       }
+       if (! s.Exists("b"))
+       {
+               cerr << "ERROR: AliHLTScalars claims scalar 'b' does not exist event though it was added." << endl;
+               return false;
+       }
+       s.Remove("a");
+       if (s.Exists("a"))
+       {
+               cerr << "ERROR: AliHLTScalars claims scalar 'a' does not exist event though it was removed." << endl;
+               return false;
+       }
+       s.Add("a", "one", 1);
+       const AliHLTScalars& p = s;
+       if (p.GetScalar("a").Value() != 1)
+       {
+               cerr << "ERROR: Constant version of AliHLTScalars::GetScalar(\"a\") returns the wrong scalar object." << endl;
+               return false;
+       }
+       if (TString(p.GetScalar("c").Name()) != "" || TString(p.GetScalar("c").Description()) != "" || p.GetScalar("c").Value() != 0)
+       {
+               cerr << "ERROR: Constant version of AliHLTScalars::GetScalar(\"c\") does not return a sentinel object." << endl;
+               return false;
+       }
+       if (s.GetScalar("a").Value() != 1)
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalar(\"a\") returns the wrong scalar object." << endl;
+               return false;
+       }
+       s.GetScalar("c").Value(3);
+       if (TString(s.GetScalar("c").Name()) != "c" || TString(s.GetScalar("c").Description()) != "")
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalar(\"c\") does not create a new object." << endl;
+               return false;
+       }
+       s.Add("c", "three", 33);
+       if (s.GetScalar("c").Value() != 33 || TString(s.GetScalar("c").Description()) != "")
+       {
+               cerr << "ERROR: AliHLTScalars::Add did not update and exisiting scalar correctly." << endl;
+               return false;
+       }
+       if (TString(p.GetScalarN(0).Name()) != "b" || TString(p.GetScalarN(1).Name()) != "a" || TString(p.GetScalarN(2).Name()) != "c")
+       {
+               cerr << "ERROR: Constant version of AliHLTScalars::GetScalarN(0) returns the wrong scalar object." << endl;
+               return false;
+       }
+       if (TString(s.GetScalarN(0).Name()) != "b" || TString(s.GetScalarN(1).Name()) != "a" || TString(s.GetScalarN(2).Name()) != "c")
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalarN(0) returns the wrong scalar object." << endl;
+               return false;
+       }
+       if (TString(p.GetScalarN(4).Name()) != "" || TString(p.GetScalarN(4).Description()) != "" || p.GetScalarN(4).Value() != 0)
+       {
+               cerr << "ERROR: Constant version of AliHLTScalars::GetScalarN(4) returns the wrong scalar object." << endl;
+               return false;
+       }
+       s.GetScalarN(4).Value(5);
+       if (TString(s.GetScalarN(4).Name()) != "Scalar4" || TString(s.GetScalarN(4).Description()) != "" || s.GetScalarN(4).Value() != 5)
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalarN(4) does not create a new scalar object correctly." << endl;
+               return false;
+       }
+       if (TString(p.GetScalarN(3).Name()) != "Scalar3" || TString(p.GetScalarN(3).Description()) != "" || p.GetScalarN(3).Value() != 0)
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalarN(4) did not initialise the third scalar as expected." << endl;
+               return false;
+       }
+       
+       // The following is a special check to check for compilation ambiguity
+       // rather than runtime behaviour.
+       if (s[4].Value() != s["Scalar4"].Value())
+       {
+               cerr << "ERROR: AliHLTScalars::operator[](UInt_t) did not return the same value as AliHLTScalars::operator[](const char*)." << endl;
+               return false;
+       }
+       
+       // Here we check to see that the AliHLTScalars::GetScalarN class correctly
+       // checks and finds an unused name.
+       s.Add("Scalar7", "six", 6);
+       s.Add("Scalar7_0", "seven", 7);
+       s.GetScalarN(7).Value(8);
+       if (! s.Exists("Scalar7_1") || s.GetScalarN(7).Value() != 8 || s.GetScalar("Scalar7_1").Value() != 8)
+       {
+               cerr << "ERROR: AliHLTScalars::GetScalarN is not creating a scalar object with a unique name as expected." << endl;
+               return false;
+       }
+       
+       // Check the copying of the object.
+       AliHLTScalars* c1 = (AliHLTScalars*) s.Clone();
+       AliHLTScalars c2;
+       c2 = s;
+       AliHLTScalars c3;
+       s.Copy(c3);
+       if (! (*c1 == s) || *c1 != s)
+       {
+               cerr << "ERROR: The equals operator of AliHLTScalars is not working as expected." << endl;
+               return false;
+       }
+       if (c2 != s)
+       {
+               cerr << "ERROR: The assignment operator of AliHLTScalars is not working as expected." << endl;
+               return false;
+       }
+       if (c3 != s)
+       {
+               cerr << "ERROR: The method AliHLTScalars::Copy is not working as expected." << endl;
+               return false;
+       }
+       delete c1;
+       
+       // Now check the IsEqual and Reset methods:
+       if (! c2.IsEqual(&c3))
+       {
+               cerr << "ERROR: The AliHLTScalars::IsEqual method is not working as expected." << endl;
+               return false;
+       }
+       
+       c3.Reset();
+       for (UInt_t i = 0; i < c3.NumberOfScalars(); ++i)
+       {
+               if (c3[i].Value() != 0)
+               {
+                       cerr << "ERROR: AliHLTScalars::Reset did not reset all scalar values to zero." << endl;
+                       return false;
+               }
+               if (TString(c3[i].Name()) != c2[i].Name())
+               {
+                       cerr << "ERROR: AliHLTScalars::Reset modified the name by mistake." << endl;
+                       return false;
+               }
+               if (TString(c3[i].Description()) != c2[i].Description())
+               {
+                       cerr << "ERROR: AliHLTScalars::Reset modified the description by mistake." << endl;
+                       return false;
+               }
+       }
+       if (! c2.IsEqual(&c3))
+       {
+               cerr << "ERROR: The AliHLTScalars::IsEqual method is not working as expected after call to Reset." << endl;
+               return false;
+       }
+       if (c2 == c3)
+       {
+               cerr << "ERROR: The equals operator for AliHLTScalars is not working as expected after call to Reset." << endl;
+               return false;
+       }
+       
+       c2.Remove("c");
+       if (c2.IsEqual(&c3))
+       {
+               cerr << "ERROR: The AliHLTScalars::IsEqual method is not working as expected after call to Remove." << endl;
+               return false;
+       }
+       if (c2 == c3)
+       {
+               cerr << "ERROR: The equals operator for AliHLTScalars is not working as expected after call to Remove." << endl;
+               return false;
+       }
+       
+       return true;
+}
+
+/**
+ * Runs the unit test for the AliHLTScalars class.
+ * \returns true if the class passed the test and false otherwise.
+ */
+bool testAliHLTScalars()
+{
+       if (! CheckScalarItemClass()) return false;
+       if (! CheckScalarsListClass()) return false;
+       return true;
+}
+
+#ifndef __MAKECINT__
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+       bool resultOk = testAliHLTScalars();
+       if (not resultOk) return 1;
+       return 0;
+}
+
+#endif // __MAKECINT__
index 745b699..aaa047a 100644 (file)
@@ -59,6 +59,7 @@ CLASS_HDRS:=          AliHLTComponent.h \
                 AliHLTTriggerMenuItem.h                     \
                 AliHLTTriggerMenuSymbol.h                   \
                 AliHLTCTPData.h                             \
+                AliHLTScalars.h                             \
                 AliHLTRunStatistics.h