<commit_before>// @(#)root/tree:$Id$
// Author: Marek Biskup   07/06/2005

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

//////////////////////////////////////////////////////////////////////////
//
// A Chain Index
//
//////////////////////////////////////////////////////////////////////////

#include "TChainIndex.h"
#include "TChain.h"
#include "TTreeFormula.h"
#include "TTreeIndex.h"
#include "TFile.h"
#include "TError.h"

ClassImp(TChainIndex)

//______________________________________________________________________________
TChainIndex::TChainIndex(): TVirtualIndex()
{
// Default constructor for TChainIndex

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;
}

//______________________________________________________________________________
TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
           : TVirtualIndex()
{
   // Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
   // parameters.
   // The tree must be a TChain.
   // All the index values in the first tree of the chain must be
   // less then any index value in the second one, and so on.
   // If any of those requirements isn't met the object becomes a zombie.
   // If some subtrees don't have indices the indices are created and stored inside this
   // TChainIndex.

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;

   TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
   if (!chain) {
      MakeZombie();
      Error("TChainIndex", "Cannot create a TChainIndex."
            " The Tree passed as an argument is not a TChain");
      return;
   }

   fTree               = (TTree*)T;
   fMajorName          = majorname;
   fMinorName          = minorname;
   Int_t i = 0;

   // Go through all the trees and check if they have indeces. If not then build them.
   for (i = 0; i < chain->GetNtrees(); i++) {
      chain->LoadTree((chain->GetTreeOffset())[i]);
      TVirtualIndex *index = chain->GetTree()->GetTreeIndex();

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;

      //if an index already exists, we must check if major/minorname correspond
      //to the major/minor names in this function call
      if (index) {
         if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
            MakeZombie();
            Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
            return;
         }
      }
      if (!index) {
         chain->GetTree()->BuildIndex(majorname, minorname);
         index = chain->GetTree()->GetTreeIndex();
         chain->GetTree()->SetTreeIndex(0);
         entry.fTreeIndex = index;
      }
      if (!index || index->IsZombie() || index->GetN() == 0) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "Error creating a tree index on a tree in the chain");
         return;
      }

      TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
               index->IsA()->GetName());
         return;
      }

      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   // Check if the indices of different trees are in order. If not then return an error.
   for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
      if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "The indices in files of this chain aren't sorted.");
      }
   }

}

//______________________________________________________________________________
void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
{
   // add an index to this chain
   // if delaySort is kFALSE (default) check if the indices of different trees are in order.
   if (index) {
      const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("Append", "The given index is not a TTreeIndex but a %s",
               index->IsA()->GetName());
      }

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;
      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   if (!delaySort) {
      // Check if the indices of different trees are in order. If not then return an error.
      for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
         if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
            DeleteIndices();
            MakeZombie();
            Error("Append", "The indices in files of this chain aren't sorted.");
         }
      }
   }
}

//______________________________________________________________________________
void TChainIndex::DeleteIndices()
{
   // Delete all the indices which were built by this object
   for (unsigned int i = 0; i < fEntries.size(); i++) {
      if (fEntries[i].fTreeIndex) {
         if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
            fTree->GetTree()->SetTreeIndex(0);
            SafeDelete(fEntries[i].fTreeIndex);
         }
         SafeDelete(fEntries[i].fTreeIndex);
      }
   }
}

//______________________________________________________________________________
TChainIndex::~TChainIndex()
{
   // The destructor.
   DeleteIndices();
   if (fTree && fTree->GetTreeIndex() == this)
      fTree->SetTreeIndex(0);
}

//______________________________________________________________________________
std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
{
   // Returns a TVirtualIndex for a tree which holds the entry with the specified
   // major and minor values and the number of that tree.
   // If the index for that tree was created by this object it's set to the tree.
   // The tree index should be later released using ReleaseSubTreeIndex();

   using namespace std;
   if (fEntries.size() == 0) {
      Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Long64_t indexValue = (Long64_t(major) << 31) + minor;

   if (indexValue < fEntries[0].fMinIndexValue) {
      Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Int_t treeNo = fEntries.size() - 1;
   for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
      if (indexValue < fEntries[i+1].fMinIndexValue) {
         treeNo = i;
         break;
      }
   }
   // Double check we found the right range.
   if (indexValue > fEntries[treeNo].fMaxIndexValue) {
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }
   TChain* chain = dynamic_cast<TChain*> (fTree);
   R__ASSERT(chain);
   chain->LoadTree(chain->GetTreeOffset()[treeNo]);
   TVirtualIndex* index =  fTree->GetTree()->GetTreeIndex();
   if (index)
      return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
   else {
      index = fEntries[treeNo].fTreeIndex;
      if (!index) {
         Warning("GetSubTreeIndex", "The tree has no index and the chain index"
                  " doesn't store an index for that tree");
         return make_pair(static_cast<TVirtualIndex*>(0), 0);
      }
      else {
         fTree->GetTree()->SetTreeIndex(index);
         return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
      }
   }
}

//______________________________________________________________________________
void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
{
   // Releases the tree index got using GetSubTreeIndex. If the index was
   // created by this object it is removed from the current tree, so that it isn't
   // deleted in its destructor.

   if (fEntries[treeNo].fTreeIndex == index) {
      R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
      fTree->GetTree()->SetTreeIndex(0);
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberFriend(const TTree *parent)
{
   // see TTreeIndex::GetEntryNumberFriend for description

   if (!parent) return -3;
   GetMajorFormulaParent(parent);
   GetMinorFormulaParent(parent);
   if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
   if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
      // The Tree Index in the friend has a pair majorname,minorname
      // not available in the parent Tree T.
      // if the friend Tree has less entries than the parent, this is an error
      Long64_t pentry = parent->GetReadEntry();
      if (pentry >= fTree->GetEntries()) return -2;
      // otherwise we ignore the Tree Index and return the entry number
      // in the parent Tree.
      return pentry;
   }

   // majorname, minorname exist in the parent Tree
   // we find the current values pair majorv,minorv in the parent Tree
   Double_t majord = fMajorFormulaParent->EvalInstance();
   Double_t minord = fMinorFormulaParent->EvalInstance();
   Long64_t majorv = (Long64_t)majord;
   Long64_t minorv = (Long64_t)minord;
   // we check if this pair exist in the index.
   // if yes, we return the corresponding entry number
   // if not the function returns -1
   return fTree->GetEntryNumberWithIndex(majorv,minorv);
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
{
   // See TTreeIndex::GetEntryNumberWithBestIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      // Error("GetEntryNumberWithBestIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      return rv + chain->GetTreeOffset()[indexAndNumber.second];
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
{
   // Returns the entry number with given index values.
   // See TTreeIndex::GetEntryNumberWithIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      // Error("GetEntryNumberWithIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      if (rv > 0) {
         return rv + chain->GetTreeOffset()[indexAndNumber.second];
      } else {
         return rv;
      }
   }
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the majorname in parent tree T

   if (!fMajorFormulaParent) {
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),const_cast<TTree*>(parent));
      fMajorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMajorFormulaParent->GetTree() != parent) {
      fMajorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   return fMajorFormulaParent;
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the minorname in parent tree T

   if (!fMinorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
      fMinorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMinorFormulaParent->GetTree() != parent) {
      fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMinorFormulaParent->UpdateFormulaLeaves();
   }

   return fMinorFormulaParent;
}

//______________________________________________________________________________
void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
{
   // Updates the parent formulae.
   // Called by TChain::LoadTree when the parent chain changes it's tree.
   if (fMajorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   if (fMinorFormulaParent) {
      if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
      fMinorFormulaParent->UpdateFormulaLeaves();
   }
}

//______________________________________________________________________________
void TChainIndex::SetTree(const TTree *T)
{
   // See TTreeIndex::SetTree.

   R__ASSERT(fTree == 0 || fTree == T || T==0);
}

<commit_msg>Import revision 44719 from the trunk: Fix off by one error introduced in revision 43390 ; this fixes <http://savannah.cern.ch/bugs/?94910> (TChained Tree index returns wrong entry on GetEntryNumberWithIndex)<commit_after>// @(#)root/tree:$Id$
// Author: Marek Biskup   07/06/2005

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

//////////////////////////////////////////////////////////////////////////
//
// A Chain Index
//
//////////////////////////////////////////////////////////////////////////

#include "TChainIndex.h"
#include "TChain.h"
#include "TTreeFormula.h"
#include "TTreeIndex.h"
#include "TFile.h"
#include "TError.h"

ClassImp(TChainIndex)

//______________________________________________________________________________
TChainIndex::TChainIndex(): TVirtualIndex()
{
// Default constructor for TChainIndex

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;
}

//______________________________________________________________________________
TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
           : TVirtualIndex()
{
   // Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
   // parameters.
   // The tree must be a TChain.
   // All the index values in the first tree of the chain must be
   // less then any index value in the second one, and so on.
   // If any of those requirements isn't met the object becomes a zombie.
   // If some subtrees don't have indices the indices are created and stored inside this
   // TChainIndex.

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;

   TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
   if (!chain) {
      MakeZombie();
      Error("TChainIndex", "Cannot create a TChainIndex."
            " The Tree passed as an argument is not a TChain");
      return;
   }

   fTree               = (TTree*)T;
   fMajorName          = majorname;
   fMinorName          = minorname;
   Int_t i = 0;

   // Go through all the trees and check if they have indeces. If not then build them.
   for (i = 0; i < chain->GetNtrees(); i++) {
      chain->LoadTree((chain->GetTreeOffset())[i]);
      TVirtualIndex *index = chain->GetTree()->GetTreeIndex();

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;

      //if an index already exists, we must check if major/minorname correspond
      //to the major/minor names in this function call
      if (index) {
         if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
            MakeZombie();
            Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
            return;
         }
      }
      if (!index) {
         chain->GetTree()->BuildIndex(majorname, minorname);
         index = chain->GetTree()->GetTreeIndex();
         chain->GetTree()->SetTreeIndex(0);
         entry.fTreeIndex = index;
      }
      if (!index || index->IsZombie() || index->GetN() == 0) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "Error creating a tree index on a tree in the chain");
         return;
      }

      TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
               index->IsA()->GetName());
         return;
      }

      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   // Check if the indices of different trees are in order. If not then return an error.
   for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
      if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "The indices in files of this chain aren't sorted.");
      }
   }

}

//______________________________________________________________________________
void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
{
   // add an index to this chain
   // if delaySort is kFALSE (default) check if the indices of different trees are in order.
   if (index) {
      const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("Append", "The given index is not a TTreeIndex but a %s",
               index->IsA()->GetName());
      }

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;
      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   if (!delaySort) {
      // Check if the indices of different trees are in order. If not then return an error.
      for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
         if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
            DeleteIndices();
            MakeZombie();
            Error("Append", "The indices in files of this chain aren't sorted.");
         }
      }
   }
}

//______________________________________________________________________________
void TChainIndex::DeleteIndices()
{
   // Delete all the indices which were built by this object
   for (unsigned int i = 0; i < fEntries.size(); i++) {
      if (fEntries[i].fTreeIndex) {
         if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
            fTree->GetTree()->SetTreeIndex(0);
            SafeDelete(fEntries[i].fTreeIndex);
         }
         SafeDelete(fEntries[i].fTreeIndex);
      }
   }
}

//______________________________________________________________________________
TChainIndex::~TChainIndex()
{
   // The destructor.
   DeleteIndices();
   if (fTree && fTree->GetTreeIndex() == this)
      fTree->SetTreeIndex(0);
}

//______________________________________________________________________________
std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
{
   // Returns a TVirtualIndex for a tree which holds the entry with the specified
   // major and minor values and the number of that tree.
   // If the index for that tree was created by this object it's set to the tree.
   // The tree index should be later released using ReleaseSubTreeIndex();

   using namespace std;
   if (fEntries.size() == 0) {
      Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Long64_t indexValue = (Long64_t(major) << 31) + minor;

   if (indexValue < fEntries[0].fMinIndexValue) {
      Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Int_t treeNo = fEntries.size() - 1;
   for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
      if (indexValue < fEntries[i+1].fMinIndexValue) {
         treeNo = i;
         break;
      }
   }
   // Double check we found the right range.
   if (indexValue > fEntries[treeNo].fMaxIndexValue) {
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }
   TChain* chain = dynamic_cast<TChain*> (fTree);
   R__ASSERT(chain);
   chain->LoadTree(chain->GetTreeOffset()[treeNo]);
   TVirtualIndex* index =  fTree->GetTree()->GetTreeIndex();
   if (index)
      return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
   else {
      index = fEntries[treeNo].fTreeIndex;
      if (!index) {
         Warning("GetSubTreeIndex", "The tree has no index and the chain index"
                  " doesn't store an index for that tree");
         return make_pair(static_cast<TVirtualIndex*>(0), 0);
      }
      else {
         fTree->GetTree()->SetTreeIndex(index);
         return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
      }
   }
}

//______________________________________________________________________________
void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
{
   // Releases the tree index got using GetSubTreeIndex. If the index was
   // created by this object it is removed from the current tree, so that it isn't
   // deleted in its destructor.

   if (fEntries[treeNo].fTreeIndex == index) {
      R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
      fTree->GetTree()->SetTreeIndex(0);
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberFriend(const TTree *parent)
{
   // see TTreeIndex::GetEntryNumberFriend for description

   if (!parent) return -3;
   GetMajorFormulaParent(parent);
   GetMinorFormulaParent(parent);
   if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
   if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
      // The Tree Index in the friend has a pair majorname,minorname
      // not available in the parent Tree T.
      // if the friend Tree has less entries than the parent, this is an error
      Long64_t pentry = parent->GetReadEntry();
      if (pentry >= fTree->GetEntries()) return -2;
      // otherwise we ignore the Tree Index and return the entry number
      // in the parent Tree.
      return pentry;
   }

   // majorname, minorname exist in the parent Tree
   // we find the current values pair majorv,minorv in the parent Tree
   Double_t majord = fMajorFormulaParent->EvalInstance();
   Double_t minord = fMinorFormulaParent->EvalInstance();
   Long64_t majorv = (Long64_t)majord;
   Long64_t minorv = (Long64_t)minord;
   // we check if this pair exist in the index.
   // if yes, we return the corresponding entry number
   // if not the function returns -1
   return fTree->GetEntryNumberWithIndex(majorv,minorv);
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
{
   // See TTreeIndex::GetEntryNumberWithBestIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      // Error("GetEntryNumberWithBestIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      return rv + chain->GetTreeOffset()[indexAndNumber.second];
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
{
   // Returns the entry number with given index values.
   // See TTreeIndex::GetEntryNumberWithIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      // Error("GetEntryNumberWithIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      if (rv >= 0) {
         return rv + chain->GetTreeOffset()[indexAndNumber.second];
      } else {
         return rv;
      }
   }
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the majorname in parent tree T

   if (!fMajorFormulaParent) {
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),const_cast<TTree*>(parent));
      fMajorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMajorFormulaParent->GetTree() != parent) {
      fMajorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   return fMajorFormulaParent;
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the minorname in parent tree T

   if (!fMinorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
      fMinorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMinorFormulaParent->GetTree() != parent) {
      fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMinorFormulaParent->UpdateFormulaLeaves();
   }

   return fMinorFormulaParent;
}

//______________________________________________________________________________
void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
{
   // Updates the parent formulae.
   // Called by TChain::LoadTree when the parent chain changes it's tree.
   if (fMajorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   if (fMinorFormulaParent) {
      if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
      fMinorFormulaParent->UpdateFormulaLeaves();
   }
}

//______________________________________________________________________________
void TChainIndex::SetTree(const TTree *T)
{
   // See TTreeIndex::SetTree.

   R__ASSERT(fTree == 0 || fTree == T || T==0);
}

<|endoftext|>


<commit_before>/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbMorphologicalOpeningProfileFilter.h"
#include "itkBinaryBallStructuringElement.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImage.h"

#include "itkMacro.h"

int otbMorphologicalOpeningProfileFilter(int argc, char * argv[])
{
  const char * inputFilename = argv[1];
  const char * outputFilenamePrefix = argv[2];
  const char * outputFilenameSuffix = argv[3];
  const unsigned int profileSize = atoi(argv[4]);
  const unsigned int initialValue = atoi(argv[5]);
  const unsigned int step = atoi(argv[5]);

  const unsigned int Dimension = 2;
  typedef double InputPixelType;
  typedef double OutputPixelType;

  typedef otb::Image<InputPixelType,Dimension> InputImageType;
  typedef otb::Image<OutputPixelType,Dimension> OutputImageType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::StreamingImageFileWriter<OutputImageType> WriterType;

  typedef itk::BinaryBallStructuringElement<InputPixelType,Dimension> StructuringElementType;
  typedef otb::MorphologicalOpeningProfileFilter<InputImageType,InputImageType,StructuringElementType>
    OpeningProfileFilterType;

  // Reading input image
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFilename);

  // Instantiation
  OpeningProfileFilterType::Pointer profileFilter = OpeningProfileFilterType::New();
  profileFilter->SetInput(reader->GetOutput());
  profileFilter->SetProfileSize(profileSize);
  profileFilter->SetInitialValue(initialValue);
  profileFilter->SetStep(step);
  profileFilter->Update();

  WriterType::Pointer writer;

  // std::stringstream oss;
  itk::OStringStream oss;
  // Writing the results images
  for(unsigned int i = 1;i<=profileSize;++i)
    {
      writer =  WriterType::New();
      oss<<outputFilenamePrefix<<i<<"."<<outputFilenameSuffix;
      writer->SetInput(profileFilter->GetOutput()->GetNthElement(i-1));
      writer->SetFileName(oss.str().c_str());
      writer->Update();
      oss.str("");
    }

  return EXIT_SUCCESS;
}
<commit_msg>Correction de l'argument 6<commit_after>/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbMorphologicalOpeningProfileFilter.h"
#include "itkBinaryBallStructuringElement.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImage.h"

#include "itkMacro.h"

int otbMorphologicalOpeningProfileFilter(int argc, char * argv[])
{
  const char * inputFilename = argv[1];
  const char * outputFilenamePrefix = argv[2];
  const char * outputFilenameSuffix = argv[3];
  const unsigned int profileSize = atoi(argv[4]);
  const unsigned int initialValue = atoi(argv[5]);
  const unsigned int step = atoi(argv[6]);

  const unsigned int Dimension = 2;
  typedef double InputPixelType;
  typedef double OutputPixelType;

  typedef otb::Image<InputPixelType,Dimension> InputImageType;
  typedef otb::Image<OutputPixelType,Dimension> OutputImageType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::StreamingImageFileWriter<OutputImageType> WriterType;

  typedef itk::BinaryBallStructuringElement<InputPixelType,Dimension> StructuringElementType;
  typedef otb::MorphologicalOpeningProfileFilter<InputImageType,InputImageType,StructuringElementType>
    OpeningProfileFilterType;

  // Reading input image
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFilename);

  // Instantiation
  OpeningProfileFilterType::Pointer profileFilter = OpeningProfileFilterType::New();
  profileFilter->SetInput(reader->GetOutput());
  profileFilter->SetProfileSize(profileSize);
  profileFilter->SetInitialValue(initialValue);
  profileFilter->SetStep(step);
  profileFilter->Update();

  WriterType::Pointer writer;

  // std::stringstream oss;
  itk::OStringStream oss;
  // Writing the results images
  for(unsigned int i = 1;i<=profileSize;++i)
    {
      writer =  WriterType::New();
      oss<<outputFilenamePrefix<<i<<"."<<outputFilenameSuffix;
      writer->SetInput(profileFilter->GetOutput()->GetNthElement(i-1));
      writer->SetFileName(oss.str().c_str());
      writer->Update();
      oss.str("");
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#ifndef __AIRINV_CMD_INVENTORYPARSERHELPER_HPP
#define __AIRINV_CMD_INVENTORYPARSERHELPER_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <string>
// StdAir
#include <stdair/command/CmdAbstract.hpp>
// Airinv
#include <airinv/AIRINV_Types.hpp>
#define BOOST_SPIRIT_DEBUG
#include <airinv/basic/BasParserTypes.hpp>
#include <airinv/bom/FlightDateStruct.hpp>

// Forward declarations
namespace stdair {
  class BomRoot;
}

namespace AIRINV {

  namespace InventoryParserHelper {

    // ///////////////////////////////////////////////////////////////////
    //  Semantic actions
    // ///////////////////////////////////////////////////////////////////
    /** Generic Semantic Action (Actor / Functor) for the Inventory Parser. */
    struct ParserSemanticAction {
      /** Actor Constructor. */
      ParserSemanticAction (FlightDateStruct_T&);
      /** Actor Context. */
      FlightDateStruct_T& _flightDate;
    };

    /** Store the snapshot date. */
    struct storeSnapshotDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSnapshotDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed airline code. */
    struct storeAirlineCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeAirlineCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed flight number. */
    struct storeFlightNumber : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightNumber (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the flight date. */
    struct storeFlightDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the flight type code. */
    struct storeFlightTypeCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightTypeCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg boarding point. */
    struct storeLegBoardingPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegBoardingPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg off point. */
    struct storeLegOffPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegOffPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the boarding date. */
    struct storeBoardingDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBoardingDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the boarding time. */
    struct storeBoardingTime : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBoardingTime (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the off date. */
    struct storeOffDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOffDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the off time. */
    struct storeOffTime : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOffTime (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg cabin code. */
    struct storeLegCabinCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegCabinCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed saleable capacity. */
    struct storeSaleableCapacity : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSaleableCapacity (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Authorisation Level (AU). */
    struct storeAU : public ParserSemanticAction {
      /** Actor Constructor. */
      storeAU (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Unsold Protected (UPR). */
    struct storeUPR : public ParserSemanticAction {
      /** Actor Constructor. */
      storeUPR (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed booking counter. */
    struct storeBookingCounter : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBookingCounter (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Net Availability (NAV). */
    struct storeNAV : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNAV (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Gross Availability (GAV). */
    struct storeGAV : public ParserSemanticAction {
      /** Actor Constructor. */
      storeGAV (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Average Cancellation Percentage (ACP). */
    struct storeACP : public ParserSemanticAction {
      /** Actor Constructor. */
      storeACP (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Expected To Board (ETB) number. */
    struct storeETB : public ParserSemanticAction {
      /** Actor Constructor. */
      storeETB (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Yield Upper Range value. */
    struct storeYieldUpperRange : public ParserSemanticAction {
      /** Actor Constructor. */
      storeYieldUpperRange (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed bucket availability. */
    struct storeBucketAvaibality : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBucketAvaibality (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed leg-cabin seat index. */
    struct storeSeatIndex : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSeatIndex (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed segment boarding point. */
    struct storeSegmentBoardingPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentBoardingPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed segment off point. */
    struct storeSegmentOffPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentOffPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed segment cabin code. */
    struct storeSegmentCabinCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentCabinCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed segment cabin number of bookings. */
    struct storeSegmentCabinBookingCounter : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentCabinBookingCounter (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed booking class code. */
    struct storeClassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeClassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed sub-class code. */
    struct storeSubclassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSubclassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the parsed class code of the parent sub-class. */
    struct storeParentClassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeParentClassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed sub-class code of the parent sub-class. */
    struct storeParentSubclassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeParentSubclassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the parsed cumulated protection (at booking class level). */
    struct storeCumulatedProtection : public ParserSemanticAction {
      /** Actor Constructor. */
      storeCumulatedProtection (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed protection (at booking class level). */
    struct storeProtection : public ParserSemanticAction {
      /** Actor Constructor. */
      storeProtection (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the negotiated allotment (at booking class level). */
    struct storeNego : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNego (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed No-Show percentage (at booking class level). */
    struct storeNoShow : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNoShow (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Overbooking percentage (at booking class level). */
    struct storeOverbooking : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOverbooking (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed list of class codes. */
    struct storeClasses : public ParserSemanticAction {
      /** Actor Constructor. */
      storeClasses (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Mark the end of the inventory parsing. */
    struct doEndFlightDate : public ParserSemanticAction {
      /** Actor Constructor. */
      doEndFlightDate (stdair::BomRoot&, FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
      /** Actor Specific Context. */
      stdair::BomRoot& _bomRoot;
    };

    /////////////////////////////////////////////////////////////////////////
    //
    //  (Boost Spirit) Grammar Definition
    //
    /////////////////////////////////////////////////////////////////////////
    /**
       FlightDepDate;
       2010-02-08; SIN; BKK; L; 10.0; 1.0;

    Grammar:
      FlightDate ::= FlightDepDate ';' Origin ';' Destination
         EndOfFlightDate
      FlightDepDate ::= date
      EndOfFlightDate ::= ';'
     */

    /** Grammar for the inventory parser. */
    struct InventoryParser :
      public boost::spirit::classic::grammar<InventoryParser> {

      InventoryParser (stdair::BomRoot&, FlightDateStruct_T&);

      template <typename ScannerT>
      struct definition {
        definition (InventoryParser const& self);

        // Instantiation of rules
        boost::spirit::classic::rule<ScannerT> flight_date_list, flight_date,
          flight_date_end, flight_key, airline_code, flight_number,
          flight_type_code, date, leg_list, leg, leg_key, leg_details,
          full_leg_cabin_details, leg_cabin_details,
          bucket_list, bucket_details,
          time, segment_list, segment, segment_key, full_segment_cabin_details,
          segment_cabin_list, segment_cabin_key, segment_cabin_details,
          class_list, class_key, parent_subclass_code, class_protection, class_nego,
          class_details;

        /** Entry point of the parser. */
        boost::spirit::classic::rule<ScannerT> const& start() const;
      };

      // Parser Context
      stdair::BomRoot& _bomRoot;
      FlightDateStruct_T& _flightDate;
    };

  }

  /////////////////////////////////////////////////////////////////////////
  //
  //  Entry class for the file parser
  //
  /////////////////////////////////////////////////////////////////////////
  /** Class wrapping the initialisation and entry point of the parser.
      <br>The seemingly redundancy is used to force the instantiation of
      the actual parser, which is a templatised Boost Spirit grammar.
      Hence, the actual parser is instantiated within that class object
      code. */
  class InventoryFileParser : public stdair::CmdAbstract {
  public:
    /** Constructor. */
    InventoryFileParser (stdair::BomRoot&,
                         const stdair::Filename_T& iInventoryInputFilename);

    /** Parse the inventory input file. */
    bool generateInventory ();

  private:
    /** Initialise. */
    void init();

  private:
    // Attributes
    /** File-name of the CSV-formatted inventory input file. */
    stdair::Filename_T _filename;

    /** Start iterator for the parser. */
    iterator_t _startIterator;

    /** End iterator for the parser. */
    iterator_t _endIterator;

    /** Root of the BOM tree. */
    stdair::BomRoot& _bomRoot;

    /** FlightDate Structure. */
    FlightDateStruct_T _flightDate;
  };

}
#endif // __AIRINV_CMD_INVENTORYPARSERHELPER_HPP
<commit_msg>[Parser] The inventory dumps have a new subclass-related field.<commit_after>#ifndef __AIRINV_CMD_INVENTORYPARSERHELPER_HPP
#define __AIRINV_CMD_INVENTORYPARSERHELPER_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <string>
// StdAir
#include <stdair/command/CmdAbstract.hpp>
// Airinv
#include <airinv/AIRINV_Types.hpp>
//#define BOOST_SPIRIT_DEBUG
#include <airinv/basic/BasParserTypes.hpp>
#include <airinv/bom/FlightDateStruct.hpp>

// Forward declarations
namespace stdair {
  class BomRoot;
}

namespace AIRINV {

  namespace InventoryParserHelper {

    // ///////////////////////////////////////////////////////////////////
    //  Semantic actions
    // ///////////////////////////////////////////////////////////////////
    /** Generic Semantic Action (Actor / Functor) for the Inventory Parser. */
    struct ParserSemanticAction {
      /** Actor Constructor. */
      ParserSemanticAction (FlightDateStruct_T&);
      /** Actor Context. */
      FlightDateStruct_T& _flightDate;
    };

    /** Store the snapshot date. */
    struct storeSnapshotDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSnapshotDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed airline code. */
    struct storeAirlineCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeAirlineCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed flight number. */
    struct storeFlightNumber : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightNumber (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the flight date. */
    struct storeFlightDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the flight type code. */
    struct storeFlightTypeCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeFlightTypeCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg boarding point. */
    struct storeLegBoardingPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegBoardingPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg off point. */
    struct storeLegOffPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegOffPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the boarding date. */
    struct storeBoardingDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBoardingDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the boarding time. */
    struct storeBoardingTime : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBoardingTime (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the off date. */
    struct storeOffDate : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOffDate (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the off time. */
    struct storeOffTime : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOffTime (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed leg cabin code. */
    struct storeLegCabinCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeLegCabinCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed saleable capacity. */
    struct storeSaleableCapacity : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSaleableCapacity (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Authorisation Level (AU). */
    struct storeAU : public ParserSemanticAction {
      /** Actor Constructor. */
      storeAU (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Unsold Protected (UPR). */
    struct storeUPR : public ParserSemanticAction {
      /** Actor Constructor. */
      storeUPR (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed booking counter. */
    struct storeBookingCounter : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBookingCounter (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Net Availability (NAV). */
    struct storeNAV : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNAV (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Gross Availability (GAV). */
    struct storeGAV : public ParserSemanticAction {
      /** Actor Constructor. */
      storeGAV (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Average Cancellation Percentage (ACP). */
    struct storeACP : public ParserSemanticAction {
      /** Actor Constructor. */
      storeACP (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Expected To Board (ETB) number. */
    struct storeETB : public ParserSemanticAction {
      /** Actor Constructor. */
      storeETB (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Yield Upper Range value. */
    struct storeYieldUpperRange : public ParserSemanticAction {
      /** Actor Constructor. */
      storeYieldUpperRange (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed bucket availability. */
    struct storeBucketAvaibality : public ParserSemanticAction {
      /** Actor Constructor. */
      storeBucketAvaibality (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed leg-cabin seat index. */
    struct storeSeatIndex : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSeatIndex (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed segment boarding point. */
    struct storeSegmentBoardingPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentBoardingPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed segment off point. */
    struct storeSegmentOffPoint : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentOffPoint (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Store the parsed segment cabin code. */
    struct storeSegmentCabinCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentCabinCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed segment cabin number of bookings. */
    struct storeSegmentCabinBookingCounter : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSegmentCabinBookingCounter (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed booking class code. */
    struct storeClassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeClassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed sub-class code. */
    struct storeSubclassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeSubclassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the parsed class code of the parent sub-class. */
    struct storeParentClassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeParentClassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (char iChar) const;
    };

    /** Store the parsed sub-class code of the parent sub-class. */
    struct storeParentSubclassCode : public ParserSemanticAction {
      /** Actor Constructor. */
      storeParentSubclassCode (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (unsigned int iNumber) const;
    };

    /** Store the parsed cumulated protection (at booking class level). */
    struct storeCumulatedProtection : public ParserSemanticAction {
      /** Actor Constructor. */
      storeCumulatedProtection (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed protection (at booking class level). */
    struct storeProtection : public ParserSemanticAction {
      /** Actor Constructor. */
      storeProtection (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the negotiated allotment (at booking class level). */
    struct storeNego : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNego (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed No-Show percentage (at booking class level). */
    struct storeNoShow : public ParserSemanticAction {
      /** Actor Constructor. */
      storeNoShow (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed Overbooking percentage (at booking class level). */
    struct storeOverbooking : public ParserSemanticAction {
      /** Actor Constructor. */
      storeOverbooking (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (double iReal) const;
    };

    /** Store the parsed list of class codes. */
    struct storeClasses : public ParserSemanticAction {
      /** Actor Constructor. */
      storeClasses (FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
    };

    /** Mark the end of the inventory parsing. */
    struct doEndFlightDate : public ParserSemanticAction {
      /** Actor Constructor. */
      doEndFlightDate (stdair::BomRoot&, FlightDateStruct_T&);
      /** Actor Function (functor). */
      void operator() (iterator_t iStr, iterator_t iStrEnd) const;
      /** Actor Specific Context. */
      stdair::BomRoot& _bomRoot;
    };

    /////////////////////////////////////////////////////////////////////////
    //
    //  (Boost Spirit) Grammar Definition
    //
    /////////////////////////////////////////////////////////////////////////
    /**
       FlightDepDate;
       2010-02-08; SIN; BKK; L; 10.0; 1.0;

    Grammar:
      FlightDate ::= FlightDepDate ';' Origin ';' Destination
         EndOfFlightDate
      FlightDepDate ::= date
      EndOfFlightDate ::= ';'
     */

    /** Grammar for the inventory parser. */
    struct InventoryParser :
      public boost::spirit::classic::grammar<InventoryParser> {

      InventoryParser (stdair::BomRoot&, FlightDateStruct_T&);

      template <typename ScannerT>
      struct definition {
        definition (InventoryParser const& self);

        // Instantiation of rules
        boost::spirit::classic::rule<ScannerT> flight_date_list, flight_date,
          flight_date_end, flight_key, airline_code, flight_number,
          flight_type_code, date, leg_list, leg, leg_key, leg_details,
          full_leg_cabin_details, leg_cabin_details,
          bucket_list, bucket_details,
          time, segment_list, segment, segment_key, full_segment_cabin_details,
          segment_cabin_list, segment_cabin_key, segment_cabin_details,
          class_list, class_key, parent_subclass_code, class_protection, class_nego,
          class_details;

        /** Entry point of the parser. */
        boost::spirit::classic::rule<ScannerT> const& start() const;
      };

      // Parser Context
      stdair::BomRoot& _bomRoot;
      FlightDateStruct_T& _flightDate;
    };

  }

  /////////////////////////////////////////////////////////////////////////
  //
  //  Entry class for the file parser
  //
  /////////////////////////////////////////////////////////////////////////
  /** Class wrapping the initialisation and entry point of the parser.
      <br>The seemingly redundancy is used to force the instantiation of
      the actual parser, which is a templatised Boost Spirit grammar.
      Hence, the actual parser is instantiated within that class object
      code. */
  class InventoryFileParser : public stdair::CmdAbstract {
  public:
    /** Constructor. */
    InventoryFileParser (stdair::BomRoot&,
                         const stdair::Filename_T& iInventoryInputFilename);

    /** Parse the inventory input file. */
    bool generateInventory ();

  private:
    /** Initialise. */
    void init();

  private:
    // Attributes
    /** File-name of the CSV-formatted inventory input file. */
    stdair::Filename_T _filename;

    /** Start iterator for the parser. */
    iterator_t _startIterator;

    /** End iterator for the parser. */
    iterator_t _endIterator;

    /** Root of the BOM tree. */
    stdair::BomRoot& _bomRoot;

    /** FlightDate Structure. */
    FlightDateStruct_T _flightDate;
  };

}
#endif // __AIRINV_CMD_INVENTORYPARSERHELPER_HPP
<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <osterfeld@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "storagefactoryregistry.h"
#include "storagefactory.h"

#include <k3staticdeleter.h>

#include <QHash>
#include <QString>
#include <QStringList>

namespace Akregator {
namespace Backend {

class StorageFactoryRegistry::StorageFactoryRegistryPrivate
{
    public:
        QHash<QString, StorageFactory*> map;
};

StorageFactoryRegistry* StorageFactoryRegistry::m_instance = 0;
static K3StaticDeleter<StorageFactoryRegistry> storagefactoryregistrysd;

StorageFactoryRegistry* StorageFactoryRegistry::self()
{
    if (!m_instance)
        m_instance = storagefactoryregistrysd.setObject(m_instance, new StorageFactoryRegistry);
    return m_instance;
}

bool StorageFactoryRegistry::registerFactory(StorageFactory* factory, const QString& typestr)
{
    if (containsFactory(typestr))
        return false;
    d->map[typestr] = factory;
    return true;
}

void StorageFactoryRegistry::unregisterFactory(const QString& typestr)
{
    d->map.remove(typestr);
}

StorageFactory* StorageFactoryRegistry::getFactory(const QString& typestr)
{
    return d->map[typestr];
}

bool StorageFactoryRegistry::containsFactory(const QString& typestr) const
{
    return d->map.contains(typestr);
}

QStringList StorageFactoryRegistry::list() const
{
    return d->map.keys();
}

StorageFactoryRegistry::StorageFactoryRegistry() : d(new StorageFactoryRegistryPrivate)
{
}

StorageFactoryRegistry::~StorageFactoryRegistry()
{
    delete d;
    d = 0;
}

} // namespace Backend
} // namespace Akregator
<commit_msg>Fix memleak. Delete all registered factories when destroying the factory.<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <osterfeld@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "storagefactoryregistry.h"
#include "storagefactory.h"

#include <k3staticdeleter.h>

#include <QHash>
#include <QString>
#include <QStringList>

namespace Akregator {
namespace Backend {

class StorageFactoryRegistry::StorageFactoryRegistryPrivate
{
    public:
        QHash<QString, StorageFactory*> map;
};

StorageFactoryRegistry* StorageFactoryRegistry::m_instance = 0;
static K3StaticDeleter<StorageFactoryRegistry> storagefactoryregistrysd;

StorageFactoryRegistry* StorageFactoryRegistry::self()
{
    if (!m_instance)
        m_instance = storagefactoryregistrysd.setObject(m_instance, new StorageFactoryRegistry);
    return m_instance;
}

bool StorageFactoryRegistry::registerFactory(StorageFactory* factory, const QString& typestr)
{
    if (containsFactory(typestr))
        return false;
    d->map[typestr] = factory;
    return true;
}

void StorageFactoryRegistry::unregisterFactory(const QString& typestr)
{
    d->map.remove(typestr);
}

StorageFactory* StorageFactoryRegistry::getFactory(const QString& typestr)
{
    return d->map[typestr];
}

bool StorageFactoryRegistry::containsFactory(const QString& typestr) const
{
    return d->map.contains(typestr);
}

QStringList StorageFactoryRegistry::list() const
{
    return d->map.keys();
}

StorageFactoryRegistry::StorageFactoryRegistry() : d(new StorageFactoryRegistryPrivate)
{
}

StorageFactoryRegistry::~StorageFactoryRegistry()
{
    qDeleteAll(d->map);
    delete d;
    d = 0;
}

} // namespace Backend
} // namespace Akregator
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bstbuseditor.hh"
#include "bstparam.hh"
#include "bstitemseqdialog.hh" // FIXME
#include "bstsnifferscope.hh" // FIXME
#include "bse/internal.hh"

/* --- prototypes --- */
static void     bus_editor_action_exec           (gpointer                data,
                                                  size_t                  action);
static gboolean bus_editor_action_check          (gpointer                data,
                                                  size_t                  action,
                                                  guint64                 action_stamp);

/* --- bus actions --- */
enum {
  ACTION_ADD_BUS,
  ACTION_DELETE_BUS,
  ACTION_EDIT_BUS
};
static const GxkStockAction bus_editor_actions[] = {
  { N_("Add"),          NULL,   NULL,   ACTION_ADD_BUS,        BST_STOCK_PART },
  { N_("Delete"),       NULL,   NULL,   ACTION_DELETE_BUS,     BST_STOCK_TRASHCAN },
  { N_("Editor"),       NULL,   NULL,   ACTION_EDIT_BUS,       BST_STOCK_PART_EDITOR },
};

/* --- functions --- */
G_DEFINE_TYPE (BstBusEditor, bst_bus_editor, GTK_TYPE_ALIGNMENT);

static void
bst_bus_editor_init (BstBusEditor *self)
{
  new (&self->source) Bse::SourceS();
  new (&self->lmonitor) Bse::SignalMonitorS();
  new (&self->rmonitor) Bse::SignalMonitorS();
  self->mon_handler = 0;
  /* complete GUI */
  gxk_radget_complete (GTK_WIDGET (self), "beast", "bus-editor", NULL);
  /* create tool actions */
  gxk_widget_publish_actions (self, "bus-editor-actions",
                              G_N_ELEMENTS (bus_editor_actions), bus_editor_actions,
                              NULL, bus_editor_action_check, bus_editor_action_exec);
}

static void
bst_bus_editor_destroy (GtkObject *object)
{
  BstBusEditor *self = BST_BUS_EDITOR (object);
  bst_bus_editor_set_bus (self, 0);
  GTK_OBJECT_CLASS (bst_bus_editor_parent_class)->destroy (object);
}

static void
bst_bus_editor_finalize (GObject *object)
{
  BstBusEditor *self = BST_BUS_EDITOR (object);
  bst_bus_editor_set_bus (self, 0);
  G_OBJECT_CLASS (bst_bus_editor_parent_class)->finalize (object);
  using namespace Bse;
  Bst::remove_handler (&self->mon_handler);
  self->source.~SourceS();
  self->lmonitor.~SignalMonitorS();
  self->rmonitor.~SignalMonitorS();
}

GtkWidget*
bst_bus_editor_new (SfiProxy bus)
{
  assert_return (BSE_IS_BUS (bus), NULL);
  GtkWidget *widget = (GtkWidget*) g_object_new (BST_TYPE_BUS_EDITOR, NULL);
  BstBusEditor *self = BST_BUS_EDITOR (widget);
  bst_bus_editor_set_bus (self, bus);
  return widget;
}

static void
bus_editor_release_item (SfiProxy      item,
                         BstBusEditor *self)
{
  assert_return (self->item == item);
  bst_bus_editor_set_bus (self, 0);
}

static GtkWidget*
bus_build_param (BstBusEditor *self,
                 const gchar  *property,
                 const gchar  *area,
                 const gchar  *editor,
                 const gchar  *label)
{
  GxkParam *gxk_param = nullptr;

  /* aida property? */
  Bse::BusH bus = Bse::BusH::__cast__ (bse_server.from_proxy (self->item));
  const Bse::StringSeq meta = bus.find_prop (property);

  GParamSpec *cxxpspec = Bse::pspec_from_key_value_list (property, meta);
  if (cxxpspec)
    gxk_param = bst_param_new_property (cxxpspec, bus);

  if (!gxk_param)
    {
      /* proxy property */
      auto pspec = bse_proxy_get_pspec (self->item, property);
      gxk_param = bst_param_new_proxy (pspec, self->item);
    }

  self->params = sfi_ring_prepend (self->params, gxk_param);
  GtkWidget *ewidget = gxk_param_create_editor ((GxkParam*) self->params->data, editor);
  gxk_radget_add (self, area, ewidget);
  if (label)
    g_object_set (gxk_parent_find_descendant (ewidget, GTK_TYPE_LABEL), "label", label, NULL);
  return ewidget;
}

static gboolean
grab_focus_and_false (GtkWidget *widget)
{
  gtk_widget_grab_focus (widget);
  return FALSE;
}

void
bst_bus_editor_set_bus (BstBusEditor *self,
                        SfiProxy      item)
{
  if (item)
    assert_return (BSE_IS_BUS (item));
  if (self->item)
    {
      Bst::remove_handler (&self->mon_handler);
      self->lmonitor = NULL;
      self->rmonitor = NULL;
      Bse::SourceH source = Bse::SourceH::__cast__ (bse_server.from_proxy (self->item));
      bse_proxy_disconnect (self->item,
                            "any-signal", bus_editor_release_item, self,
                            NULL);
      self->source = NULL;
      while (self->params)
        gxk_param_destroy ((GxkParam*) sfi_ring_pop_head (&self->params));
    }
  self->item = item;
  if (self->item)
    {
      self->source = Bse::SourceH::__cast__ (bse_server.from_proxy (self->item));
      GParamSpec *pspec;
      SfiRing *ring;
      bse_proxy_connect (self->item,
                         "signal::release", bus_editor_release_item, self,
                         NULL);
      /* create and hook up volume params & scopes */
      pspec = bse_proxy_get_pspec (self->item, "left-volume");
      GxkParam *lvolume = bst_param_new_proxy (pspec, self->item);
      GtkWidget *lspinner = gxk_param_create_editor (lvolume, "spinner");
      pspec = bse_proxy_get_pspec (self->item, "right-volume");
      GxkParam *rvolume = bst_param_new_proxy (pspec, self->item);
      GtkWidget *rspinner = gxk_param_create_editor (rvolume, "spinner");
      BstDBMeter *dbmeter = (BstDBMeter*) gxk_radget_find (self, "db-meter");
      if (dbmeter)
        {
          GtkRange *range = bst_db_meter_get_scale (dbmeter, 0);
          bst_db_scale_hook_up_param (range, lvolume);
          g_signal_connect_object (range, "button-press-event", G_CALLBACK (grab_focus_and_false), lspinner, G_CONNECT_SWAPPED);
          range = bst_db_meter_get_scale (dbmeter, 1);
          bst_db_scale_hook_up_param (range, rvolume);
          g_signal_connect_object (range, "button-press-event", G_CALLBACK (grab_focus_and_false), rspinner, G_CONNECT_SWAPPED);
          self->lbeam = bst_db_meter_get_beam (dbmeter, 0);
          if (self->lbeam)
            bst_db_beam_set_value (self->lbeam, -G_MAXDOUBLE);
          self->rbeam = bst_db_meter_get_beam (dbmeter, 1);
          if (self->rbeam)
            bst_db_beam_set_value (self->rbeam, -G_MAXDOUBLE);
        }
      gxk_radget_add (self, "spinner-box", lspinner);
      gxk_radget_add (self, "spinner-box", rspinner);
      self->params = sfi_ring_prepend (self->params, lvolume);
      self->params = sfi_ring_prepend (self->params, rvolume);
      /* create remaining params */
      bus_build_param (self, "uname", "name-box", NULL, NULL);
      bus_build_param (self, "inputs", "inputs-box", NULL, NULL);
      bus_build_param (self, "mute", "toggle-box", "toggle+label", "M");
      bus_build_param (self, "sync", "toggle-box", "toggle+label", "Y");
      bus_build_param (self, "solo", "toggle-box", "toggle+label", "S");
      bus_build_param (self, "outputs", "outputs-box", NULL, NULL);
      /* update params */
      for (ring = self->params; ring; ring = sfi_ring_walk (ring, self->params))
        gxk_param_update ((GxkParam*) ring->data);
      /* setup scope */
      Bse::ProbeFeatures features;
      features.probe_energy = true;
      self->lmonitor = self->source.create_signal_monitor (0);
      self->rmonitor = self->source.create_signal_monitor (1);
      self->lmonitor.set_probe_features (features);
      self->rmonitor.set_probe_features (features);
      Bst::MonitorFieldU lfields = Bst::monitor_fields_from_shm (self->lmonitor.get_shm_id(), self->lmonitor.get_shm_offset());
      Bst::MonitorFieldU rfields = Bst::monitor_fields_from_shm (self->rmonitor.get_shm_id(), self->rmonitor.get_shm_offset());
      auto framecb = [self, lfields, rfields] () {
        bst_db_beam_set_value (self->lbeam, lfields.f32 (Bse::MonitorField::F32_DB_SPL));
        bst_db_beam_set_value (self->rbeam, rfields.f32 (Bse::MonitorField::F32_DB_SPL));
        if (0)
          printerr ("BstBusEditor: (%x.%x/%x %x.%x/%x) ldb=%f rdb=%f\n",
                    self->lmonitor.get_shm_id(), self->lmonitor.get_shm_offset(),
                    lfields.f64 (Bse::MonitorField::F64_GENERATION),
                    self->rmonitor.get_shm_id(), self->rmonitor.get_shm_offset(),
                    rfields.f64 (Bse::MonitorField::F64_GENERATION),
                    lfields.f32 (Bse::MonitorField::F32_DB_SPL),
                    rfields.f32 (Bse::MonitorField::F32_DB_SPL));
      };
      self->mon_handler = Bst::add_frame_handler (framecb);
    }
}

static void
bus_editor_action_exec (gpointer data,
                        size_t   action)
{
  BstBusEditor *self = BST_BUS_EDITOR (data);
  switch (action)
    {
    case ACTION_ADD_BUS:
      break;
    case ACTION_DELETE_BUS:
      break;
    case ACTION_EDIT_BUS:
      break;
    }
  gxk_widget_update_actions_downwards (self);
}

static gboolean
bus_editor_action_check (gpointer data,
                         size_t   action,
                         guint64  action_stamp)
{
  // BstBusEditor *self = BST_BUS_EDITOR (data);
  switch (action)
    {
    case ACTION_ADD_BUS:
    case ACTION_DELETE_BUS:
    case ACTION_EDIT_BUS:
      return TRUE;
    default:
      return FALSE;
    }
}

static void
bst_bus_editor_class_init (BstBusEditorClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);

  gobject_class->finalize = bst_bus_editor_finalize;
  object_class->destroy = bst_bus_editor_destroy;
}
<commit_msg>BEAST-GTK: bstbuseditor: use left_volume C++ property<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bstbuseditor.hh"
#include "bstparam.hh"
#include "bstitemseqdialog.hh" // FIXME
#include "bstsnifferscope.hh" // FIXME
#include "bse/internal.hh"

/* --- prototypes --- */
static void     bus_editor_action_exec           (gpointer                data,
                                                  size_t                  action);
static gboolean bus_editor_action_check          (gpointer                data,
                                                  size_t                  action,
                                                  guint64                 action_stamp);

/* --- bus actions --- */
enum {
  ACTION_ADD_BUS,
  ACTION_DELETE_BUS,
  ACTION_EDIT_BUS
};
static const GxkStockAction bus_editor_actions[] = {
  { N_("Add"),          NULL,   NULL,   ACTION_ADD_BUS,        BST_STOCK_PART },
  { N_("Delete"),       NULL,   NULL,   ACTION_DELETE_BUS,     BST_STOCK_TRASHCAN },
  { N_("Editor"),       NULL,   NULL,   ACTION_EDIT_BUS,       BST_STOCK_PART_EDITOR },
};

/* --- functions --- */
G_DEFINE_TYPE (BstBusEditor, bst_bus_editor, GTK_TYPE_ALIGNMENT);

static void
bst_bus_editor_init (BstBusEditor *self)
{
  new (&self->source) Bse::SourceS();
  new (&self->lmonitor) Bse::SignalMonitorS();
  new (&self->rmonitor) Bse::SignalMonitorS();
  self->mon_handler = 0;
  /* complete GUI */
  gxk_radget_complete (GTK_WIDGET (self), "beast", "bus-editor", NULL);
  /* create tool actions */
  gxk_widget_publish_actions (self, "bus-editor-actions",
                              G_N_ELEMENTS (bus_editor_actions), bus_editor_actions,
                              NULL, bus_editor_action_check, bus_editor_action_exec);
}

static void
bst_bus_editor_destroy (GtkObject *object)
{
  BstBusEditor *self = BST_BUS_EDITOR (object);
  bst_bus_editor_set_bus (self, 0);
  GTK_OBJECT_CLASS (bst_bus_editor_parent_class)->destroy (object);
}

static void
bst_bus_editor_finalize (GObject *object)
{
  BstBusEditor *self = BST_BUS_EDITOR (object);
  bst_bus_editor_set_bus (self, 0);
  G_OBJECT_CLASS (bst_bus_editor_parent_class)->finalize (object);
  using namespace Bse;
  Bst::remove_handler (&self->mon_handler);
  self->source.~SourceS();
  self->lmonitor.~SignalMonitorS();
  self->rmonitor.~SignalMonitorS();
}

GtkWidget*
bst_bus_editor_new (SfiProxy bus)
{
  assert_return (BSE_IS_BUS (bus), NULL);
  GtkWidget *widget = (GtkWidget*) g_object_new (BST_TYPE_BUS_EDITOR, NULL);
  BstBusEditor *self = BST_BUS_EDITOR (widget);
  bst_bus_editor_set_bus (self, bus);
  return widget;
}

static void
bus_editor_release_item (SfiProxy      item,
                         BstBusEditor *self)
{
  assert_return (self->item == item);
  bst_bus_editor_set_bus (self, 0);
}

static GxkParam *
get_property_param (BstBusEditor *self,
                    const gchar  *property)
{
  Bse::BusH bus = Bse::BusH::__cast__ (bse_server.from_proxy (self->item));
  const Bse::StringSeq kvlist = bus.find_prop (property);

  GParamSpec *cxxpspec = Bse::pspec_from_key_value_list (property, kvlist);
  if (cxxpspec)
    return bst_param_new_property (cxxpspec, bus);

  return nullptr;
}

static GtkWidget*
bus_build_param (BstBusEditor *self,
                 const gchar  *property,
                 const gchar  *area,
                 const gchar  *editor,
                 const gchar  *label)
{
  GxkParam *gxk_param = get_property_param (self, property); /* aida property? */

  if (!gxk_param)
    {
      /* proxy property */
      auto pspec = bse_proxy_get_pspec (self->item, property);
      gxk_param = bst_param_new_proxy (pspec, self->item);
    }

  self->params = sfi_ring_prepend (self->params, gxk_param);
  GtkWidget *ewidget = gxk_param_create_editor ((GxkParam*) self->params->data, editor);
  gxk_radget_add (self, area, ewidget);
  if (label)
    g_object_set (gxk_parent_find_descendant (ewidget, GTK_TYPE_LABEL), "label", label, NULL);
  return ewidget;
}

static gboolean
grab_focus_and_false (GtkWidget *widget)
{
  gtk_widget_grab_focus (widget);
  return FALSE;
}

void
bst_bus_editor_set_bus (BstBusEditor *self,
                        SfiProxy      item)
{
  if (item)
    assert_return (BSE_IS_BUS (item));
  if (self->item)
    {
      Bst::remove_handler (&self->mon_handler);
      self->lmonitor = NULL;
      self->rmonitor = NULL;
      Bse::SourceH source = Bse::SourceH::__cast__ (bse_server.from_proxy (self->item));
      bse_proxy_disconnect (self->item,
                            "any-signal", bus_editor_release_item, self,
                            NULL);
      self->source = NULL;
      while (self->params)
        gxk_param_destroy ((GxkParam*) sfi_ring_pop_head (&self->params));
    }
  self->item = item;
  if (self->item)
    {
      self->source = Bse::SourceH::__cast__ (bse_server.from_proxy (self->item));
      GParamSpec *pspec;
      SfiRing *ring;
      bse_proxy_connect (self->item,
                         "signal::release", bus_editor_release_item, self,
                         NULL);
      /* create and hook up volume params & scopes */
      GxkParam *lvolume = get_property_param (self, "left_volume");
      GtkWidget *lspinner = gxk_param_create_editor (lvolume, "spinner");
      pspec = bse_proxy_get_pspec (self->item, "right-volume");
      GxkParam *rvolume = bst_param_new_proxy (pspec, self->item);
      GtkWidget *rspinner = gxk_param_create_editor (rvolume, "spinner");
      BstDBMeter *dbmeter = (BstDBMeter*) gxk_radget_find (self, "db-meter");
      if (dbmeter)
        {
          GtkRange *range = bst_db_meter_get_scale (dbmeter, 0);
          bst_db_scale_hook_up_param (range, lvolume);
          g_signal_connect_object (range, "button-press-event", G_CALLBACK (grab_focus_and_false), lspinner, G_CONNECT_SWAPPED);
          range = bst_db_meter_get_scale (dbmeter, 1);
          bst_db_scale_hook_up_param (range, rvolume);
          g_signal_connect_object (range, "button-press-event", G_CALLBACK (grab_focus_and_false), rspinner, G_CONNECT_SWAPPED);
          self->lbeam = bst_db_meter_get_beam (dbmeter, 0);
          if (self->lbeam)
            bst_db_beam_set_value (self->lbeam, -G_MAXDOUBLE);
          self->rbeam = bst_db_meter_get_beam (dbmeter, 1);
          if (self->rbeam)
            bst_db_beam_set_value (self->rbeam, -G_MAXDOUBLE);
        }
      gxk_radget_add (self, "spinner-box", lspinner);
      gxk_radget_add (self, "spinner-box", rspinner);
      self->params = sfi_ring_prepend (self->params, lvolume);
      self->params = sfi_ring_prepend (self->params, rvolume);
      /* create remaining params */
      bus_build_param (self, "uname", "name-box", NULL, NULL);
      bus_build_param (self, "inputs", "inputs-box", NULL, NULL);
      bus_build_param (self, "mute", "toggle-box", "toggle+label", "M");
      bus_build_param (self, "sync", "toggle-box", "toggle+label", "Y");
      bus_build_param (self, "solo", "toggle-box", "toggle+label", "S");
      bus_build_param (self, "outputs", "outputs-box", NULL, NULL);
      /* update params */
      for (ring = self->params; ring; ring = sfi_ring_walk (ring, self->params))
        gxk_param_update ((GxkParam*) ring->data);
      /* setup scope */
      Bse::ProbeFeatures features;
      features.probe_energy = true;
      self->lmonitor = self->source.create_signal_monitor (0);
      self->rmonitor = self->source.create_signal_monitor (1);
      self->lmonitor.set_probe_features (features);
      self->rmonitor.set_probe_features (features);
      Bst::MonitorFieldU lfields = Bst::monitor_fields_from_shm (self->lmonitor.get_shm_id(), self->lmonitor.get_shm_offset());
      Bst::MonitorFieldU rfields = Bst::monitor_fields_from_shm (self->rmonitor.get_shm_id(), self->rmonitor.get_shm_offset());
      auto framecb = [self, lfields, rfields] () {
        bst_db_beam_set_value (self->lbeam, lfields.f32 (Bse::MonitorField::F32_DB_SPL));
        bst_db_beam_set_value (self->rbeam, rfields.f32 (Bse::MonitorField::F32_DB_SPL));
        if (0)
          printerr ("BstBusEditor: (%x.%x/%x %x.%x/%x) ldb=%f rdb=%f\n",
                    self->lmonitor.get_shm_id(), self->lmonitor.get_shm_offset(),
                    lfields.f64 (Bse::MonitorField::F64_GENERATION),
                    self->rmonitor.get_shm_id(), self->rmonitor.get_shm_offset(),
                    rfields.f64 (Bse::MonitorField::F64_GENERATION),
                    lfields.f32 (Bse::MonitorField::F32_DB_SPL),
                    rfields.f32 (Bse::MonitorField::F32_DB_SPL));
      };
      self->mon_handler = Bst::add_frame_handler (framecb);
    }
}

static void
bus_editor_action_exec (gpointer data,
                        size_t   action)
{
  BstBusEditor *self = BST_BUS_EDITOR (data);
  switch (action)
    {
    case ACTION_ADD_BUS:
      break;
    case ACTION_DELETE_BUS:
      break;
    case ACTION_EDIT_BUS:
      break;
    }
  gxk_widget_update_actions_downwards (self);
}

static gboolean
bus_editor_action_check (gpointer data,
                         size_t   action,
                         guint64  action_stamp)
{
  // BstBusEditor *self = BST_BUS_EDITOR (data);
  switch (action)
    {
    case ACTION_ADD_BUS:
    case ACTION_DELETE_BUS:
    case ACTION_EDIT_BUS:
      return TRUE;
    default:
      return FALSE;
    }
}

static void
bst_bus_editor_class_init (BstBusEditorClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);

  gobject_class->finalize = bst_bus_editor_finalize;
  object_class->destroy = bst_bus_editor_destroy;
}
<|endoftext|>


<commit_before>/*
* Basic camera class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

class Camera
{
private:
	float fov;
	float znear, zfar;

	void updateViewMatrix()
	{
		glm::mat4 rotM = glm::mat4();
		glm::mat4 transM;

		rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

		transM = glm::translate(glm::mat4(), position);

		if (type == CameraType::firstperson)
		{
			matrices.view = rotM * transM;
		}
		else
		{
			matrices.view = transM * rotM;
		}
	};
public:
	enum CameraType { lookat, firstperson };
	CameraType type = CameraType::lookat;

	glm::vec3 rotation = glm::vec3();
	glm::vec3 position = glm::vec3();

	float rotationSpeed = 1.0f;
	float movementSpeed = 1.0f;

	struct
	{
		glm::mat4 perspective;
		glm::mat4 view;
	} matrices;

	struct
	{
		bool left = false;
		bool right = false;
		bool up = false;
		bool down = false;
	} keys;

	bool moving()
	{
		return keys.left || keys.right || keys.up || keys.down;
	}

	void setPerspective(float fov, float aspect, float znear, float zfar)
	{
		this->fov = fov;
		this->znear = znear;
		this->zfar = zfar;
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	};

	void updateAspectRatio(float aspect)
	{
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	}

	void setPosition(glm::vec3 position)
	{
		this->position = position;
		updateViewMatrix();
	}

	void setRotation(glm::vec3 rotation)
	{
		this->rotation = rotation;
		updateViewMatrix();
	};

	void rotate(glm::vec3 delta)
	{
		this->rotation += delta;
		updateViewMatrix();
	}

	void setTranslation(glm::vec3 translation)
	{
		this->position = translation;
		updateViewMatrix();
	};

	void translate(glm::vec3 delta)
	{
		this->position += delta;
		updateViewMatrix();
	}

	void update(float deltaTime)
	{
		if (type == CameraType::firstperson)
		{
			if (moving())
			{
				glm::vec3 camFront;
				camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
				camFront.y = sin(glm::radians(rotation.x));
				camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
				camFront = glm::normalize(camFront);

				float moveSpeed = deltaTime * movementSpeed;

				if (keys.up)
					position += camFront * moveSpeed;
				if (keys.down)
					position -= camFront * moveSpeed;
				if (keys.left)
					position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
				if (keys.right)
					position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;

				updateViewMatrix();
			}
		}
	};

	// Update camera passing separate axis data (gamepad)
	// Returns true if view or position has been changed
	bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
	{
		bool retVal = false;

		if (type == CameraType::firstperson)
		{
			// Use the common console thumbstick layout
			// Left = view, right = move

			const float deadZone = 0.0015f;
			const float range = 1.0f - deadZone;

			glm::vec3 camFront;
			camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
			camFront.y = sin(glm::radians(rotation.x));
			camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
			camFront = glm::normalize(camFront);

			float moveSpeed = deltaTime * movementSpeed * 2.0f;
			float rotSpeed = deltaTime * rotationSpeed * 50.0f;

			// Move
			if (fabsf(axisLeft.y) > deadZone)
			{
				float pos = (fabsf(axisLeft.y) - deadZone) / range;
				position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}
			if (fabsf(axisLeft.x) > deadZone)
			{
				float pos = (fabsf(axisLeft.x) - deadZone) / range;
				position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}

			// Rotate
			if (fabsf(axisRight.x) > deadZone)
			{
				float pos = (fabsf(axisRight.x) - deadZone) / range;
				rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
			if (fabsf(axisRight.y) > deadZone)
			{
				float pos = (fabsf(axisRight.y) - deadZone) / range;
				rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
		}
		else
		{
			// todo: move code from example base class for look-at
		}

		if (retVal)
		{
			updateViewMatrix();
		}

		return retVal;
	}

};<commit_msg>Missing include<commit_after>/*
* Basic camera class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>

class Camera
{
private:
	float fov;
	float znear, zfar;

	void updateViewMatrix()
	{
		glm::mat4 rotM = glm::mat4();
		glm::mat4 transM;

		rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

		transM = glm::translate(glm::mat4(), position);

		if (type == CameraType::firstperson)
		{
			matrices.view = rotM * transM;
		}
		else
		{
			matrices.view = transM * rotM;
		}
	};
public:
	enum CameraType { lookat, firstperson };
	CameraType type = CameraType::lookat;

	glm::vec3 rotation = glm::vec3();
	glm::vec3 position = glm::vec3();

	float rotationSpeed = 1.0f;
	float movementSpeed = 1.0f;

	struct
	{
		glm::mat4 perspective;
		glm::mat4 view;
	} matrices;

	struct
	{
		bool left = false;
		bool right = false;
		bool up = false;
		bool down = false;
	} keys;

	bool moving()
	{
		return keys.left || keys.right || keys.up || keys.down;
	}

	void setPerspective(float fov, float aspect, float znear, float zfar)
	{
		this->fov = fov;
		this->znear = znear;
		this->zfar = zfar;
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	};

	void updateAspectRatio(float aspect)
	{
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	}

	void setPosition(glm::vec3 position)
	{
		this->position = position;
		updateViewMatrix();
	}

	void setRotation(glm::vec3 rotation)
	{
		this->rotation = rotation;
		updateViewMatrix();
	};

	void rotate(glm::vec3 delta)
	{
		this->rotation += delta;
		updateViewMatrix();
	}

	void setTranslation(glm::vec3 translation)
	{
		this->position = translation;
		updateViewMatrix();
	};

	void translate(glm::vec3 delta)
	{
		this->position += delta;
		updateViewMatrix();
	}

	void update(float deltaTime)
	{
		if (type == CameraType::firstperson)
		{
			if (moving())
			{
				glm::vec3 camFront;
				camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
				camFront.y = sin(glm::radians(rotation.x));
				camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
				camFront = glm::normalize(camFront);

				float moveSpeed = deltaTime * movementSpeed;

				if (keys.up)
					position += camFront * moveSpeed;
				if (keys.down)
					position -= camFront * moveSpeed;
				if (keys.left)
					position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
				if (keys.right)
					position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;

				updateViewMatrix();
			}
		}
	};

	// Update camera passing separate axis data (gamepad)
	// Returns true if view or position has been changed
	bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
	{
		bool retVal = false;

		if (type == CameraType::firstperson)
		{
			// Use the common console thumbstick layout
			// Left = view, right = move

			const float deadZone = 0.0015f;
			const float range = 1.0f - deadZone;

			glm::vec3 camFront;
			camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
			camFront.y = sin(glm::radians(rotation.x));
			camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
			camFront = glm::normalize(camFront);

			float moveSpeed = deltaTime * movementSpeed * 2.0f;
			float rotSpeed = deltaTime * rotationSpeed * 50.0f;

			// Move
			if (fabsf(axisLeft.y) > deadZone)
			{
				float pos = (fabsf(axisLeft.y) - deadZone) / range;
				position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}
			if (fabsf(axisLeft.x) > deadZone)
			{
				float pos = (fabsf(axisLeft.x) - deadZone) / range;
				position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}

			// Rotate
			if (fabsf(axisRight.x) > deadZone)
			{
				float pos = (fabsf(axisRight.x) - deadZone) / range;
				rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
			if (fabsf(axisRight.y) > deadZone)
			{
				float pos = (fabsf(axisRight.y) - deadZone) / range;
				rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
		}
		else
		{
			// todo: move code from example base class for look-at
		}

		if (retVal)
		{
			updateViewMatrix();
		}

		return retVal;
	}

};<|endoftext|>