<commit_before>// @(#)root/cont:$Id$
// Author: Philippe Canal October 2013

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TViewPubFunctions                                                    //
//                                                                      //
// View implementing the TList interface and giving access all the      //
// TFunction describing public methods in a class and all its base      //
// classes without caching any of the TFunction pointers.               //
//                                                                      //
// Adding to this collection directly is prohibited.                    //
// Iteration can only be done via the TIterator interfaces.             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TViewPubFunctions.h"

#include "TClass.h"
#include "TBaseClass.h"
#include "TError.h"
#include "TFunction.h"
#include "THashList.h"

// ClassImp(TViewPubFunctions)

//______________________________________________________________________________
static void AddBasesClasses(TList &bases, TClass *cl)
{
   // loop over all base classes and add them to the container.

   TIter nextBaseClass(cl->GetListOfBases());
   TBaseClass *base;
   while ((base = (TBaseClass*) nextBaseClass())) {
      if (!base->GetClassPointer()) continue;
      if (!(base->Property() & kIsPublic)) continue;

      bases.Add(base->GetClassPointer());
      AddBasesClasses(bases,base->GetClassPointer());
   }
}

//______________________________________________________________________________
TViewPubFunctions::TViewPubFunctions(TClass *cl /* = 0 */)
{
   // Usual constructor

   if (cl) {
      fClasses.Add(cl);
      AddBasesClasses(fClasses,cl);
   }
}

//______________________________________________________________________________
TViewPubFunctions::~TViewPubFunctions()
{
   // Default destructor.

}

//______________________________________________________________________________
void TViewPubFunctions::Clear(Option_t * /* option="" */)
{
   // Clear is not allowed in this class.
   // See TList::Clear for the intended behavior.

   ::Error("TViewPubFunctions::Clear","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::Delete(Option_t * /*option="" */)
{
   // Delete is not allowed in this class.
   // See TList::Delete for the intended behavior.

   ::Error("TViewPubFunctions::Delete","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject *TViewPubFunctions::FindObject(const char * name) const
{
   // Find an object in this list using its name. Requires a sequential
   // scan till the object has been found. Returns 0 if object with specified
   // name is not found.

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      THashList *hl = dynamic_cast<THashList*>(cl->GetListOfMethods(kFALSE));
      TIter funcnext(hl->GetListForObject(name));
      while (TFunction *p = (TFunction*) funcnext())
         if (p->Property() & kIsPublic) return p;
   }
   return 0;
}

//______________________________________________________________________________
TObject *TViewPubFunctions::FindObject(const TObject * obj) const
{
   // Find an object in this list using the object's IsEqual()
   // member function. Requires a sequential scan till the object has
   // been found. Returns 0 if object is not found.

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TObject *result = cl->GetListOfMethods(kFALSE)->FindObject(obj);
      if (result) return result;
   }
   return 0;
}

//______________________________________________________________________________
TIterator *TViewPubFunctions::MakeIterator(Bool_t dir /* = kIterForward*/) const
{
   // Return a list iterator.

   return new TViewPubFunctionsIter(this, dir);
}

//______________________________________________________________________________
void TViewPubFunctions::AddFirst(TObject * /* obj */)
{
   // AddFirst is not allowed in this class.
   // See TList::AddFirst for the intended behavior.

   ::Error("TViewPubFunctions::AddFirst","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddFirst(TObject * /* obj */, Option_t * /* opt */)
{
   // AddFirst is not allowed in this class.
   // See TList::AddFirst for the intended behavior.

   ::Error("TViewPubFunctions::AddFirst","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddLast(TObject * /* obj */)
{
   // AddLast is not allowed in this class.
   // See TList::AddLast for the intended behavior.

   ::Error("TViewPubFunctions::AddLast","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddLast(TObject * /* obj */, Option_t * /* opt */)
{
   // AddLast is not allowed in this class.
   // See TList::AddLast for the intended behavior.

   ::Error("TViewPubFunctions::AddLast","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAt(TObject * /* obj */, Int_t /* idx */)
{
   // AddAt is not allowed in this class.
   // See TList::AddAt for the intended behavior.

   ::Error("TViewPubFunctions::AddAt","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAfter(const TObject * /* after */, TObject * /* obj */)
{
   // AddAfter is not allowed in this class.
   // See TList::AddAfter for the intended behavior.

   ::Error("TViewPubFunctions::RemAddLastove","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAfter(TObjLink * /* after */, TObject * /* obj */)
{
   // AddAfter is not allowed in this class.
   // See TList::AddAfter for the intended behavior.

   ::Error("TViewPubFunctions::AddAfter","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddBefore(const TObject * /* before */, TObject * /* obj */)
{
   // AddBefore is not allowed in this class.
   // See TList::AddBefore for the intended behavior.

   ::Error("TViewPubFunctions::AddBefore","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddBefore(TObjLink * /* before */, TObject * /* obj */)
{
   // AddBefore is not allowed in this class.
   // See TList::AddBefore for the intended behavior.

   ::Error("TViewPubFunctions::AddBefore","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::At(Int_t idx) const
{
   // Returns the object at position idx. Returns 0 if idx is out of range.

   Int_t i = 0;
   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TIter funcnext(cl->GetListOfMethods(kFALSE));
      while (TFunction *p = (TFunction*) funcnext()) {
         if (p->Property() & kIsPublic) {
            if (i == idx) return p;
            ++i;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::After(const TObject * /* obj */) const
{
   // After is not allowed in this class.
   // See TList::After for the intended behavior.

   ::Error("TViewPubFunctions::After","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::Before(const TObject * /* obj */) const
{
   // Before is not allowed in this class.
   // See TList::Before for the intended behavior.

   ::Error("TViewPubFunctions::Before","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::First() const
{
   // First is not allowed in this class.
   // See TList::First for the intended behavior.

   ::Error("TViewPubFunctions::First","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObjLink *TViewPubFunctions::FirstLink() const
{
   // FirstLink is not allowed in this class.
   // See TList::FirstLink for the intended behavior.

   ::Error("TViewPubFunctions::FirstLink","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject **TViewPubFunctions::GetObjectRef(const TObject * /* obj */) const
{
   // GetObjectRef is not allowed in this class.
   // See TList::GetObjectRef for the intended behavior.

   ::Error("TViewPubFunctions::GetObjectRef","Operation not yet allowed on a view.");
   return 0;
}

//______________________________________________________________________________
Int_t TViewPubFunctions::GetSize() const
{
   // Return the total number of public methods (currently loaded in the list
   // of functions) in this class and all its base classes.

   Int_t size = 0;
   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TIter funcnext(cl->GetListOfMethods(kFALSE));
      while (TFunction *p = (TFunction*) funcnext())
         if (p->Property() & kIsPublic) ++size;
   }
   return size;

}

//______________________________________________________________________________
void TViewPubFunctions::Load()
{
   // Load all the functions known to the intepreter for the scope 'fClass'
   // and all its bases classes.

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      cl->GetListOfMethods(kTRUE);
   }
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::Last() const
{
   // Last is not allowed in this class.
   // See TList::Last for the intended behavior.

   ::Error("TViewPubFunctions::Last","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObjLink *TViewPubFunctions::LastLink() const
{
   // LastLink is not allowed in this class.
   // See TList::LastLink for the intended behavior.

   ::Error("TViewPubFunctions::LastLink","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
void TViewPubFunctions::RecursiveRemove(TObject * /* obj */)
{
   // RecursiveRemove is not allowed in this class.
   // See TList::RecursiveRemove for the intended behavior.

   ::Error("TViewPubFunctions::RecursiveRemove","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject   *TViewPubFunctions::Remove(TObject * /* obj */)
{
   // Remove is not allowed in this class.
   // See TList::Remove for the intended behavior.

   ::Error("TViewPubFunctions::Remove","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject   *TViewPubFunctions::Remove(TObjLink * /* lnk */)
{
   // Remove is not allowed in this class.
   // See TList::Remove for the intended behavior.

   ::Error("TViewPubFunctions::Remove","Operation not allowed on a view.");
   return 0;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TViewPubFunctionsIter                                                //
//                                                                      //
// Iterator of over the view's content                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

// ClassImp(TViewPubFunctionsIter)

//______________________________________________________________________________
TViewPubFunctionsIter::TViewPubFunctionsIter(const TViewPubFunctions *l, Bool_t dir)
: fView(l),fClassIter(l->GetListOfClasses(),dir), fFuncIter((TCollection *)0),
  fStarted(kFALSE), fDirection(dir)
{
   // Create a new list iterator. By default the iteration direction
   // is kIterForward. To go backward use kIterBackward.
}

//______________________________________________________________________________
TViewPubFunctionsIter::TViewPubFunctionsIter(const TViewPubFunctionsIter &iter) :
   TIterator(iter), fView(iter.fView),
   fClassIter(iter.fClassIter), fFuncIter(iter.fFuncIter),
   fStarted(iter.fStarted), fDirection(iter.fDirection)
{
   // Copy ctor.

}

//______________________________________________________________________________
TIterator &TViewPubFunctionsIter::operator=(const TIterator &rhs)
{
   // Overridden assignment operator.

   const TViewPubFunctionsIter *iter = dynamic_cast<const TViewPubFunctionsIter*>(&rhs);
   if (this != &rhs && iter) {
      fView      = iter->fView;
      fClassIter = iter->fClassIter;
      fFuncIter  = iter->fFuncIter;
      fStarted   = iter->fStarted;
      fDirection = iter->fDirection;
   }
   return *this;
}

//______________________________________________________________________________
TViewPubFunctionsIter &TViewPubFunctionsIter::operator=(const TViewPubFunctionsIter &rhs)
{
   // Overloaded assignment operator.

   if (this != &rhs) {
      fView      = rhs.fView;
      fClassIter = rhs.fClassIter;
      fFuncIter  = rhs.fFuncIter;
      fStarted   = rhs.fStarted;
      fDirection = rhs.fDirection;
   }
   return *this;
}

//______________________________________________________________________________
TObject *TViewPubFunctionsIter::Next()
{
   // Return next object in the list. Returns 0 when no more objects in list.

   if (!fView) return 0;

   if (!fStarted) {
      TClass *current = (TClass*)fClassIter();
      fStarted = kTRUE;
      if (current) {
         fFuncIter.~TIter();
         new (&(fFuncIter)) TIter(current->GetListOfMethods(kFALSE),fDirection);
      } else {
         return 0;
      }
   }

   while (1) {

      TFunction *func = (TFunction *)fFuncIter();
      if (!func) {
         // End of list of functions, move to the next;
         TClass *current = (TClass*)fClassIter();
         if (current) {
            fFuncIter.~TIter();
            new (&(fFuncIter)) TIter(current->GetListOfMethods(kFALSE),fDirection);
            continue;
         } else {
            return 0;
         }
      } else if (func->Property() & kIsPublic) {
         // If it is public we found the next one.
         return func;
      }

   }
   // Not reacheable.
   return 0;
}

//______________________________________________________________________________
void TViewPubFunctionsIter::Reset()
{
   // Reset list iterator.

   fStarted = kFALSE;
   fClassIter.Reset();
}

//______________________________________________________________________________
Bool_t TViewPubFunctionsIter::operator!=(const TIterator &aIter) const
{
   // This operator compares two TIterator objects.

   if (nullptr == (&aIter))
      return 0 != *(fFuncIter);

   const TViewPubFunctionsIter *iter = dynamic_cast<const TViewPubFunctionsIter*>(&aIter);
   if (iter) {
      return (fClassIter != iter->fClassIter || fFuncIter != iter->fFuncIter);
   }
   return false; // for base class we don't implement a comparison
}

//______________________________________________________________________________
Bool_t TViewPubFunctionsIter::operator!=(const TViewPubFunctionsIter &aIter) const
{
   // This operator compares two TViewPubFunctionsIter objects.

   if (nullptr == (&aIter))
      return 0 != *(fFuncIter);

   return (fClassIter != aIter.fClassIter || fFuncIter != aIter.fFuncIter);
}

<commit_msg>In TViewPubFunctions prevent FindObject(name) from returning the wrong function<commit_after>// @(#)root/cont:$Id$
// Author: Philippe Canal October 2013

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TViewPubFunctions                                                    //
//                                                                      //
// View implementing the TList interface and giving access all the      //
// TFunction describing public methods in a class and all its base      //
// classes without caching any of the TFunction pointers.               //
//                                                                      //
// Adding to this collection directly is prohibited.                    //
// Iteration can only be done via the TIterator interfaces.             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TViewPubFunctions.h"

#include "TClass.h"
#include "TBaseClass.h"
#include "TError.h"
#include "TFunction.h"
#include "THashList.h"

// ClassImp(TViewPubFunctions)

//______________________________________________________________________________
static void AddBasesClasses(TList &bases, TClass *cl)
{
   // loop over all base classes and add them to the container.

   TIter nextBaseClass(cl->GetListOfBases());
   TBaseClass *base;
   while ((base = (TBaseClass*) nextBaseClass())) {
      if (!base->GetClassPointer()) continue;
      if (!(base->Property() & kIsPublic)) continue;

      bases.Add(base->GetClassPointer());
      AddBasesClasses(bases,base->GetClassPointer());
   }
}

//______________________________________________________________________________
TViewPubFunctions::TViewPubFunctions(TClass *cl /* = 0 */)
{
   // Usual constructor

   if (cl) {
      fClasses.Add(cl);
      AddBasesClasses(fClasses,cl);
   }
}

//______________________________________________________________________________
TViewPubFunctions::~TViewPubFunctions()
{
   // Default destructor.

}

//______________________________________________________________________________
void TViewPubFunctions::Clear(Option_t * /* option="" */)
{
   // Clear is not allowed in this class.
   // See TList::Clear for the intended behavior.

   ::Error("TViewPubFunctions::Clear","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::Delete(Option_t * /*option="" */)
{
   // Delete is not allowed in this class.
   // See TList::Delete for the intended behavior.

   ::Error("TViewPubFunctions::Delete","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject *TViewPubFunctions::FindObject(const char * name) const
{
   // Find an object in this list using its name. Requires a sequential
   // scan till the object has been found. Returns 0 if object with specified
   // name is not found.

   if (name || name[0]) return 0;

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      THashList *hl = dynamic_cast<THashList*>(cl->GetListOfMethods(kFALSE));
      TIter funcnext(hl->GetListForObject(name));
      while (TFunction *p = (TFunction*) funcnext())
         if (p->Property() & kIsPublic
             && strncmp(p->GetName(),name,strlen(p->GetName())) == 0)
            return p;
   }
   return 0;
}

//______________________________________________________________________________
TObject *TViewPubFunctions::FindObject(const TObject * obj) const
{
   // Find an object in this list using the object's IsEqual()
   // member function. Requires a sequential scan till the object has
   // been found. Returns 0 if object is not found.

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TObject *result = cl->GetListOfMethods(kFALSE)->FindObject(obj);
      if (result) return result;
   }
   return 0;
}

//______________________________________________________________________________
TIterator *TViewPubFunctions::MakeIterator(Bool_t dir /* = kIterForward*/) const
{
   // Return a list iterator.

   return new TViewPubFunctionsIter(this, dir);
}

//______________________________________________________________________________
void TViewPubFunctions::AddFirst(TObject * /* obj */)
{
   // AddFirst is not allowed in this class.
   // See TList::AddFirst for the intended behavior.

   ::Error("TViewPubFunctions::AddFirst","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddFirst(TObject * /* obj */, Option_t * /* opt */)
{
   // AddFirst is not allowed in this class.
   // See TList::AddFirst for the intended behavior.

   ::Error("TViewPubFunctions::AddFirst","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddLast(TObject * /* obj */)
{
   // AddLast is not allowed in this class.
   // See TList::AddLast for the intended behavior.

   ::Error("TViewPubFunctions::AddLast","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddLast(TObject * /* obj */, Option_t * /* opt */)
{
   // AddLast is not allowed in this class.
   // See TList::AddLast for the intended behavior.

   ::Error("TViewPubFunctions::AddLast","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAt(TObject * /* obj */, Int_t /* idx */)
{
   // AddAt is not allowed in this class.
   // See TList::AddAt for the intended behavior.

   ::Error("TViewPubFunctions::AddAt","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAfter(const TObject * /* after */, TObject * /* obj */)
{
   // AddAfter is not allowed in this class.
   // See TList::AddAfter for the intended behavior.

   ::Error("TViewPubFunctions::RemAddLastove","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddAfter(TObjLink * /* after */, TObject * /* obj */)
{
   // AddAfter is not allowed in this class.
   // See TList::AddAfter for the intended behavior.

   ::Error("TViewPubFunctions::AddAfter","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddBefore(const TObject * /* before */, TObject * /* obj */)
{
   // AddBefore is not allowed in this class.
   // See TList::AddBefore for the intended behavior.

   ::Error("TViewPubFunctions::AddBefore","Operation not allowed on a view.");
}

//______________________________________________________________________________
void TViewPubFunctions::AddBefore(TObjLink * /* before */, TObject * /* obj */)
{
   // AddBefore is not allowed in this class.
   // See TList::AddBefore for the intended behavior.

   ::Error("TViewPubFunctions::AddBefore","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::At(Int_t idx) const
{
   // Returns the object at position idx. Returns 0 if idx is out of range.

   Int_t i = 0;
   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TIter funcnext(cl->GetListOfMethods(kFALSE));
      while (TFunction *p = (TFunction*) funcnext()) {
         if (p->Property() & kIsPublic) {
            if (i == idx) return p;
            ++i;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::After(const TObject * /* obj */) const
{
   // After is not allowed in this class.
   // See TList::After for the intended behavior.

   ::Error("TViewPubFunctions::After","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::Before(const TObject * /* obj */) const
{
   // Before is not allowed in this class.
   // See TList::Before for the intended behavior.

   ::Error("TViewPubFunctions::Before","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::First() const
{
   // First is not allowed in this class.
   // See TList::First for the intended behavior.

   ::Error("TViewPubFunctions::First","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObjLink *TViewPubFunctions::FirstLink() const
{
   // FirstLink is not allowed in this class.
   // See TList::FirstLink for the intended behavior.

   ::Error("TViewPubFunctions::FirstLink","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject **TViewPubFunctions::GetObjectRef(const TObject * /* obj */) const
{
   // GetObjectRef is not allowed in this class.
   // See TList::GetObjectRef for the intended behavior.

   ::Error("TViewPubFunctions::GetObjectRef","Operation not yet allowed on a view.");
   return 0;
}

//______________________________________________________________________________
Int_t TViewPubFunctions::GetSize() const
{
   // Return the total number of public methods (currently loaded in the list
   // of functions) in this class and all its base classes.

   Int_t size = 0;
   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      TIter funcnext(cl->GetListOfMethods(kFALSE));
      while (TFunction *p = (TFunction*) funcnext())
         if (p->Property() & kIsPublic) ++size;
   }
   return size;

}

//______________________________________________________________________________
void TViewPubFunctions::Load()
{
   // Load all the functions known to the intepreter for the scope 'fClass'
   // and all its bases classes.

   TIter next(&fClasses);
   while (TClass *cl = (TClass*)next()) {
      cl->GetListOfMethods(kTRUE);
   }
}

//______________________________________________________________________________
TObject  *TViewPubFunctions::Last() const
{
   // Last is not allowed in this class.
   // See TList::Last for the intended behavior.

   ::Error("TViewPubFunctions::Last","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObjLink *TViewPubFunctions::LastLink() const
{
   // LastLink is not allowed in this class.
   // See TList::LastLink for the intended behavior.

   ::Error("TViewPubFunctions::LastLink","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
void TViewPubFunctions::RecursiveRemove(TObject * /* obj */)
{
   // RecursiveRemove is not allowed in this class.
   // See TList::RecursiveRemove for the intended behavior.

   ::Error("TViewPubFunctions::RecursiveRemove","Operation not allowed on a view.");
}

//______________________________________________________________________________
TObject   *TViewPubFunctions::Remove(TObject * /* obj */)
{
   // Remove is not allowed in this class.
   // See TList::Remove for the intended behavior.

   ::Error("TViewPubFunctions::Remove","Operation not allowed on a view.");
   return 0;
}

//______________________________________________________________________________
TObject   *TViewPubFunctions::Remove(TObjLink * /* lnk */)
{
   // Remove is not allowed in this class.
   // See TList::Remove for the intended behavior.

   ::Error("TViewPubFunctions::Remove","Operation not allowed on a view.");
   return 0;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TViewPubFunctionsIter                                                //
//                                                                      //
// Iterator of over the view's content                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

// ClassImp(TViewPubFunctionsIter)

//______________________________________________________________________________
TViewPubFunctionsIter::TViewPubFunctionsIter(const TViewPubFunctions *l, Bool_t dir)
: fView(l),fClassIter(l->GetListOfClasses(),dir), fFuncIter((TCollection *)0),
  fStarted(kFALSE), fDirection(dir)
{
   // Create a new list iterator. By default the iteration direction
   // is kIterForward. To go backward use kIterBackward.
}

//______________________________________________________________________________
TViewPubFunctionsIter::TViewPubFunctionsIter(const TViewPubFunctionsIter &iter) :
   TIterator(iter), fView(iter.fView),
   fClassIter(iter.fClassIter), fFuncIter(iter.fFuncIter),
   fStarted(iter.fStarted), fDirection(iter.fDirection)
{
   // Copy ctor.

}

//______________________________________________________________________________
TIterator &TViewPubFunctionsIter::operator=(const TIterator &rhs)
{
   // Overridden assignment operator.

   const TViewPubFunctionsIter *iter = dynamic_cast<const TViewPubFunctionsIter*>(&rhs);
   if (this != &rhs && iter) {
      fView      = iter->fView;
      fClassIter = iter->fClassIter;
      fFuncIter  = iter->fFuncIter;
      fStarted   = iter->fStarted;
      fDirection = iter->fDirection;
   }
   return *this;
}

//______________________________________________________________________________
TViewPubFunctionsIter &TViewPubFunctionsIter::operator=(const TViewPubFunctionsIter &rhs)
{
   // Overloaded assignment operator.

   if (this != &rhs) {
      fView      = rhs.fView;
      fClassIter = rhs.fClassIter;
      fFuncIter  = rhs.fFuncIter;
      fStarted   = rhs.fStarted;
      fDirection = rhs.fDirection;
   }
   return *this;
}

//______________________________________________________________________________
TObject *TViewPubFunctionsIter::Next()
{
   // Return next object in the list. Returns 0 when no more objects in list.

   if (!fView) return 0;

   if (!fStarted) {
      TClass *current = (TClass*)fClassIter();
      fStarted = kTRUE;
      if (current) {
         fFuncIter.~TIter();
         new (&(fFuncIter)) TIter(current->GetListOfMethods(kFALSE),fDirection);
      } else {
         return 0;
      }
   }

   while (1) {

      TFunction *func = (TFunction *)fFuncIter();
      if (!func) {
         // End of list of functions, move to the next;
         TClass *current = (TClass*)fClassIter();
         if (current) {
            fFuncIter.~TIter();
            new (&(fFuncIter)) TIter(current->GetListOfMethods(kFALSE),fDirection);
            continue;
         } else {
            return 0;
         }
      } else if (func->Property() & kIsPublic) {
         // If it is public we found the next one.
         return func;
      }

   }
   // Not reacheable.
   return 0;
}

//______________________________________________________________________________
void TViewPubFunctionsIter::Reset()
{
   // Reset list iterator.

   fStarted = kFALSE;
   fClassIter.Reset();
}

//______________________________________________________________________________
Bool_t TViewPubFunctionsIter::operator!=(const TIterator &aIter) const
{
   // This operator compares two TIterator objects.

   if (nullptr == (&aIter))
      return 0 != *(fFuncIter);

   const TViewPubFunctionsIter *iter = dynamic_cast<const TViewPubFunctionsIter*>(&aIter);
   if (iter) {
      return (fClassIter != iter->fClassIter || fFuncIter != iter->fFuncIter);
   }
   return false; // for base class we don't implement a comparison
}

//______________________________________________________________________________
Bool_t TViewPubFunctionsIter::operator!=(const TViewPubFunctionsIter &aIter) const
{
   // This operator compares two TViewPubFunctionsIter objects.

   if (nullptr == (&aIter))
      return 0 != *(fFuncIter);

   return (fClassIter != aIter.fClassIter || fFuncIter != aIter.fFuncIter);
}

<|endoftext|>


<commit_before>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
#include <string>
#include <sstream>
#include "phIO.h"
#include "phComm.h"
#include "phio_base.h"
#include "ph_mpi_help.h"

#ifndef PHASTAIO_TIMERS_ON
#define PHASTAIO_TIMERS_ON 0
#endif
struct phastaio_stats {
  double readTime;
  double writeTime;
  double openTime;
  double closeTime;
  size_t readBytes;
  size_t writeBytes;
};
phastaio_stats phio_global_stats;

namespace {
  inline double getTime() {
    return MPI_Wtime();
  }
  inline size_t getSize(const char* t) {
    std::string type(t);
    if(type == "integer")
      return sizeof(int);
    else if(type == "double")
      return sizeof(double);
    else {
      assert(0);
      exit(EXIT_FAILURE);
    }
  }
}

#define PHIO_TRACING 0
namespace {
  void trace(const char* key, const char* aux="", void* obj=NULL) {
    if(PHIO_TRACING)
      fprintf(stderr, "PHIO_TRACE entering %s %s %p\n", key, aux, obj);
  }
  void printMinMaxAvg(const char* key, size_t v) {
    int val = static_cast<int>(v);
    int min = ph_min_int(val);
    int max = ph_max_int(val);
    long tot = ph_add_long(static_cast<long>(val));
    double avg = tot/static_cast<double>(ph_peers());
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %d %d %f\n",
          key, min, max, avg);
  }

  void printMinMaxAvg(const char* key, double v) {
    double min = ph_min_double(v);
    double max = ph_max_double(v);
    double tot = ph_add_double(v);
    double avg = tot/ph_peers();
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %f %f %f\n",
          key, min, max, avg);
  }
}

#ifdef __cplusplus
extern "C" {
#endif

void phio_printStats() {
  const int mebi=1024*1024;
  printMinMaxAvg("readTime (s)",phio_getReadTime());
  printMinMaxAvg("writeTime (s)", phio_getWriteTime());
  printMinMaxAvg("openTime (s)", phio_getOpenTime());
  printMinMaxAvg("closeTime (s)", phio_getCloseTime());
  printMinMaxAvg("readBytes (B)", phio_getReadBytes());
  printMinMaxAvg("writeBytes (B)", phio_getWriteBytes());
  printMinMaxAvg("readBandwidth (MiB/s)",
      (phio_getReadBytes()/phio_getReadTime())/mebi);
  printMinMaxAvg("writeBandwidth (MiB/s)",
      (phio_getWriteBytes()/phio_getWriteTime())/mebi);
}

void phio_initStats() {
  phio_global_stats.readTime = 0;
  phio_global_stats.writeTime = 0;
  phio_global_stats.openTime = 0;
  phio_global_stats.closeTime = 0;
  phio_global_stats.readBytes = 0;
  phio_global_stats.writeBytes = 0;
}

double phio_getReadTime() {
  return phio_global_stats.readTime;
}

double phio_getWriteTime() {
  return phio_global_stats.writeTime;
}

double phio_getOpenTime() {
  return phio_global_stats.openTime;
}

double phio_getCloseTime() {
  return phio_global_stats.closeTime;
}

size_t phio_getReadBytes() {
  return phio_global_stats.readBytes;
}

size_t phio_getWriteBytes() {
  return phio_global_stats.writeBytes;
}

void phio_readheader(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readheader(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize("integer");
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writeheader(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const int* ndataItems,
    const char datatype[],
    const char iotype[] ) {
  const double t0 = getTime();
  f->ops->writeheader(f->file, keyphrase, valueArray,
      nItems, ndataItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize("integer");
  phio_global_stats.writeTime += getTime()-t0;
}
void phio_readdatablock(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readdatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writedatablock(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const char datatype[],
    const char iotype[]) {
  const double t0 = getTime();
  f->ops->writedatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}

void phio_constructName(
    phio_fp f,
    const char inName[],
    char* outName) {
  f->ops->constructname(inName, outName);
}

void phio_openfile(
    const char filename[],
    phio_fp f) {
  const double t0 = getTime();
  trace("openfile",filename,f);
  f->ops->openfile(filename, f);
  phio_global_stats.openTime += getTime()-t0;
}

void phio_closefile(phio_fp f) {
  const double t0 = getTime();
  trace("closefile","unknown",f);
  f->ops->closefile(f);
  phio_global_stats.closeTime += getTime()-t0;
}

void phio_appendInt(char* dest, int v) {
  std::stringstream ss;
  ss << dest << v << '.';
  std::string s = ss.str();
  strcpy(dest, s.c_str());
}

#ifdef __cplusplus
}
#endif
<commit_msg>Revert "common: headers only contain integers"<commit_after>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
#include <string>
#include <sstream>
#include "phIO.h"
#include "phComm.h"
#include "phio_base.h"
#include "ph_mpi_help.h"

#ifndef PHASTAIO_TIMERS_ON
#define PHASTAIO_TIMERS_ON 0
#endif
struct phastaio_stats {
  double readTime;
  double writeTime;
  double openTime;
  double closeTime;
  size_t readBytes;
  size_t writeBytes;
};
phastaio_stats phio_global_stats;

namespace {
  inline double getTime() {
    return MPI_Wtime();
  }
  inline size_t getSize(const char* t) {
    std::string type(t);
    if(type == "integer")
      return sizeof(int);
    else if(type == "double")
      return sizeof(double);
    else {
      assert(0);
      exit(EXIT_FAILURE);
    }
  }
}

#define PHIO_TRACING 0
namespace {
  void trace(const char* key, const char* aux="", void* obj=NULL) {
    if(PHIO_TRACING)
      fprintf(stderr, "PHIO_TRACE entering %s %s %p\n", key, aux, obj);
  }
  void printMinMaxAvg(const char* key, size_t v) {
    int val = static_cast<int>(v);
    int min = ph_min_int(val);
    int max = ph_max_int(val);
    long tot = ph_add_long(static_cast<long>(val));
    double avg = tot/static_cast<double>(ph_peers());
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %d %d %f\n",
          key, min, max, avg);
  }

  void printMinMaxAvg(const char* key, double v) {
    double min = ph_min_double(v);
    double max = ph_max_double(v);
    double tot = ph_add_double(v);
    double avg = tot/ph_peers();
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %f %f %f\n",
          key, min, max, avg);
  }
}

#ifdef __cplusplus
extern "C" {
#endif

void phio_printStats() {
  const int mebi=1024*1024;
  printMinMaxAvg("readTime (s)",phio_getReadTime());
  printMinMaxAvg("writeTime (s)", phio_getWriteTime());
  printMinMaxAvg("openTime (s)", phio_getOpenTime());
  printMinMaxAvg("closeTime (s)", phio_getCloseTime());
  printMinMaxAvg("readBytes (B)", phio_getReadBytes());
  printMinMaxAvg("writeBytes (B)", phio_getWriteBytes());
  printMinMaxAvg("readBandwidth (MiB/s)",
      (phio_getReadBytes()/phio_getReadTime())/mebi);
  printMinMaxAvg("writeBandwidth (MiB/s)",
      (phio_getWriteBytes()/phio_getWriteTime())/mebi);
}

void phio_initStats() {
  phio_global_stats.readTime = 0;
  phio_global_stats.writeTime = 0;
  phio_global_stats.openTime = 0;
  phio_global_stats.closeTime = 0;
  phio_global_stats.readBytes = 0;
  phio_global_stats.writeBytes = 0;
}

double phio_getReadTime() {
  return phio_global_stats.readTime;
}

double phio_getWriteTime() {
  return phio_global_stats.writeTime;
}

double phio_getOpenTime() {
  return phio_global_stats.openTime;
}

double phio_getCloseTime() {
  return phio_global_stats.closeTime;
}

size_t phio_getReadBytes() {
  return phio_global_stats.readBytes;
}

size_t phio_getWriteBytes() {
  return phio_global_stats.writeBytes;
}

void phio_readheader(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readheader(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writeheader(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const int* ndataItems,
    const char datatype[],
    const char iotype[] ) {
  const double t0 = getTime();
  f->ops->writeheader(f->file, keyphrase, valueArray,
      nItems, ndataItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}
void phio_readdatablock(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readdatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writedatablock(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const char datatype[],
    const char iotype[]) {
  const double t0 = getTime();
  f->ops->writedatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}

void phio_constructName(
    phio_fp f,
    const char inName[],
    char* outName) {
  f->ops->constructname(inName, outName);
}

void phio_openfile(
    const char filename[],
    phio_fp f) {
  const double t0 = getTime();
  trace("openfile",filename,f);
  f->ops->openfile(filename, f);
  phio_global_stats.openTime += getTime()-t0;
}

void phio_closefile(phio_fp f) {
  const double t0 = getTime();
  trace("closefile","unknown",f);
  f->ops->closefile(f);
  phio_global_stats.closeTime += getTime()-t0;
}

void phio_appendInt(char* dest, int v) {
  std::stringstream ss;
  ss << dest << v << '.';
  std::string s = ss.str();
  strcpy(dest, s.c_str());
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Trolltech ASA
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "globalconfig_p.h"

#include "factory_p.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "platformplugin.h"
#include "backendinterface.h"
#include "qsettingsgroup_p.h"
#include "phononnamespace_p.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

QT_BEGIN_NAMESPACE

namespace Phonon
{

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

enum WhatToFilter {
    FilterAdvancedDevices = 1,
    FilterHardwareDevices = 2
};

static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
{
    QMutableListIterator<int> it(*list);
    while (it.hasNext()) {
        const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(type, it.next());
        QVariant var;
        if (whatToFilter & FilterAdvancedDevices) {
            var = properties.value("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
        if (whatToFilter & FilterHardwareDevices) {
            var = properties.value("isHardwareDevice");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
    }
}

static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList<int> &defaultList)
{
    if (defaultList.size() <= 1) {
        // nothing to sort
        return defaultList;
    } else {
        // make entries unique
        QSet<int> seen;
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            if (seen.contains(it.next())) {
                it.remove();
            } else {
                seen.insert(it.value());
            }
        }
    }

    QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
    if (!backendConfig.hasKey(categoryKey)) {
        // no list in config for the given category
        categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
        if (!backendConfig.hasKey(categoryKey)) {
            // no list in config for NoCategory
            return defaultList;
        }
    }

    //Now the list from m_config
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());

    //if there are devices in m_config that the backend doesn't report, remove them from the list
    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            i.remove();
        }
    }

    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
            const QVariant var = objDesc.property("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioOutputDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                    );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
            const QVariant var = objDesc.property("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioCaptureDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                  );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioCaptureDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

} // namespace Phonon

QT_END_NAMESPACE

#include "moc_globalconfig_p.cpp"

// vim: sw=4 ts=4
<commit_msg>unhide advanced devices from the platform plugin BUG: 166713<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Trolltech ASA
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "globalconfig_p.h"

#include "factory_p.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "platformplugin.h"
#include "backendinterface.h"
#include "qsettingsgroup_p.h"
#include "phononnamespace_p.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

QT_BEGIN_NAMESPACE

namespace Phonon
{

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

enum WhatToFilter {
    FilterAdvancedDevices = 1,
    FilterHardwareDevices = 2
};

static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
{
    QMutableListIterator<int> it(*list);
    while (it.hasNext()) {
        const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(type, it.next());
        QVariant var;
        if (whatToFilter & FilterAdvancedDevices) {
            var = properties.value("isAdvanced");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
        if (whatToFilter & FilterHardwareDevices) {
            var = properties.value("isHardwareDevice");
            if (var.isValid() && var.toBool()) {
                it.remove();
                continue;
            }
        }
    }
}

static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList<int> &defaultList)
{
    if (defaultList.size() <= 1) {
        // nothing to sort
        return defaultList;
    } else {
        // make entries unique
        QSet<int> seen;
        QMutableListIterator<int> it(defaultList);
        while (it.hasNext()) {
            if (seen.contains(it.next())) {
                it.remove();
            } else {
                seen.insert(it.value());
            }
        }
    }

    QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
    if (!backendConfig.hasKey(categoryKey)) {
        // no list in config for the given category
        categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
        if (!backendConfig.hasKey(categoryKey)) {
            // no list in config for NoCategory
            return defaultList;
        }
    }

    //Now the list from m_config
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());

    //if there are devices in m_config that the backend doesn't report, remove them from the list
    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            i.remove();
        }
    }

    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices) {
            QMutableListIterator<int> it(defaultList);
            while (it.hasNext()) {
                AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
                const QVariant var = objDesc.property("isAdvanced");
                if (var.isValid() && var.toBool()) {
                    it.remove();
                }
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioOutputDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                    );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, HideAdvancedDevicesOverride override) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = (override == FromSettings
            ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
            : static_cast<bool>(override));

    PlatformPlugin *platformPlugin = Factory::platformPlugin();
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());

    QList<int> defaultList;
    if (platformPlugin) {
        // the platform plugin lists the audio devices for the platform
        // this list already is in default order (as defined by the platform plugin)
        defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices) {
            QMutableListIterator<int> it(defaultList);
            while (it.hasNext()) {
                AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
                const QVariant var = objDesc.property("isAdvanced");
                if (var.isValid() && var.toBool()) {
                    it.remove();
                }
            }
        }
    }

    // lookup the available devices directly from the backend (mostly for virtual devices)
    if (backendIface) {
        // this list already is in default order (as defined by the backend)
        QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
        if (hideAdvancedDevices || !defaultList.isEmpty()) {
            filter(AudioCaptureDeviceType, backendIface, &list,
                    (hideAdvancedDevices ? FilterAdvancedDevices : 0)
                    // the platform plugin already provided the hardware devices
                    | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
                  );
        }
        defaultList += list;
    }

    return listSortedByConfig(backendConfig, category, defaultList);
}

int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioCaptureDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

} // namespace Phonon

QT_END_NAMESPACE

#include "moc_globalconfig_p.cpp"

// vim: sw=4 ts=4
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2014 The QXmpp developers
 *
 * Author:
 *	Manjeet Dahiya
 *
 * Source:
 *	https://github.com/qxmpp-project/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "capabilitiesCache.h"

#include "QXmppClient.h"
#include "QXmppDiscoveryManager.h"
#include <utils.h>

#include <QCoreApplication>
#include <QXmlStreamWriter>
#include <QDir>

capabilitiesCache::capabilitiesCache(QXmppClient* client) :
    QObject(client), m_client(client)
{
    QXmppDiscoveryManager* ext = m_client->findExtension<QXmppDiscoveryManager>();
    if(ext)
    {
        bool check = connect(ext, SIGNAL(infoReceived(QXmppDiscoveryIq)),
                             SLOT(infoReceived(QXmppDiscoveryIq)));
        Q_ASSERT(check);
        Q_UNUSED(check);
    }
}

bool capabilitiesCache::isCapabilityAvailable(const QString& nodeVer)
{
    return m_mapCapabilities.contains(nodeVer);
}

void capabilitiesCache::requestInfo(const QString& jid, const QString& node)
{
    QXmppDiscoveryManager* ext = m_client->findExtension<QXmppDiscoveryManager>();
    if(ext)
    {
        bool alreadyRequested = false;
        foreach(QString key, m_mapIdNodeVer.keys())
        {
            if(m_mapIdNodeVer[key] == node)
            {
                alreadyRequested = true;
                break;
            }
        }

        if(!alreadyRequested)
        {
            QString id = ext->requestInfo(jid, node);
            m_mapIdNodeVer[id] = node;
        }
    }
}

void capabilitiesCache::infoReceived(const QXmppDiscoveryIq& discoIqRcv)
{
    QXmppDiscoveryIq discoIq = discoIqRcv;
    if(discoIq.queryType() == QXmppDiscoveryIq::InfoQuery &&
       discoIq.type() == QXmppIq::Result)
    {
        if(discoIq.queryNode().isEmpty())
        {
            discoIq.setQueryNode(m_mapIdNodeVer[discoIq.id()]);
            m_mapIdNodeVer.remove(discoIq.id());
        }

        discoIq.setTo("");
        discoIq.setFrom("");
        discoIq.setId("");
        m_mapCapabilities[discoIq.queryNode()] = discoIq;
        saveToFile(discoIq.queryNode());
    }
}

void capabilitiesCache::loadFromFile()
{
    m_mapCapabilities.clear();

    QDir dirCaps(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/");
    if(dirCaps.exists())
    {
        QStringList list = dirCaps.entryList(QStringList("*.xml"));
        foreach(QString fileName, list)
        {
            QFile file(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/" + fileName);
            if(file.open(QIODevice::ReadOnly))
            {
                QDomDocument doc;
                if(doc.setContent(&file, true))
                {
                    QXmppDiscoveryIq discoIq;
                    discoIq.parse(doc.documentElement());
                    m_mapCapabilities[discoIq.queryNode()] = discoIq;
                    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
                }
            }
        }
    }
}

void capabilitiesCache::saveToFile(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return;

    QString fileName = getSha1HashAsHex(nodeVer.toUtf8());
    QDir dir;
    if(!dir.exists(getSettingsDir(m_client->configuration().jidBare())))
        dir.mkpath(getSettingsDir(m_client->configuration().jidBare()));

    QDir dir2;
    if(!dir2.exists(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/"))
        dir2.mkpath(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/");

    QString fileCapability = getSettingsDir(m_client->configuration().jidBare()) + "capabilities/" + fileName + ".xml";
    QFile file(fileCapability);

    if(file.open(QIODevice::ReadWrite))
    {
        QXmlStreamWriter stream(&file);
        stream.setAutoFormatting(true);
        stream.setAutoFormattingIndent(2);
        m_mapCapabilities[nodeVer].toXml(&stream);
        file.close();
    }
}

QStringList capabilitiesCache::getFeatures(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return QStringList();

    return m_mapCapabilities[nodeVer].features();
}

QStringList capabilitiesCache::getIdentities(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return QStringList();

    QStringList idList;
    QList<QXmppDiscoveryIq::Identity> list = m_mapCapabilities[nodeVer].identities();
    foreach(QXmppDiscoveryIq::Identity identity, list)
    {
        QStringList tmpList;
        if(!identity.name().isEmpty())
            tmpList << identity.name();
        if(!identity.category().isEmpty())
            tmpList << identity.category();
        if(!identity.type().isEmpty())
            tmpList << identity.type();
        if(!identity.language().isEmpty())
            tmpList << identity.language();
        idList << tmpList.join(" | ");
    }
    return idList;
}

<commit_msg>fix include of utils.h<commit_after>/*
 * Copyright (C) 2008-2014 The QXmpp developers
 *
 * Author:
 *	Manjeet Dahiya
 *
 * Source:
 *	https://github.com/qxmpp-project/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "capabilitiesCache.h"
#include "utils.h"

#include "QXmppClient.h"
#include "QXmppDiscoveryManager.h"

#include <QCoreApplication>
#include <QXmlStreamWriter>
#include <QDir>

capabilitiesCache::capabilitiesCache(QXmppClient* client) :
    QObject(client), m_client(client)
{
    QXmppDiscoveryManager* ext = m_client->findExtension<QXmppDiscoveryManager>();
    if(ext)
    {
        bool check = connect(ext, SIGNAL(infoReceived(QXmppDiscoveryIq)),
                             SLOT(infoReceived(QXmppDiscoveryIq)));
        Q_ASSERT(check);
        Q_UNUSED(check);
    }
}

bool capabilitiesCache::isCapabilityAvailable(const QString& nodeVer)
{
    return m_mapCapabilities.contains(nodeVer);
}

void capabilitiesCache::requestInfo(const QString& jid, const QString& node)
{
    QXmppDiscoveryManager* ext = m_client->findExtension<QXmppDiscoveryManager>();
    if(ext)
    {
        bool alreadyRequested = false;
        foreach(QString key, m_mapIdNodeVer.keys())
        {
            if(m_mapIdNodeVer[key] == node)
            {
                alreadyRequested = true;
                break;
            }
        }

        if(!alreadyRequested)
        {
            QString id = ext->requestInfo(jid, node);
            m_mapIdNodeVer[id] = node;
        }
    }
}

void capabilitiesCache::infoReceived(const QXmppDiscoveryIq& discoIqRcv)
{
    QXmppDiscoveryIq discoIq = discoIqRcv;
    if(discoIq.queryType() == QXmppDiscoveryIq::InfoQuery &&
       discoIq.type() == QXmppIq::Result)
    {
        if(discoIq.queryNode().isEmpty())
        {
            discoIq.setQueryNode(m_mapIdNodeVer[discoIq.id()]);
            m_mapIdNodeVer.remove(discoIq.id());
        }

        discoIq.setTo("");
        discoIq.setFrom("");
        discoIq.setId("");
        m_mapCapabilities[discoIq.queryNode()] = discoIq;
        saveToFile(discoIq.queryNode());
    }
}

void capabilitiesCache::loadFromFile()
{
    m_mapCapabilities.clear();

    QDir dirCaps(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/");
    if(dirCaps.exists())
    {
        QStringList list = dirCaps.entryList(QStringList("*.xml"));
        foreach(QString fileName, list)
        {
            QFile file(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/" + fileName);
            if(file.open(QIODevice::ReadOnly))
            {
                QDomDocument doc;
                if(doc.setContent(&file, true))
                {
                    QXmppDiscoveryIq discoIq;
                    discoIq.parse(doc.documentElement());
                    m_mapCapabilities[discoIq.queryNode()] = discoIq;
                    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
                }
            }
        }
    }
}

void capabilitiesCache::saveToFile(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return;

    QString fileName = getSha1HashAsHex(nodeVer.toUtf8());
    QDir dir;
    if(!dir.exists(getSettingsDir(m_client->configuration().jidBare())))
        dir.mkpath(getSettingsDir(m_client->configuration().jidBare()));

    QDir dir2;
    if(!dir2.exists(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/"))
        dir2.mkpath(getSettingsDir(m_client->configuration().jidBare())+ "capabilities/");

    QString fileCapability = getSettingsDir(m_client->configuration().jidBare()) + "capabilities/" + fileName + ".xml";
    QFile file(fileCapability);

    if(file.open(QIODevice::ReadWrite))
    {
        QXmlStreamWriter stream(&file);
        stream.setAutoFormatting(true);
        stream.setAutoFormattingIndent(2);
        m_mapCapabilities[nodeVer].toXml(&stream);
        file.close();
    }
}

QStringList capabilitiesCache::getFeatures(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return QStringList();

    return m_mapCapabilities[nodeVer].features();
}

QStringList capabilitiesCache::getIdentities(const QString& nodeVer)
{
    if(!m_mapCapabilities.contains(nodeVer))
        return QStringList();

    QStringList idList;
    QList<QXmppDiscoveryIq::Identity> list = m_mapCapabilities[nodeVer].identities();
    foreach(QXmppDiscoveryIq::Identity identity, list)
    {
        QStringList tmpList;
        if(!identity.name().isEmpty())
            tmpList << identity.name();
        if(!identity.category().isEmpty())
            tmpList << identity.category();
        if(!identity.type().isEmpty())
            tmpList << identity.type();
        if(!identity.language().isEmpty())
            tmpList << identity.language();
        idList << tmpList.join(" | ");
    }
    return idList;
}

<|endoftext|>


<commit_before>/*  Sirikata
 *  main.cpp
 *
 *  Copyright (c) 2008, Daniel Reiter Horn
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sirikata/oh/Platform.hpp>
#include <sirikata/proxyobject/ModelsSystemFactory.hpp> // MCB:
#include <sirikata/core/util/RoutableMessageHeader.hpp>
#include <sirikata/core/options/Options.hpp>
#include <sirikata/core/util/PluginManager.hpp>
#include <sirikata/proxyobject/SimulationFactory.hpp>

#include <sirikata/core/task/EventManager.hpp>
#include <sirikata/core/task/WorkQueue.hpp>
#include <sirikata/core/options/CDNConfig.hpp>

#include <sirikata/oh/ObjectHost.hpp>
#include <sirikata/proxyobject/LightInfo.hpp>
#include <sirikata/oh/ObjectHostProxyManager.hpp>
#include <sirikata/core/transfer/TransferManager.hpp>
#include <sirikata/oh/SpaceConnection.hpp>
#include <sirikata/oh/HostedObject.hpp>
#include <sirikata/oh/SpaceIDMap.hpp>
#include <sirikata/oh/ObjectHostTimeOffsetManager.hpp>
#include <sirikata/core/network/IOServiceFactory.hpp>
#include <sirikata/core/network/IOService.hpp>
#include <sirikata/core/util/KnownServices.hpp>
#include <sirikata/core/persistence/ObjectStorage.hpp>
#include <sirikata/core/persistence/ReadWriteHandlerFactory.hpp>
#include <Protocol_Persistence.pbj.hpp>
#include <Protocol_Sirikata.pbj.hpp>
#include <time.h>
#include <boost/thread.hpp>

#include <sirikata/core/options/Options.hpp>
#include <sirikata/core/options/CommonOptions.hpp>
#include "Options.hpp"
#include <sirikata/oh/Trace.hpp>

#include <sirikata/core/network/ServerIDMap.hpp>
#include <sirikata/core/network/NTPTimeSync.hpp>

#include <sirikata/core/network/SSTImpl.hpp>

#include <sirikata/oh/ObjectHostContext.hpp>

#ifdef __GNUC__
#include <fenv.h>
#endif

int main (int argc, char** argv) {
    using namespace Sirikata;

    InitOptions();
    Trace::Trace::InitOptions();
    OHTrace::InitOptions();
    InitCPPOHOptions();

    ParseOptions(argc, argv);

    PluginManager plugins;
    plugins.loadList( GetOptionValue<String>(OPT_PLUGINS) );
    plugins.loadList( GetOptionValue<String>(OPT_OH_PLUGINS) );

    String time_server = GetOptionValue<String>("time-server");
    NTPTimeSync sync;
    if (time_server.size() > 0)
        sync.start(time_server);

#ifdef __GNUC__
#ifndef __APPLE__
    if (GetOptionValue<bool>(OPT_SIGFPE)) {
        feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
    }
#endif
#endif

    OptionMapPtr transferOptions (new OptionMap);
    {
        std::string contents( GetOptionValue<String>(OPT_CDN_CONFIG) );
        std::string::size_type pos(0);
        parseConfig(contents, transferOptions, transferOptions, pos);
        std::cout << *transferOptions;
    }

    // FIXME: Initializes protocol handlers (http, rest, file, x-shasumofuri,
    // x-hashed) in the Transfer system.  This seems like it should be handled
    // automatically with plugins.
    initializeProtocols();

    ObjectHostID oh_id = GetOptionValue<ObjectHostID>("ohid");
    String trace_file = GetPerServerFile(STATS_OH_TRACE_FILE, oh_id);
    Trace::Trace* trace = new Trace::Trace(trace_file);

    String servermap_type = GetOptionValue<String>("servermap");
    String servermap_options = GetOptionValue<String>("servermap-options");
    ServerIDMap * server_id_map =
        ServerIDMapFactory::getSingleton().getConstructor(servermap_type)(servermap_options);

    srand( GetOptionValue<uint32>("rand-seed") );

    Network::IOService* ios = Network::IOServiceFactory::makeIOService();
    Network::IOStrand* mainStrand = ios->createStrand();

    Time start_time = Timer::now(); // Just for stats in ObjectHostContext.
    Duration duration = Duration::zero(); // Indicates to run forever.
    ObjectHostContext* ctx = new ObjectHostContext(oh_id, ios, mainStrand, trace, start_time, duration);

    SSTConnectionManager* sstConnMgr = new SSTConnectionManager(ctx);

    Task::WorkQueue *workQueue = new Task::LockFreeWorkQueue;
    Task::GenEventManager *eventManager = new Task::GenEventManager(workQueue);
    SpaceIDMap *spaceMap = new SpaceIDMap;
    SpaceID mainSpace(GetOptionValue<UUID>(OPT_MAIN_SPACE));
    typedef std::map<std::string,std::string> SimpleSpaceIDMap;
    SimpleSpaceIDMap spaceIdMap(GetOptionValue<SimpleSpaceIDMap>(OPT_SPACEID_MAP));
    for (SimpleSpaceIDMap::iterator i = spaceIdMap.begin(),
             ie=spaceIdMap.end();
         i!=ie;
         ++i) {
        SpaceID newSpace(UUID(i->first,UUID::HumanReadable()));
        spaceMap->insert(newSpace, Network::Address::lexical_cast(i->second).as<Network::Address>());
    }
    String localDbFile = GetOptionValue<String>(OPT_DB);
    if (localDbFile.length()&&localDbFile[0]!='/'&&localDbFile[0]!='\\') {
        FILE * fp=fopen(localDbFile.c_str(),"rb");
        for (int i=0;i<4&&fp==NULL;++i) {
            localDbFile="../"+localDbFile;
            fp=fopen(localDbFile.c_str(),"rb");
        }
        if (fp) fclose(fp);
        else localDbFile = GetOptionValue<String>(OPT_DB);
    }
    Persistence::ReadWriteHandler *database=Persistence::ReadWriteHandlerFactory::getSingleton()
        .getConstructor("sqlite")(String("--databasefile ")+localDbFile);

    ObjectHost *oh = new ObjectHost(ctx, spaceMap, workQueue, ios, "");
    oh->registerService(Services::PERSISTENCE, database);

    // Add all the spaces to the ObjectHost.
    // FIXME we're adding all spaces and having them use the same ServerIDMap
    // because its difficult to encode this in the options.
    // FIXME once this is working, the above SpaceIDMap (spaceMap) shouldn't be
    // used the same way -- it was only mapping to a single address instead of
    // an entire ServerIDMap.
    for (SimpleSpaceIDMap::iterator i = spaceIdMap.begin(),
             ie=spaceIdMap.end();
         i!=ie;
         ++i) {
        SpaceID newSpace(UUID(i->first,UUID::HumanReadable()));
        oh->addServerIDMap(newSpace, server_id_map);
    }

    Transfer::TransferManager *tm;
    try {
        tm = initializeTransferManager((*transferOptions)["cdn"], eventManager);
    } catch (OptionDoesNotExist &err) {
        SILOG(input,fatal,"Fatal Error: Failed to load CDN config: " << err.what());
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
        return 1;
    }

    String graphicsCommandArguments;
    {
        std::ostringstream os;
        os << "--transfermanager=" << tm << " ";
        os << "--eventmanager=" << eventManager << " ";
        os << "--workqueue=" << workQueue << " ";
        graphicsCommandArguments = os.str();
    }

    // FIXME simple test example
    // This is the camera.  We need it early on because other things depend on
    // having its ObjectHostProxyManager.
    HostedObjectPtr obj = HostedObject::construct<HostedObject>(ctx, oh, UUID::random(), true);
    obj->init();
    // Note: We currently just use the proxy manager for the default space. Not
    // sure if we should do something about handling multiple spaces.
    ProxyManagerPtr proxy_manager = obj->getProxyManager( mainSpace );

    // MCB: seems like a good place to initialize models system
    ModelsSystem* mm ( ModelsSystemFactory::getSingleton ().getConstructor ( "colladamodels" ) ( proxy_manager.get(), graphicsCommandArguments ) );

    if ( mm )
    {
        SILOG(cppoh,info,"Created ModelsSystemFactory ");
    }
    else
    {
        SILOG(cppoh,error,"Failed to create ModelsSystemFactory ");
    }

    bool continue_simulation = true;

    typedef std::vector<TimeSteppedSimulation*> SimList;
    SimList sims;

    struct SimulationRequest {
        const char* name;
        bool required;
    };
    const uint32 nSimRequests = 1;
    SimulationRequest simRequests[nSimRequests] = {
        {"ogregraphics", true}
    };
    for(uint32 ir = 0; ir < nSimRequests && continue_simulation; ir++) {
        String simName = simRequests[ir].name;
        SILOG(cppoh,info,String("Initializing ") + simName);
        TimeSteppedSimulation *sim =
            SimulationFactory::getSingleton()
            .getConstructor ( simName ) ( ctx, proxy_manager.get(), proxy_manager->getTimeOffsetManager(), graphicsCommandArguments );
        if (!sim) {
            if (simRequests[ir].required) {
                SILOG(cppoh,error,String("Unable to load ") + simName + String(" plugin. The PATH environment variable is ignored, so make sure you have copied the DLLs from dependencies/ogre/bin/ into the current directory. Sorry about this!"));
                std::cout << "Press enter to continue" << std::endl;
                std::cerr << "Press enter to continue" << std::endl;
                fgetc(stdin);
                continue_simulation = false;
            }
            else {
                SILOG(cppoh,info,String("Couldn't load ") + simName + String(" plugin."));
            }
        }
        else {
            oh->addListener(sim);
            SILOG(cppoh,info,String("Successfully initialized ") + simName);
            sims.push_back(sim);
        }
    }

    // FIXME
    obj->connect(
        mainSpace,
        Location( Vector3d::nil(), Quaternion::identity(), Vector3f::nil(), Vector3f::nil(), 0),
        BoundingSphere3f(Vector3f::nil(), 1.f),
        "http://www.sirikata.com/content/assets/cube.dae",
        UUID::null());

    HostedObjectPtr obj2 = HostedObject::construct<HostedObject>(ctx, oh, UUID::random(), false);
    obj2->init();
    obj2->connect(
        mainSpace,
        Location( Vector3d::nil(), Quaternion::identity(), Vector3f::nil(), Vector3f::nil(), 0),
        BoundingSphere3f(Vector3f::nil(), 1.f),
        "http://www.sirikata.com/content/assets/cube.dae",
        UUID::null());

    ///////////Go go go!! start of simulation/////////////////////
    ctx->add(ctx);
    ctx->add(oh);
    ctx->add(sstConnMgr);
    for(SimList::iterator it = sims.begin(); it != sims.end(); it++)
        ctx->add(*it);
    ctx->run(1);

    obj2.reset();
    obj.reset();

    ctx->cleanup();
    trace->prepareShutdown();

    proxy_manager.reset();
    delete oh;

    // delete after OH in case objects want to do last-minute state flushes
    delete database;

    destroyTransferManager(tm);
    delete eventManager;
    delete workQueue;

    for(SimList::reverse_iterator it = sims.rbegin(); it != sims.rend(); it++) {
        delete *it;
    }
    sims.clear();
    plugins.gc();
    SimulationFactory::destroy();

    delete spaceMap;

    delete ctx;

    trace->shutdown();
    delete trace;
    trace = NULL;

    delete mainStrand;
    Network::IOServiceFactory::destroyIOService(ios);

    sync.stop();

    return 0;
}
<commit_msg>Don't initialize the camera with a mesh.<commit_after>/*  Sirikata
 *  main.cpp
 *
 *  Copyright (c) 2008, Daniel Reiter Horn
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sirikata/oh/Platform.hpp>
#include <sirikata/proxyobject/ModelsSystemFactory.hpp> // MCB:
#include <sirikata/core/util/RoutableMessageHeader.hpp>
#include <sirikata/core/options/Options.hpp>
#include <sirikata/core/util/PluginManager.hpp>
#include <sirikata/proxyobject/SimulationFactory.hpp>

#include <sirikata/core/task/EventManager.hpp>
#include <sirikata/core/task/WorkQueue.hpp>
#include <sirikata/core/options/CDNConfig.hpp>

#include <sirikata/oh/ObjectHost.hpp>
#include <sirikata/proxyobject/LightInfo.hpp>
#include <sirikata/oh/ObjectHostProxyManager.hpp>
#include <sirikata/core/transfer/TransferManager.hpp>
#include <sirikata/oh/SpaceConnection.hpp>
#include <sirikata/oh/HostedObject.hpp>
#include <sirikata/oh/SpaceIDMap.hpp>
#include <sirikata/oh/ObjectHostTimeOffsetManager.hpp>
#include <sirikata/core/network/IOServiceFactory.hpp>
#include <sirikata/core/network/IOService.hpp>
#include <sirikata/core/util/KnownServices.hpp>
#include <sirikata/core/persistence/ObjectStorage.hpp>
#include <sirikata/core/persistence/ReadWriteHandlerFactory.hpp>
#include <Protocol_Persistence.pbj.hpp>
#include <Protocol_Sirikata.pbj.hpp>
#include <time.h>
#include <boost/thread.hpp>

#include <sirikata/core/options/Options.hpp>
#include <sirikata/core/options/CommonOptions.hpp>
#include "Options.hpp"
#include <sirikata/oh/Trace.hpp>

#include <sirikata/core/network/ServerIDMap.hpp>
#include <sirikata/core/network/NTPTimeSync.hpp>

#include <sirikata/core/network/SSTImpl.hpp>

#include <sirikata/oh/ObjectHostContext.hpp>

#ifdef __GNUC__
#include <fenv.h>
#endif

int main (int argc, char** argv) {
    using namespace Sirikata;

    InitOptions();
    Trace::Trace::InitOptions();
    OHTrace::InitOptions();
    InitCPPOHOptions();

    ParseOptions(argc, argv);

    PluginManager plugins;
    plugins.loadList( GetOptionValue<String>(OPT_PLUGINS) );
    plugins.loadList( GetOptionValue<String>(OPT_OH_PLUGINS) );

    String time_server = GetOptionValue<String>("time-server");
    NTPTimeSync sync;
    if (time_server.size() > 0)
        sync.start(time_server);

#ifdef __GNUC__
#ifndef __APPLE__
    if (GetOptionValue<bool>(OPT_SIGFPE)) {
        feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
    }
#endif
#endif

    OptionMapPtr transferOptions (new OptionMap);
    {
        std::string contents( GetOptionValue<String>(OPT_CDN_CONFIG) );
        std::string::size_type pos(0);
        parseConfig(contents, transferOptions, transferOptions, pos);
        std::cout << *transferOptions;
    }

    // FIXME: Initializes protocol handlers (http, rest, file, x-shasumofuri,
    // x-hashed) in the Transfer system.  This seems like it should be handled
    // automatically with plugins.
    initializeProtocols();

    ObjectHostID oh_id = GetOptionValue<ObjectHostID>("ohid");
    String trace_file = GetPerServerFile(STATS_OH_TRACE_FILE, oh_id);
    Trace::Trace* trace = new Trace::Trace(trace_file);

    String servermap_type = GetOptionValue<String>("servermap");
    String servermap_options = GetOptionValue<String>("servermap-options");
    ServerIDMap * server_id_map =
        ServerIDMapFactory::getSingleton().getConstructor(servermap_type)(servermap_options);

    srand( GetOptionValue<uint32>("rand-seed") );

    Network::IOService* ios = Network::IOServiceFactory::makeIOService();
    Network::IOStrand* mainStrand = ios->createStrand();

    Time start_time = Timer::now(); // Just for stats in ObjectHostContext.
    Duration duration = Duration::zero(); // Indicates to run forever.
    ObjectHostContext* ctx = new ObjectHostContext(oh_id, ios, mainStrand, trace, start_time, duration);

    SSTConnectionManager* sstConnMgr = new SSTConnectionManager(ctx);

    Task::WorkQueue *workQueue = new Task::LockFreeWorkQueue;
    Task::GenEventManager *eventManager = new Task::GenEventManager(workQueue);
    SpaceIDMap *spaceMap = new SpaceIDMap;
    SpaceID mainSpace(GetOptionValue<UUID>(OPT_MAIN_SPACE));
    typedef std::map<std::string,std::string> SimpleSpaceIDMap;
    SimpleSpaceIDMap spaceIdMap(GetOptionValue<SimpleSpaceIDMap>(OPT_SPACEID_MAP));
    for (SimpleSpaceIDMap::iterator i = spaceIdMap.begin(),
             ie=spaceIdMap.end();
         i!=ie;
         ++i) {
        SpaceID newSpace(UUID(i->first,UUID::HumanReadable()));
        spaceMap->insert(newSpace, Network::Address::lexical_cast(i->second).as<Network::Address>());
    }
    String localDbFile = GetOptionValue<String>(OPT_DB);
    if (localDbFile.length()&&localDbFile[0]!='/'&&localDbFile[0]!='\\') {
        FILE * fp=fopen(localDbFile.c_str(),"rb");
        for (int i=0;i<4&&fp==NULL;++i) {
            localDbFile="../"+localDbFile;
            fp=fopen(localDbFile.c_str(),"rb");
        }
        if (fp) fclose(fp);
        else localDbFile = GetOptionValue<String>(OPT_DB);
    }
    Persistence::ReadWriteHandler *database=Persistence::ReadWriteHandlerFactory::getSingleton()
        .getConstructor("sqlite")(String("--databasefile ")+localDbFile);

    ObjectHost *oh = new ObjectHost(ctx, spaceMap, workQueue, ios, "");
    oh->registerService(Services::PERSISTENCE, database);

    // Add all the spaces to the ObjectHost.
    // FIXME we're adding all spaces and having them use the same ServerIDMap
    // because its difficult to encode this in the options.
    // FIXME once this is working, the above SpaceIDMap (spaceMap) shouldn't be
    // used the same way -- it was only mapping to a single address instead of
    // an entire ServerIDMap.
    for (SimpleSpaceIDMap::iterator i = spaceIdMap.begin(),
             ie=spaceIdMap.end();
         i!=ie;
         ++i) {
        SpaceID newSpace(UUID(i->first,UUID::HumanReadable()));
        oh->addServerIDMap(newSpace, server_id_map);
    }

    Transfer::TransferManager *tm;
    try {
        tm = initializeTransferManager((*transferOptions)["cdn"], eventManager);
    } catch (OptionDoesNotExist &err) {
        SILOG(input,fatal,"Fatal Error: Failed to load CDN config: " << err.what());
        std::cout << "Press enter to continue" << std::endl;
        std::cerr << "Press enter to continue" << std::endl;
        fgetc(stdin);
        return 1;
    }

    String graphicsCommandArguments;
    {
        std::ostringstream os;
        os << "--transfermanager=" << tm << " ";
        os << "--eventmanager=" << eventManager << " ";
        os << "--workqueue=" << workQueue << " ";
        graphicsCommandArguments = os.str();
    }

    // FIXME simple test example
    // This is the camera.  We need it early on because other things depend on
    // having its ObjectHostProxyManager.
    HostedObjectPtr obj = HostedObject::construct<HostedObject>(ctx, oh, UUID::random(), true);
    obj->init();
    // Note: We currently just use the proxy manager for the default space. Not
    // sure if we should do something about handling multiple spaces.
    ProxyManagerPtr proxy_manager = obj->getProxyManager( mainSpace );

    // MCB: seems like a good place to initialize models system
    ModelsSystem* mm ( ModelsSystemFactory::getSingleton ().getConstructor ( "colladamodels" ) ( proxy_manager.get(), graphicsCommandArguments ) );

    if ( mm )
    {
        SILOG(cppoh,info,"Created ModelsSystemFactory ");
    }
    else
    {
        SILOG(cppoh,error,"Failed to create ModelsSystemFactory ");
    }

    bool continue_simulation = true;

    typedef std::vector<TimeSteppedSimulation*> SimList;
    SimList sims;

    struct SimulationRequest {
        const char* name;
        bool required;
    };
    const uint32 nSimRequests = 1;
    SimulationRequest simRequests[nSimRequests] = {
        {"ogregraphics", true}
    };
    for(uint32 ir = 0; ir < nSimRequests && continue_simulation; ir++) {
        String simName = simRequests[ir].name;
        SILOG(cppoh,info,String("Initializing ") + simName);
        TimeSteppedSimulation *sim =
            SimulationFactory::getSingleton()
            .getConstructor ( simName ) ( ctx, proxy_manager.get(), proxy_manager->getTimeOffsetManager(), graphicsCommandArguments );
        if (!sim) {
            if (simRequests[ir].required) {
                SILOG(cppoh,error,String("Unable to load ") + simName + String(" plugin. The PATH environment variable is ignored, so make sure you have copied the DLLs from dependencies/ogre/bin/ into the current directory. Sorry about this!"));
                std::cout << "Press enter to continue" << std::endl;
                std::cerr << "Press enter to continue" << std::endl;
                fgetc(stdin);
                continue_simulation = false;
            }
            else {
                SILOG(cppoh,info,String("Couldn't load ") + simName + String(" plugin."));
            }
        }
        else {
            oh->addListener(sim);
            SILOG(cppoh,info,String("Successfully initialized ") + simName);
            sims.push_back(sim);
        }
    }

    // FIXME
    obj->connect(
        mainSpace,
        Location( Vector3d::nil(), Quaternion::identity(), Vector3f::nil(), Vector3f::nil(), 0),
        BoundingSphere3f(Vector3f::nil(), 1.f),
        "",
        UUID::null());

    HostedObjectPtr obj2 = HostedObject::construct<HostedObject>(ctx, oh, UUID::random(), false);
    obj2->init();
    obj2->connect(
        mainSpace,
        Location( Vector3d::nil(), Quaternion::identity(), Vector3f::nil(), Vector3f::nil(), 0),
        BoundingSphere3f(Vector3f::nil(), 1.f),
        "http://www.sirikata.com/content/assets/cube.dae",
        UUID::null());

    ///////////Go go go!! start of simulation/////////////////////
    ctx->add(ctx);
    ctx->add(oh);
    ctx->add(sstConnMgr);
    for(SimList::iterator it = sims.begin(); it != sims.end(); it++)
        ctx->add(*it);
    ctx->run(1);

    obj2.reset();
    obj.reset();

    ctx->cleanup();
    trace->prepareShutdown();

    proxy_manager.reset();
    delete oh;

    // delete after OH in case objects want to do last-minute state flushes
    delete database;

    destroyTransferManager(tm);
    delete eventManager;
    delete workQueue;

    for(SimList::reverse_iterator it = sims.rbegin(); it != sims.rend(); it++) {
        delete *it;
    }
    sims.clear();
    plugins.gc();
    SimulationFactory::destroy();

    delete spaceMap;

    delete ctx;

    trace->shutdown();
    delete trace;
    trace = NULL;

    delete mainStrand;
    Network::IOServiceFactory::destroyIOService(ios);

    sync.stop();

    return 0;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <vector>
#include <thread>

void first() {
  std::cout << "Thread 1" << std::endl;
}

void second() {
  std::cout << "Thread 2" << std::endl;
}

int main() {
  std::thread t1(first);
  std::thread t2(second);

  t1.join();
  t2.join();
  return 0;
}
<commit_msg>Passing data to thread by-reference<commit_after>#include <string>
#include <iostream>
#include <vector>
#include <thread>

void first(std::vector<std::string>& values) {
  values.reserve(100);
  for (int i = 0; i < 100; ++i) {
    values.emplace_back(std::to_string(i));
  }
  std::cout << "Thread 1" << std::endl;
}

void second() {
  std::cout << "Thread 2" << std::endl;
}

int main() {
  std::vector<std::string> values;

  std::thread t1(first, std::ref(values));
  std::thread t2(second);

  t1.join();
  t2.join();

  for (auto& value : values) {
    std::cout << value << std::endl;
  }

  return 0;
}
<|endoftext|>