<commit_before>// @(#):$Id$
// Author: Andrei Gheata   01/03/11

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

////////////////////////////////////////////////////////////////////////////
//
// TGeoBranchArray - An array of daughter indices making a geometry path.
//   Can be used to backup/restore a state. To setup an object of this type,
// one should use:
//   TGeoBranchArray *array = new TGeoBranchArray(level);
//   array->InitFromNavigator(nav); (To initialize from current navigator state)
// The navigator can be updated to reflect this path array:
//   array->UpdateNavigator();
//
/////////////////////////////////////////////////////////////////////////////

#include "TGeoBranchArray.h"

#include "TMath.h"
#include "TThread.h"
#include "TString.h"
#include "TGeoNavigator.h"
#include "TGeoCache.h"
#include "TGeoManager.h"

ClassImp(TGeoBranchArray)

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(Int_t maxlevel)
                :fLevel(-1),
                 fMaxLevel(maxlevel),
                 fMatrix(),
                 fArray(&fRealArray[0])
{
// Constructor. Alocates the array with a size given by level.
   memset(fRealArray, 0, fMaxLevel*sizeof(TGeoNode*));
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeInstance(size_t maxlevel)
{
// Make an instance of the class which allocates the node array. To be
// released using ReleaseInstance. If addr is non-zero, the user promised that
// addr contains at least that many bytes:  size_t needed = SizeOf(maxlevel);
   TGeoBranchArray* ba = 0;
   size_t needed = SizeOf(maxlevel);
   char *ptr = new char[ needed ];
   if (!ptr) return 0;
   new (ptr) TGeoBranchArray(maxlevel);
   ba = reinterpret_cast<TGeoBranchArray*>(ptr);
   ba->SetBit(kBASelfAlloc, kTRUE);
   return ba;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeInstanceAt(size_t maxlevel, void *addr)
{
   // Make an instance of the class which allocates the node array. To be
   // released using ReleaseInstance. If addr is non-zero, the user promised that
   // addr contains at least that many bytes:  size_t needed = SizeOf(maxlevel);
   TGeoBranchArray* ba = 0;
   new (addr) TGeoBranchArray(maxlevel);
   ba = reinterpret_cast<TGeoBranchArray*>(addr);
   ba->SetBit(kBASelfAlloc, kFALSE);
   return ba;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeCopy(const TGeoBranchArray &other)
{
// Make a copy of a branch array at the location (if indicated)
   TGeoBranchArray *copy = 0;
   size_t needed = SizeOf(other.fMaxLevel);
   char *ptr = new char[ needed ];
   if (!ptr) return 0;
   new (ptr) TGeoBranchArray(other.fMaxLevel);
   copy = reinterpret_cast<TGeoBranchArray*>(ptr);
   copy->SetBit(kBASelfAlloc, kTRUE);
   copy->fLevel = other.fLevel;
   copy->fMatrix = other.fMatrix;
   if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
   return copy;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeCopyAt(const TGeoBranchArray &other, void *addr)
{
   // Make a copy of a branch array at the location (if indicated)
   TGeoBranchArray *copy = 0;
   new (addr) TGeoBranchArray(other.fMaxLevel);
   copy = reinterpret_cast<TGeoBranchArray*>(addr);
   copy->SetBit(kBASelfAlloc, kFALSE);
   copy->fLevel = other.fLevel;
   copy->fMatrix = other.fMatrix;
   if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
   return copy;
}

//______________________________________________________________________________
void TGeoBranchArray::CopyTo(TGeoBranchArray *dest)
{
// Raw memcpy of the branch array content to an existing destination.
   memcpy(dest->DataStart(), DataStart(), DataSize());
   dest->fArray = &(dest->fRealArray[0]);
}

//______________________________________________________________________________
void TGeoBranchArray::ReleaseInstance(TGeoBranchArray *obj)
{
// Releases the space allocated for the object
   obj->~TGeoBranchArray();
   if (obj->TestBit(kBASelfAlloc)) delete [] (char*)obj;
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateArray(size_t nobj)
{
// Updates the internal addresses for n contiguous objects which have the same
// fMaxLevel
// Updates the internal addresses for n contiguous objects which have the same fMaxLevel
   size_t needed = SizeOf();
//   char *where = &fArray;
//   for (size_t i=0; i<nobj; ++i, where += needed) {
//      TGeoNode ***array =  reinterpret_cast<TGeoNode***>(where);
//      *array = ((void**)where)+1;
//   }
   char *where = reinterpret_cast<char*>(this);
   for (size_t i=0; i<nobj; ++i, where += needed) {
      TGeoBranchArray *obj = reinterpret_cast<TGeoBranchArray*>(where);
      obj->fArray = &(obj->fRealArray[0]);
   }
}

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray&  other)
                :TObject(other),
                 fLevel(other.fLevel),
                 fMaxLevel(other.fMaxLevel),
                 fMatrix(other.fMatrix),
                 fArray(NULL)
{
// Copy constructor. Not callable anymore. Use TGeoBranchArray::MakeCopy instead
   if (fMaxLevel) {
      fArray = new TGeoNode*[fMaxLevel];
      if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
   }
}

//______________________________________________________________________________
TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
{
// Assignment. Not valid anymore. Use TGeoBranchArray::MakeCopy instead
   if (&other == this) return *this;
//   TThread::Lock();
//   TObject::operator=(other);
   fLevel = other.fLevel;
   fMatrix.CopyFrom(&other.fMatrix);
   if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
//   SetBit(other.TestBit(kBASelfAlloc));
//   TThread::UnLock();
   return *this;
}

//______________________________________________________________________________
void TGeoBranchArray::AddLevel(Int_t dindex)
{
// Add and extra daughter to the current path array. No validity check performed !
   if (fLevel<0) {
      Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
      return;
   }
   if (fLevel>fMaxLevel) {
      Fatal("AddLevel", "Max level = %d reached\n", fMaxLevel);
      return;
   }
   fLevel++;
/*
   if (fLevel+1>fMaxLevel) {
      TGeoNode **array = new TGeoNode*[fLevel+1];
      memcpy(array, fArray, fLevel*sizeof(TGeoNode*));
      delete [] fArray;
      fArray = array;
   }
*/
   fArray[fLevel] = fArray[fLevel-1]->GetVolume()->GetNode(dindex);
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value==0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
{
// Not equal operator.
   Int_t value = Compare(&other);
   if (value!=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
{
// Binary search in an array of n pointers to branch arrays, to locate value.
// Returns element index or index of nearest element smaller than value
   Long64_t nabove, nbelow, middle;
   const TGeoBranchArray *pind;
   nabove = n+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      pind = array[middle-1];
      if (*value == *pind) return middle-1;
      if (*value  < *pind) nabove = middle;
      else                          nbelow = middle;
   }
   return nbelow-1;
}

//______________________________________________________________________________
Int_t TGeoBranchArray::Compare(const TObject *obj) const
{
// Compare with other object of same type. Returns -1 if this is smaller (first
// smaller array value prevails), 0 if equal (size and values) and 1 if this is
// larger.
   Int_t i;
   TGeoBranchArray *other = (TGeoBranchArray*)obj;
   Int_t otherLevel = other->GetLevel();
   Int_t maxLevel = TMath::Min(fLevel, otherLevel);
   TGeoNode **otherArray = other->GetArray();
   for (i=0; i<maxLevel+1; i++) {
      if (fArray[i]==otherArray[i]) continue;
      if ((Long64_t)fArray[i]<(Long64_t)otherArray[i]) return -1;
      return 1;
   }
   if (fLevel==otherLevel) return 0;
   if (fLevel<otherLevel) return -1;
   return 1;
}

//______________________________________________________________________________
void TGeoBranchArray::CleanMatrix()
{
// Garbage collect the stored matrix.
}

//______________________________________________________________________________
void TGeoBranchArray::Init(TGeoNode **branch, TGeoMatrix *global, Int_t level)
{
// Init the branch array from an array of nodes, the global matrix for the path and
// the level.
   fMatrix.CopyFrom(global);
   if (level>fMaxLevel) {
      Fatal("Init", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
      return;
   }
   fLevel = level;
   memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
}

//______________________________________________________________________________
void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
{
// Init the branch array from current navigator state.
   TGeoNodeCache *cache = nav->GetCache();
   const TGeoNode **branch = (const TGeoNode**)cache->GetBranch();
   Int_t level = cache->GetLevel();
   fMatrix.CopyFrom(cache->GetCurrentMatrix());
   if (level>fMaxLevel) {
      Fatal("InitFromNavigator", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
      return;
   }
   fLevel = level;
   memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
   if (nav->IsOutside()) fLevel = -1;
}

//______________________________________________________________________________
void TGeoBranchArray::GetPath(TString &path) const
{
// Fill path pointed by the array.
   path = "";
   if (!fArray || !fArray[0]) return;
   for (Int_t i=0; i<fLevel+1; i++) {
      path += "/";
      path += fArray[i]->GetName();
   }
}

//______________________________________________________________________________
void TGeoBranchArray::Print(Option_t *) const
{
// Print branch information
   TString path;
   GetPath(path);
   printf("branch:    %s\n", path.Data());
}

//______________________________________________________________________________
void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
{
// Sorting of an array of branch array pointers.
   for (Int_t i=0; i<n; i++) index[i] = i;
   if (down)
      std::sort(index, index + n, compareBAdesc(array));
   else
      std::sort(index, index + n, compareBAasc(array));
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
{
// Update the navigator to reflect the branch.
   nav->CdTop();
   if (fLevel<0) {nav->SetOutside(kTRUE); return;}
   for (Int_t i=1; i<fLevel+1; i++) nav->CdDown(fArray[i]);
}
<commit_msg>Optimised TGeoBranchArray::UpdateNavigator to use the partial path the navigator may be already in<commit_after>// @(#):$Id$
// Author: Andrei Gheata   01/03/11

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

////////////////////////////////////////////////////////////////////////////
//
// TGeoBranchArray - An array of daughter indices making a geometry path.
//   Can be used to backup/restore a state. To setup an object of this type,
// one should use:
//   TGeoBranchArray *array = new TGeoBranchArray(level);
//   array->InitFromNavigator(nav); (To initialize from current navigator state)
// The navigator can be updated to reflect this path array:
//   array->UpdateNavigator();
//
/////////////////////////////////////////////////////////////////////////////

#include "TGeoBranchArray.h"

#include "TMath.h"
#include "TThread.h"
#include "TString.h"
#include "TGeoNavigator.h"
#include "TGeoCache.h"
#include "TGeoManager.h"

ClassImp(TGeoBranchArray)

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(Int_t maxlevel)
                :fLevel(-1),
                 fMaxLevel(maxlevel),
                 fMatrix(),
                 fArray(&fRealArray[0])
{
// Constructor. Alocates the array with a size given by level.
   memset(fRealArray, 0, fMaxLevel*sizeof(TGeoNode*));
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeInstance(size_t maxlevel)
{
// Make an instance of the class which allocates the node array. To be
// released using ReleaseInstance. If addr is non-zero, the user promised that
// addr contains at least that many bytes:  size_t needed = SizeOf(maxlevel);
   TGeoBranchArray* ba = 0;
   size_t needed = SizeOf(maxlevel);
   char *ptr = new char[ needed ];
   if (!ptr) return 0;
   new (ptr) TGeoBranchArray(maxlevel);
   ba = reinterpret_cast<TGeoBranchArray*>(ptr);
   ba->SetBit(kBASelfAlloc, kTRUE);
   return ba;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeInstanceAt(size_t maxlevel, void *addr)
{
   // Make an instance of the class which allocates the node array. To be
   // released using ReleaseInstance. If addr is non-zero, the user promised that
   // addr contains at least that many bytes:  size_t needed = SizeOf(maxlevel);
   TGeoBranchArray* ba = 0;
   new (addr) TGeoBranchArray(maxlevel);
   ba = reinterpret_cast<TGeoBranchArray*>(addr);
   ba->SetBit(kBASelfAlloc, kFALSE);
   return ba;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeCopy(const TGeoBranchArray &other)
{
// Make a copy of a branch array at the location (if indicated)
   TGeoBranchArray *copy = 0;
   size_t needed = SizeOf(other.fMaxLevel);
   char *ptr = new char[ needed ];
   if (!ptr) return 0;
   new (ptr) TGeoBranchArray(other.fMaxLevel);
   copy = reinterpret_cast<TGeoBranchArray*>(ptr);
   copy->SetBit(kBASelfAlloc, kTRUE);
   copy->fLevel = other.fLevel;
   copy->fMatrix = other.fMatrix;
   if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
   return copy;
}

//______________________________________________________________________________
TGeoBranchArray * TGeoBranchArray::MakeCopyAt(const TGeoBranchArray &other, void *addr)
{
   // Make a copy of a branch array at the location (if indicated)
   TGeoBranchArray *copy = 0;
   new (addr) TGeoBranchArray(other.fMaxLevel);
   copy = reinterpret_cast<TGeoBranchArray*>(addr);
   copy->SetBit(kBASelfAlloc, kFALSE);
   copy->fLevel = other.fLevel;
   copy->fMatrix = other.fMatrix;
   if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
   return copy;
}

//______________________________________________________________________________
void TGeoBranchArray::CopyTo(TGeoBranchArray *dest)
{
// Raw memcpy of the branch array content to an existing destination.
   memcpy(dest->DataStart(), DataStart(), DataSize());
   dest->fArray = &(dest->fRealArray[0]);
}

//______________________________________________________________________________
void TGeoBranchArray::ReleaseInstance(TGeoBranchArray *obj)
{
// Releases the space allocated for the object
   obj->~TGeoBranchArray();
   if (obj->TestBit(kBASelfAlloc)) delete [] (char*)obj;
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateArray(size_t nobj)
{
// Updates the internal addresses for n contiguous objects which have the same
// fMaxLevel
// Updates the internal addresses for n contiguous objects which have the same fMaxLevel
   size_t needed = SizeOf();
//   char *where = &fArray;
//   for (size_t i=0; i<nobj; ++i, where += needed) {
//      TGeoNode ***array =  reinterpret_cast<TGeoNode***>(where);
//      *array = ((void**)where)+1;
//   }
   char *where = reinterpret_cast<char*>(this);
   for (size_t i=0; i<nobj; ++i, where += needed) {
      TGeoBranchArray *obj = reinterpret_cast<TGeoBranchArray*>(where);
      obj->fArray = &(obj->fRealArray[0]);
   }
}

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray&  other)
                :TObject(other),
                 fLevel(other.fLevel),
                 fMaxLevel(other.fMaxLevel),
                 fMatrix(other.fMatrix),
                 fArray(NULL)
{
// Copy constructor. Not callable anymore. Use TGeoBranchArray::MakeCopy instead
   if (fMaxLevel) {
      fArray = new TGeoNode*[fMaxLevel];
      if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
   }
}

//______________________________________________________________________________
TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
{
// Assignment. Not valid anymore. Use TGeoBranchArray::MakeCopy instead
   if (&other == this) return *this;
//   TThread::Lock();
//   TObject::operator=(other);
   fLevel = other.fLevel;
   fMatrix.CopyFrom(&other.fMatrix);
   if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
//   SetBit(other.TestBit(kBASelfAlloc));
//   TThread::UnLock();
   return *this;
}

//______________________________________________________________________________
void TGeoBranchArray::AddLevel(Int_t dindex)
{
// Add and extra daughter to the current path array. No validity check performed !
   if (fLevel<0) {
      Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
      return;
   }
   if (fLevel>fMaxLevel) {
      Fatal("AddLevel", "Max level = %d reached\n", fMaxLevel);
      return;
   }
   fLevel++;
/*
   if (fLevel+1>fMaxLevel) {
      TGeoNode **array = new TGeoNode*[fLevel+1];
      memcpy(array, fArray, fLevel*sizeof(TGeoNode*));
      delete [] fArray;
      fArray = array;
   }
*/
   fArray[fLevel] = fArray[fLevel-1]->GetVolume()->GetNode(dindex);
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value==0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
{
// Not equal operator.
   Int_t value = Compare(&other);
   if (value!=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
{
// Binary search in an array of n pointers to branch arrays, to locate value.
// Returns element index or index of nearest element smaller than value
   Long64_t nabove, nbelow, middle;
   const TGeoBranchArray *pind;
   nabove = n+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      pind = array[middle-1];
      if (*value == *pind) return middle-1;
      if (*value  < *pind) nabove = middle;
      else                          nbelow = middle;
   }
   return nbelow-1;
}

//______________________________________________________________________________
Int_t TGeoBranchArray::Compare(const TObject *obj) const
{
// Compare with other object of same type. Returns -1 if this is smaller (first
// smaller array value prevails), 0 if equal (size and values) and 1 if this is
// larger.
   Int_t i;
   TGeoBranchArray *other = (TGeoBranchArray*)obj;
   Int_t otherLevel = other->GetLevel();
   Int_t maxLevel = TMath::Min(fLevel, otherLevel);
   TGeoNode **otherArray = other->GetArray();
   for (i=0; i<maxLevel+1; i++) {
      if (fArray[i]==otherArray[i]) continue;
      if ((Long64_t)fArray[i]<(Long64_t)otherArray[i]) return -1;
      return 1;
   }
   if (fLevel==otherLevel) return 0;
   if (fLevel<otherLevel) return -1;
   return 1;
}

//______________________________________________________________________________
void TGeoBranchArray::CleanMatrix()
{
// Garbage collect the stored matrix.
}

//______________________________________________________________________________
void TGeoBranchArray::Init(TGeoNode **branch, TGeoMatrix *global, Int_t level)
{
// Init the branch array from an array of nodes, the global matrix for the path and
// the level.
   fMatrix.CopyFrom(global);
   if (level>fMaxLevel) {
      Fatal("Init", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
      return;
   }
   fLevel = level;
   memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
}

//______________________________________________________________________________
void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
{
// Init the branch array from current navigator state.
   TGeoNodeCache *cache = nav->GetCache();
   const TGeoNode **branch = (const TGeoNode**)cache->GetBranch();
   Int_t level = cache->GetLevel();
   fMatrix.CopyFrom(cache->GetCurrentMatrix());
   if (level>fMaxLevel) {
      Fatal("InitFromNavigator", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
      return;
   }
   fLevel = level;
   memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
   if (nav->IsOutside()) fLevel = -1;
}

//______________________________________________________________________________
void TGeoBranchArray::GetPath(TString &path) const
{
// Fill path pointed by the array.
   path = "";
   if (!fArray || !fArray[0]) return;
   for (Int_t i=0; i<fLevel+1; i++) {
      path += "/";
      path += fArray[i]->GetName();
   }
}

//______________________________________________________________________________
void TGeoBranchArray::Print(Option_t *) const
{
// Print branch information
   TString path;
   GetPath(path);
   printf("branch:    %s\n", path.Data());
}

//______________________________________________________________________________
void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
{
// Sorting of an array of branch array pointers.
   for (Int_t i=0; i<n; i++) index[i] = i;
   if (down)
      std::sort(index, index + n, compareBAdesc(array));
   else
      std::sort(index, index + n, compareBAasc(array));
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
{
// Update the navigator to reflect the branch.
//   nav->CdTop();
   if (fLevel<0) {nav->SetOutside(kTRUE); return;}
   Int_t matchlev = 0;
   Int_t navlev = nav->GetLevel();
   Int_t i;
   Int_t maxlev = TMath::Min(fLevel, navlev);
   for (i=1; i<maxlev+1; ++i) {
     if (fArray[i] != nav->GetMother(navlev-i)) break;
     matchlev++;
   }
   // Go to matching level
   for (i=0; i<navlev-matchlev; i++) nav->CdUp();
   for (i=matchlev+1; i<fLevel+1; i++) nav->CdDown(fArray[i]);
}
<|endoftext|>


<commit_before>#include "cappuccino.h"

int main(int argc, char *argv[]) {
	Cappuccino::Cappuccino(argc, argv);
	Cappuccino::add_static_root("public");
	Cappuccino::add_view_root("html");

	Cappuccino::add_route("/", [](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.file("index.html")
					.build();
	});

	Cappuccino::add_route("/rize", [](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.text("Hello world!")
					.build();
	});

	Cappuccino::add_route("/sharo",[&](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.header_param("Content-type","json")
					.replace("name",req->get("name"))
					.replace("value",req->get("value"))
					.file("sample.json")
					.build();
	});

	Cappuccino::add_route("/cocoa",[&](Cappuccino::Request* req) -> Cappuccino::Response{
		if(req->method() == Cappuccino::Request::POST){
			return Cappuccino::ResponseBuilder(req)
						.status(200,"OK")
						.replace("@order",req->post("order"))
						.file("cocoa.html")
						.build();
		}else{
			return Cappuccino::ResponseBuilder(req)
						.status(200,"OK")
						.replace("@order","コーヒー")
						.file("cocoa.html")
						.build();
		}
	});

#ifndef TEST
	Cappuccino::run();
#endif

	return 0;
}<commit_msg>[Add] sample applys<commit_after>#include "cappuccino.h"

int main(int argc, char *argv[]) {
	Cappuccino::Cappuccino(argc, argv);
	Cappuccino::add_static_root("public");
	Cappuccino::add_view_root("html");

	Cappuccino::add_route("/", [](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.file(Cappuccino::FileLoader("index.html"))
					.build();
	});

	Cappuccino::add_route("/rize", [](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.text("Hello world!")
					.build();
	});

	Cappuccino::add_route("/sharo",[&](Cappuccino::Request* req) -> Cappuccino::Response{
		return Cappuccino::ResponseBuilder(req)
					.status(200,"OK")
					.header_param("Content-type","json")
					.file( Cappuccino::FileLoader("sample.json")
							.replace("name",req->get("name"))
							.replace("value",req->get("value"))
					)
					.build();
	});

	Cappuccino::add_route("/cocoa",[&](Cappuccino::Request* req) -> Cappuccino::Response{
		if(req->method() == Cappuccino::Request::POST){
			return Cappuccino::ResponseBuilder(req)
						.status(200,"OK")
						.file(Cappuccino::FileLoader("cocoa.html")
							.replace("@order",req->post("order"))
						)
						.build();
		}else{
			return Cappuccino::ResponseBuilder(req)
						.status(200,"OK")
						.file(Cappuccino::FileLoader("cocoa.html")
							.replace("@order","コーヒー")
						)
						.build();
		}
	});

#ifndef TEST
	Cappuccino::run();
#endif

	return 0;
}<|endoftext|>


<commit_before>// Copyright (c) 2011 - 2017, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/diagnostics/AsyncProfiler.h>

#include <stingraykit/function/bind.h>
#include <stingraykit/thread/TimedCancellationToken.h>
#include <stingraykit/time/TimeEngine.h>

namespace stingray
{

	namespace
	{

		TimeDuration GetMonotonic()
		{ return TimeDuration::FromMicroseconds(TimeEngine::GetMonotonicMicroseconds()); }

		std::string DeduceCurrentThreadName()
		{
			if (const IThreadInfoPtr threadInfo = Thread::GetCurrentThreadInfo())
				return threadInfo->GetName();
			return "__undefined__";
		}

	}

	AsyncProfiler::SessionImpl::SessionImpl(const char* name)
		:	_name(name),
			_threadName(DeduceCurrentThreadName()),
			_startTime(GetMonotonic())
	{ }

	AsyncProfiler::SessionImpl::SessionImpl(const optional<NameGetterFunc>& nameGetter)
		:	_name(null),
			_nameGetter(nameGetter),
			_threadName(DeduceCurrentThreadName()),
			_startTime(GetMonotonic())
	{ }

	STINGRAYKIT_DEFINE_NAMED_LOGGER(AsyncProfiler::Session);

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const char* name, TimeDuration threshold)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(name),
			_threshold(threshold),
			_impl(_nameHolder.Get())
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const std::string& name, TimeDuration threshold)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(name),
			_threshold(threshold),
			_impl(_nameHolder.Get())
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const NameGetterFunc& nameGetter, TimeDuration threshold, const NameGetterTag&)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(null),
			_threshold(threshold),
			_impl(nameGetter)
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::~Session()
	{
		STINGRAYKIT_TRY("Can't remove session from profiler", _asyncProfiler->RemoveSession(_impl));

		try
		{
			const TimeDuration duration = GetMonotonic() - _impl.GetStartTime();
			if (duration > _threshold)
				s_logger.Warning() << _impl.GetName() << " took " << duration;
		}
		catch (const std::exception& ex)
		{ s_logger.Error() << "Can't report total execution time: " << ex; }
	}

	STINGRAYKIT_DEFINE_NAMED_LOGGER(AsyncProfiler);

	AsyncProfiler::AsyncProfiler(const std::string& threadName)
		:	_timeout(TimeDuration::FromSeconds(30)),
			_thread(ThreadEngine::BeginThread(bind(&AsyncProfiler::ThreadFunc, this, _1), threadName))
	{ }

	void AsyncProfiler::ThreadFunc(const ICancellationToken& token)
	{
		MutexLock l(_mutex);
		while (token)
		{
			if (_sessions.empty())
			{
				_condition.Wait(_mutex, token);
				continue;
			}

			SessionImpl& top = *_sessions.begin();

			const TimeDuration timeNow = GetMonotonic();
			if (timeNow < top.GetAbsoluteTimeout())
			{
				_condition.Wait(_mutex, TimedCancellationToken(top.GetAbsoluteTimeout() - timeNow));
				continue;
			}

			_sessions.erase(top);
			top.SetAbsoluteTimeout(GetMonotonic() + _timeout);
			_sessions.push_back(top);

			// copy all necessary data before releasing mutex
			const std::string name(top.GetName());
			const std::string tname(top.GetThreadName());
			const TimeDuration startTime = top.GetStartTime();
			const std::string backtrace(top.GetBacktrace());

			MutexUnlock ul(l);
			s_logger.Error() << "Task " << name << " in thread " << tname << " is being executed for more than " << (timeNow - startTime) << " invoked from: " << backtrace;
		}
	}

	void AsyncProfiler::AddSession(SessionImpl& session)
	{
		MutexLock l(_mutex);
		session.SetAbsoluteTimeout(GetMonotonic() + _timeout);
		_sessions.push_back(session);
		if (&*_sessions.begin() == &session)
			_condition.Broadcast();
	}

	void AsyncProfiler::RemoveSession(SessionImpl& session)
	{
		MutexLock l(_mutex);
		if (&*_sessions.begin() == &session)
			_condition.Broadcast();
		_sessions.erase(session);
	}

}
<commit_msg>AsyncProfiler: but use current thread name from TLS data, not from thread info<commit_after>// Copyright (c) 2011 - 2017, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/diagnostics/AsyncProfiler.h>

#include <stingraykit/function/bind.h>
#include <stingraykit/thread/TimedCancellationToken.h>
#include <stingraykit/time/TimeEngine.h>

namespace stingray
{

	namespace
	{

		TimeDuration GetMonotonic()
		{ return TimeDuration::FromMicroseconds(TimeEngine::GetMonotonicMicroseconds()); }

	}

	AsyncProfiler::SessionImpl::SessionImpl(const char* name)
		:	_name(name),
			_threadName(Thread::GetCurrentThreadName().empty() ? "__undefined__" : Thread::GetCurrentThreadName()),
			_startTime(GetMonotonic())
	{ }

	AsyncProfiler::SessionImpl::SessionImpl(const optional<NameGetterFunc>& nameGetter)
		:	_name(null),
			_nameGetter(nameGetter),
			_threadName(Thread::GetCurrentThreadName().empty() ? "__undefined__" : Thread::GetCurrentThreadName()),
			_startTime(GetMonotonic())
	{ }

	STINGRAYKIT_DEFINE_NAMED_LOGGER(AsyncProfiler::Session);

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const char* name, TimeDuration threshold)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(name),
			_threshold(threshold),
			_impl(_nameHolder.Get())
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const std::string& name, TimeDuration threshold)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(name),
			_threshold(threshold),
			_impl(_nameHolder.Get())
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::Session(const AsyncProfilerPtr& asyncProfiler, const NameGetterFunc& nameGetter, TimeDuration threshold, const NameGetterTag&)
		:	_asyncProfiler(asyncProfiler),
			_nameHolder(null),
			_threshold(threshold),
			_impl(nameGetter)
	{ _asyncProfiler->AddSession(_impl); }

	AsyncProfiler::Session::~Session()
	{
		STINGRAYKIT_TRY("Can't remove session from profiler", _asyncProfiler->RemoveSession(_impl));

		try
		{
			const TimeDuration duration = GetMonotonic() - _impl.GetStartTime();
			if (duration > _threshold)
				s_logger.Warning() << _impl.GetName() << " took " << duration;
		}
		catch (const std::exception& ex)
		{ s_logger.Error() << "Can't report total execution time: " << ex; }
	}

	STINGRAYKIT_DEFINE_NAMED_LOGGER(AsyncProfiler);

	AsyncProfiler::AsyncProfiler(const std::string& threadName)
		:	_timeout(TimeDuration::FromSeconds(30)),
			_thread(ThreadEngine::BeginThread(bind(&AsyncProfiler::ThreadFunc, this, _1), threadName))
	{ }

	void AsyncProfiler::ThreadFunc(const ICancellationToken& token)
	{
		MutexLock l(_mutex);
		while (token)
		{
			if (_sessions.empty())
			{
				_condition.Wait(_mutex, token);
				continue;
			}

			SessionImpl& top = *_sessions.begin();

			const TimeDuration timeNow = GetMonotonic();
			if (timeNow < top.GetAbsoluteTimeout())
			{
				_condition.Wait(_mutex, TimedCancellationToken(top.GetAbsoluteTimeout() - timeNow));
				continue;
			}

			_sessions.erase(top);
			top.SetAbsoluteTimeout(GetMonotonic() + _timeout);
			_sessions.push_back(top);

			// copy all necessary data before releasing mutex
			const std::string name(top.GetName());
			const std::string tname(top.GetThreadName());
			const TimeDuration startTime = top.GetStartTime();
			const std::string backtrace(top.GetBacktrace());

			MutexUnlock ul(l);
			s_logger.Error() << "Task " << name << " in thread " << tname << " is being executed for more than " << (timeNow - startTime) << " invoked from: " << backtrace;
		}
	}

	void AsyncProfiler::AddSession(SessionImpl& session)
	{
		MutexLock l(_mutex);
		session.SetAbsoluteTimeout(GetMonotonic() + _timeout);
		_sessions.push_back(session);
		if (&*_sessions.begin() == &session)
			_condition.Broadcast();
	}

	void AsyncProfiler::RemoveSession(SessionImpl& session)
	{
		MutexLock l(_mutex);
		if (&*_sessions.begin() == &session)
			_condition.Broadcast();
		_sessions.erase(session);
	}

}
<|endoftext|>


<commit_before>/*
  Copyright 2007 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <jsobj.h>
#include <jsfun.h>
#include "converter.h"
#include "native_js_wrapper.h"
//#include "js_native_wrapper.h"

namespace ggadget {

static JSBool ConvertJSToNativeVoid(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  *native_val = Variant();
  return JS_TRUE;
}

static JSBool ConvertJSToNativeBool(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  JSBool value;
  if (!JS_ValueToBoolean(cx, js_val, &value))
    return JS_FALSE;

  *native_val = Variant(static_cast<bool>(value));
  return JS_TRUE;
}

static JSBool ConvertJSToNativeInt(JSContext *cx, jsval js_val,
                                   Variant *native_val) {
  JSBool result = JS_FALSE;
  if (JSVAL_IS_INT(js_val)) {
    int32 int_val;
    result = JS_ValueToECMAInt32(cx, js_val, &int_val);
    if (result)
      *native_val = Variant(int_val);
  } else {
    jsdouble double_val;
    result = JS_ValueToNumber(cx, js_val, &double_val);
    if (result)
      *native_val = Variant(static_cast<int64>(double_val));
  }
  return result;
}

static JSBool ConvertJSToNativeDouble(JSContext *cx, jsval js_val,
                                      Variant *native_val) {
  double double_val;
  JSBool result = JS_ValueToNumber(cx, js_val, &double_val);
  if (result)
    *native_val = Variant(double_val);
  return result;
}

static JSBool ConvertJSToNativeString(JSContext *cx, jsval js_val,
                                      Variant *native_val) {
  JSBool result = JS_FALSE;
  if (JSVAL_IS_NULL(js_val) || JSVAL_IS_VOID(js_val)) {
    // Result is a blank string instead of a string containing "null", etc.
    result = JS_TRUE;
    *native_val = Variant(std::string());
  } else {
    JSString *js_string = JS_ValueToString(cx, js_val);
    if (js_string) {
      // TODO(wangxianzhu): Convert to UTF8.
      char *bytes = JS_GetStringBytes(js_string);
      if (bytes) {
        result = JS_TRUE;
        *native_val = Variant(std::string(bytes));
      }
    }
  }
  return result;
}

static JSBool ConvertJSToScriptable(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  JSBool result = JS_TRUE;
  ScriptableInterface *scriptable;
  if (JSVAL_IS_NULL(js_val) || JSVAL_IS_VOID(js_val)) {
    scriptable = NULL;
  /*} else if (JSVAL_IS_STRING(js_val)) {

    // Sometimew we allow a string containing a function definition in place
    // of an IDispatch callback object.
    // Any method call to the object will be delegated to this function.
    result = JSStringNativeWrapper::Wrap(cx,
                                         JSVAL_TO_STRING(js_val),
                                         &com_val->pdispVal);
    // JS_CompileFunction(cx,
  } else if (JSVAL_IS_FUNCTION(cx, js_val)) {
    // Sometimes we allow a function in place of an IDispatch callback object.
    // Any method call to the object will be delegated to this function.
    result = JSFunctionDispatchWrapper::Wrap(cx,
                                             JS_ValueToFunction(cx, js_val),
                                             &com_val->pdispVal);
    */
  } else if (JSVAL_IS_OBJECT(js_val)) {
    // This object may be a JS wrapped native object.
    // If it is not, NativeJSWrapper::Unwrap simply fails.
    // We don't support wrapping JS object into native object now.
    result = NativeJSWrapper::Unwrap(cx, JSVAL_TO_OBJECT(js_val), &scriptable);
  } else {
    result = JS_FALSE;
  }

  if (result)
    *native_val = Variant(scriptable);
  return result;
}

static JSBool ConvertJSToSlot(JSContext *cx, jsval js_val,
                              Variant *native_val) {
  // TODO: implement it.
  return JS_FALSE;
}

static JSBool ConvertJSToIntOrString(JSContext *cx, jsval js_val,
                                     Variant *native_val) {
  Variant temp;
  if (ConvertJSToNativeInt(cx, js_val, &temp)) {
    *native_val = Variant(
        CreateIntOrString(static_cast<int>(temp.v.int64_value)));
    return JS_TRUE;
  }

  if (ConvertJSToNativeString(cx, js_val, &temp)) {
    *native_val = Variant(CreateIntOrString(temp.v.string_value));
    return JS_TRUE;
  }

  return JS_FALSE;
}

typedef JSBool (*ConvertJSToNativeFunc)(JSContext *cx, jsval js_val,
                                        Variant *native_val);
static const ConvertJSToNativeFunc kConvertJSToNativeFuncs[] = {
  ConvertJSToNativeVoid,
  ConvertJSToNativeBool,
  ConvertJSToNativeInt,
  ConvertJSToNativeDouble,
  ConvertJSToNativeString,
  ConvertJSToScriptable,
  ConvertJSToSlot,
  ConvertJSToIntOrString,
};

JSBool ConvertJSToNative(JSContext *cx, Variant::Type type,
                         jsval js_val, Variant *native_val) {
  if (type >= Variant::TYPE_VOID && type <= Variant::TYPE_INT_OR_STRING)
    return kConvertJSToNativeFuncs[type](cx, js_val, native_val);
  else
    return JS_FALSE;
}

JSBool ConvertJSToNativeVariant(JSContext *cx, jsval js_val,
                                Variant *native_val) {
  if (JSVAL_IS_VOID(js_val) || JSVAL_IS_NULL(js_val))
    return ConvertJSToNativeVoid(cx, js_val, native_val);
  if (JSVAL_IS_BOOLEAN(js_val))
    return ConvertJSToNativeBool(cx, js_val, native_val);
  if (JSVAL_IS_INT(js_val))
    return ConvertJSToNativeInt(cx, js_val, native_val);
  if (JSVAL_IS_DOUBLE(js_val))
    return ConvertJSToNativeDouble(cx, js_val, native_val);
  if (JSVAL_IS_STRING(js_val))
    return ConvertJSToNativeString(cx, js_val, native_val);
  if (JSVAL_IS_OBJECT(js_val))
    return ConvertJSToScriptable(cx, js_val, native_val);
  return JS_FALSE;
}

static JSBool ConvertNativeToJSVoid(JSContext *cx, Variant native_val,
                                    jsval *js_val) {
  *js_val = JSVAL_VOID;
  return JS_TRUE;
}

static JSBool ConvertNativeToJSBool(JSContext *cx, Variant native_val,
                                    jsval *js_val) {
  *js_val = BOOLEAN_TO_JSVAL(native_val.v.bool_value);
  return JS_TRUE;
}

static JSBool ConvertNativeToJSInt(JSContext *cx, Variant native_val,
                                   jsval *js_val) {
  int64 value = native_val.v.int64_value;
  if (value >= JSVAL_INT_MIN && value <= JSVAL_INT_MAX) {
    *js_val = INT_TO_JSVAL(value);
    return JS_TRUE;
  } else {
    jsdouble *pdouble = JS_NewDouble(cx, native_val.v.int64_value);
    if (pdouble) {
      *js_val = DOUBLE_TO_JSVAL(pdouble);
      return JS_TRUE;
    } else {
      return JS_FALSE;
    }
  }
}

static JSBool ConvertNativeToJSDouble(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  jsdouble *pdouble = JS_NewDouble(cx, native_val.v.double_value);
  if (pdouble) {
    *js_val = DOUBLE_TO_JSVAL(pdouble);
    return JS_TRUE;
  } else {
    return JS_FALSE;
  }
}

static JSBool ConvertNativeToJSString(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  JSBool result = JS_TRUE;
  JSString *js_string = JS_NewStringCopyZ(cx, native_val.v.string_value);
  // TODO(wangxianzhu): Convert UTF8 to jschar.
  if (js_string)
    *js_val = STRING_TO_JSVAL(js_string);
  else
    result = JS_FALSE;
  return result;
}

static JSBool ConvertNativeToJSObject(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  JSBool result = JS_TRUE;
  ScriptableInterface *scriptable = native_val.v.scriptable_value;
  if (!scriptable) {
    *js_val = JSVAL_NULL;
  } else {
    JSObject *js_object = NativeJSWrapper::Wrap(cx, scriptable);
    if (js_object)
      *js_val = OBJECT_TO_JSVAL(js_object);
    else
      result = JS_FALSE;
  }
  return result;
}

static JSBool ConvertNativeToJSFunction(JSContext *cx, Variant native_val,
                                        jsval *js_val) {
  if (native_val.v.slot_value) {
    // TODO: is this useful?
    return JS_FALSE;
  } else {
    *js_val = JSVAL_NULL;
    return JS_TRUE;
  }
}

static JSBool ConvertNativeToJSIntOrString(JSContext *cx, Variant native_val,
                                           jsval *js_val) {
  if (native_val.v.int_or_string_value.type == IntOrString::TYPE_STRING)
    return ConvertNativeToJSString(cx,
        Variant(native_val.v.int_or_string_value.v.string_value), js_val);
  else
    return ConvertNativeToJSInt(cx,
        Variant(native_val.v.int_or_string_value.v.int_value), js_val);
}

typedef JSBool (*ConvertNativeToJSFunc)(JSContext *cx, Variant native_val,
                                        jsval *js_val);
static const ConvertNativeToJSFunc kConvertNativeToJSFuncs[] = {
  ConvertNativeToJSVoid,
  ConvertNativeToJSBool,
  ConvertNativeToJSInt,
  ConvertNativeToJSDouble,
  ConvertNativeToJSString,
  ConvertNativeToJSObject,
  ConvertNativeToJSFunction,
  ConvertNativeToJSIntOrString,
};

JSBool ConvertNativeToJS(JSContext *cx, Variant native_val, jsval *js_val) {
  return kConvertNativeToJSFuncs[native_val.type](cx, native_val, js_val);
}

} // namespace ggadget
<commit_msg>Change "int64" to "int64_t" to make it compiled.<commit_after>/*
  Copyright 2007 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <jsobj.h>
#include <jsfun.h>
#include "converter.h"
#include "native_js_wrapper.h"
//#include "js_native_wrapper.h"

namespace ggadget {

static JSBool ConvertJSToNativeVoid(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  *native_val = Variant();
  return JS_TRUE;
}

static JSBool ConvertJSToNativeBool(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  JSBool value;
  if (!JS_ValueToBoolean(cx, js_val, &value))
    return JS_FALSE;

  *native_val = Variant(static_cast<bool>(value));
  return JS_TRUE;
}

static JSBool ConvertJSToNativeInt(JSContext *cx, jsval js_val,
                                   Variant *native_val) {
  JSBool result = JS_FALSE;
  if (JSVAL_IS_INT(js_val)) {
    int32 int_val;
    result = JS_ValueToECMAInt32(cx, js_val, &int_val);
    if (result)
      *native_val = Variant(int_val);
  } else {
    jsdouble double_val;
    result = JS_ValueToNumber(cx, js_val, &double_val);
    if (result)
      *native_val = Variant(static_cast<int64_t>(double_val));
  }
  return result;
}

static JSBool ConvertJSToNativeDouble(JSContext *cx, jsval js_val,
                                      Variant *native_val) {
  double double_val;
  JSBool result = JS_ValueToNumber(cx, js_val, &double_val);
  if (result)
    *native_val = Variant(double_val);
  return result;
}

static JSBool ConvertJSToNativeString(JSContext *cx, jsval js_val,
                                      Variant *native_val) {
  JSBool result = JS_FALSE;
  if (JSVAL_IS_NULL(js_val) || JSVAL_IS_VOID(js_val)) {
    // Result is a blank string instead of a string containing "null", etc.
    result = JS_TRUE;
    *native_val = Variant(std::string());
  } else {
    JSString *js_string = JS_ValueToString(cx, js_val);
    if (js_string) {
      // TODO(wangxianzhu): Convert to UTF8.
      char *bytes = JS_GetStringBytes(js_string);
      if (bytes) {
        result = JS_TRUE;
        *native_val = Variant(std::string(bytes));
      }
    }
  }
  return result;
}

static JSBool ConvertJSToScriptable(JSContext *cx, jsval js_val,
                                    Variant *native_val) {
  JSBool result = JS_TRUE;
  ScriptableInterface *scriptable;
  if (JSVAL_IS_NULL(js_val) || JSVAL_IS_VOID(js_val)) {
    scriptable = NULL;
  /*} else if (JSVAL_IS_STRING(js_val)) {

    // Sometimew we allow a string containing a function definition in place
    // of an IDispatch callback object.
    // Any method call to the object will be delegated to this function.
    result = JSStringNativeWrapper::Wrap(cx,
                                         JSVAL_TO_STRING(js_val),
                                         &com_val->pdispVal);
    // JS_CompileFunction(cx,
  } else if (JSVAL_IS_FUNCTION(cx, js_val)) {
    // Sometimes we allow a function in place of an IDispatch callback object.
    // Any method call to the object will be delegated to this function.
    result = JSFunctionDispatchWrapper::Wrap(cx,
                                             JS_ValueToFunction(cx, js_val),
                                             &com_val->pdispVal);
    */
  } else if (JSVAL_IS_OBJECT(js_val)) {
    // This object may be a JS wrapped native object.
    // If it is not, NativeJSWrapper::Unwrap simply fails.
    // We don't support wrapping JS object into native object now.
    result = NativeJSWrapper::Unwrap(cx, JSVAL_TO_OBJECT(js_val), &scriptable);
  } else {
    result = JS_FALSE;
  }

  if (result)
    *native_val = Variant(scriptable);
  return result;
}

static JSBool ConvertJSToSlot(JSContext *cx, jsval js_val,
                              Variant *native_val) {
  // TODO: implement it.
  return JS_FALSE;
}

static JSBool ConvertJSToIntOrString(JSContext *cx, jsval js_val,
                                     Variant *native_val) {
  Variant temp;
  if (ConvertJSToNativeInt(cx, js_val, &temp)) {
    *native_val = Variant(
        CreateIntOrString(static_cast<int>(temp.v.int64_value)));
    return JS_TRUE;
  }

  if (ConvertJSToNativeString(cx, js_val, &temp)) {
    *native_val = Variant(CreateIntOrString(temp.v.string_value));
    return JS_TRUE;
  }

  return JS_FALSE;
}

typedef JSBool (*ConvertJSToNativeFunc)(JSContext *cx, jsval js_val,
                                        Variant *native_val);
static const ConvertJSToNativeFunc kConvertJSToNativeFuncs[] = {
  ConvertJSToNativeVoid,
  ConvertJSToNativeBool,
  ConvertJSToNativeInt,
  ConvertJSToNativeDouble,
  ConvertJSToNativeString,
  ConvertJSToScriptable,
  ConvertJSToSlot,
  ConvertJSToIntOrString,
};

JSBool ConvertJSToNative(JSContext *cx, Variant::Type type,
                         jsval js_val, Variant *native_val) {
  if (type >= Variant::TYPE_VOID && type <= Variant::TYPE_INT_OR_STRING)
    return kConvertJSToNativeFuncs[type](cx, js_val, native_val);
  else
    return JS_FALSE;
}

JSBool ConvertJSToNativeVariant(JSContext *cx, jsval js_val,
                                Variant *native_val) {
  if (JSVAL_IS_VOID(js_val) || JSVAL_IS_NULL(js_val))
    return ConvertJSToNativeVoid(cx, js_val, native_val);
  if (JSVAL_IS_BOOLEAN(js_val))
    return ConvertJSToNativeBool(cx, js_val, native_val);
  if (JSVAL_IS_INT(js_val))
    return ConvertJSToNativeInt(cx, js_val, native_val);
  if (JSVAL_IS_DOUBLE(js_val))
    return ConvertJSToNativeDouble(cx, js_val, native_val);
  if (JSVAL_IS_STRING(js_val))
    return ConvertJSToNativeString(cx, js_val, native_val);
  if (JSVAL_IS_OBJECT(js_val))
    return ConvertJSToScriptable(cx, js_val, native_val);
  return JS_FALSE;
}

static JSBool ConvertNativeToJSVoid(JSContext *cx, Variant native_val,
                                    jsval *js_val) {
  *js_val = JSVAL_VOID;
  return JS_TRUE;
}

static JSBool ConvertNativeToJSBool(JSContext *cx, Variant native_val,
                                    jsval *js_val) {
  *js_val = BOOLEAN_TO_JSVAL(native_val.v.bool_value);
  return JS_TRUE;
}

static JSBool ConvertNativeToJSInt(JSContext *cx, Variant native_val,
                                   jsval *js_val) {
  int64_t value = native_val.v.int64_value;
  if (value >= JSVAL_INT_MIN && value <= JSVAL_INT_MAX) {
    *js_val = INT_TO_JSVAL(value);
    return JS_TRUE;
  } else {
    jsdouble *pdouble = JS_NewDouble(cx, native_val.v.int64_value);
    if (pdouble) {
      *js_val = DOUBLE_TO_JSVAL(pdouble);
      return JS_TRUE;
    } else {
      return JS_FALSE;
    }
  }
}

static JSBool ConvertNativeToJSDouble(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  jsdouble *pdouble = JS_NewDouble(cx, native_val.v.double_value);
  if (pdouble) {
    *js_val = DOUBLE_TO_JSVAL(pdouble);
    return JS_TRUE;
  } else {
    return JS_FALSE;
  }
}

static JSBool ConvertNativeToJSString(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  JSBool result = JS_TRUE;
  JSString *js_string = JS_NewStringCopyZ(cx, native_val.v.string_value);
  // TODO(wangxianzhu): Convert UTF8 to jschar.
  if (js_string)
    *js_val = STRING_TO_JSVAL(js_string);
  else
    result = JS_FALSE;
  return result;
}

static JSBool ConvertNativeToJSObject(JSContext *cx, Variant native_val,
                                      jsval *js_val) {
  JSBool result = JS_TRUE;
  ScriptableInterface *scriptable = native_val.v.scriptable_value;
  if (!scriptable) {
    *js_val = JSVAL_NULL;
  } else {
    JSObject *js_object = NativeJSWrapper::Wrap(cx, scriptable);
    if (js_object)
      *js_val = OBJECT_TO_JSVAL(js_object);
    else
      result = JS_FALSE;
  }
  return result;
}

static JSBool ConvertNativeToJSFunction(JSContext *cx, Variant native_val,
                                        jsval *js_val) {
  if (native_val.v.slot_value) {
    // TODO: is this useful?
    return JS_FALSE;
  } else {
    *js_val = JSVAL_NULL;
    return JS_TRUE;
  }
}

static JSBool ConvertNativeToJSIntOrString(JSContext *cx, Variant native_val,
                                           jsval *js_val) {
  if (native_val.v.int_or_string_value.type == IntOrString::TYPE_STRING)
    return ConvertNativeToJSString(cx,
        Variant(native_val.v.int_or_string_value.v.string_value), js_val);
  else
    return ConvertNativeToJSInt(cx,
        Variant(native_val.v.int_or_string_value.v.int_value), js_val);
}

typedef JSBool (*ConvertNativeToJSFunc)(JSContext *cx, Variant native_val,
                                        jsval *js_val);
static const ConvertNativeToJSFunc kConvertNativeToJSFuncs[] = {
  ConvertNativeToJSVoid,
  ConvertNativeToJSBool,
  ConvertNativeToJSInt,
  ConvertNativeToJSDouble,
  ConvertNativeToJSString,
  ConvertNativeToJSObject,
  ConvertNativeToJSFunction,
  ConvertNativeToJSIntOrString,
};

JSBool ConvertNativeToJS(JSContext *cx, Variant native_val, jsval *js_val) {
  return kConvertNativeToJSFuncs[native_val.type](cx, native_val, js_val);
}

} // namespace ggadget
<|endoftext|>


<commit_before>// Copyright (c) 2017-2021 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include "SourceText.h"
#include <cstddef>
#include <iomanip>
#include <sstream>
#include <goost/Source.h>

using namespace std;
using namespace goost;

SourceText::SourceText(const shared_ptr<const Source> &source)
	: source(source)
{
}

string SourceText::asString() const
{
	ostringstream out;
	auto s = source;
	while (true) {
		vector<byte> bytes;
		tie(bytes, s) = s->read(numeric_limits<size_t>::max());
		if (bytes.empty()) {
			break;
		}
		for (const auto &b : bytes) {
			out << hex << setw(2) << setfill('0') << to_integer<unsigned>(b);
		}
	}
	return out.str();
}
<commit_msg>#467: include <limits> for numeric_limits in SourceText<commit_after>// Copyright (c) 2017-2021 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include "SourceText.h"
#include <cstddef>
#include <iomanip>
#include <limits>
#include <sstream>
#include <goost/Source.h>

using namespace std;
using namespace goost;

SourceText::SourceText(const shared_ptr<const Source> &source)
	: source(source)
{
}

string SourceText::asString() const
{
	ostringstream out;
	auto s = source;
	while (true) {
		vector<byte> bytes;
		tie(bytes, s) = s->read(numeric_limits<size_t>::max());
		if (bytes.empty()) {
			break;
		}
		for (const auto &b : bytes) {
			out << hex << setw(2) << setfill('0') << to_integer<unsigned>(b);
		}
	}
	return out.str();
}
<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include "core_configuration.hpp"
#include "file_monitor.hpp"
#include "filesystem.hpp"
#include "grabber_client.hpp"
#include <CoreServices/CoreServices.h>
#include <memory>

class configuration_manager final {
public:
  configuration_manager(const configuration_manager&) = delete;

  configuration_manager(spdlog::logger& logger,
                        grabber_client& grabber_client) : logger_(logger),
                                                          grabber_client_(grabber_client) {
    mkdir(constants::get_configuration_directory(), 0700);

    auto core_configuration_file_path = constants::get_core_configuration_file_path();

    std::vector<std::pair<std::string, std::vector<std::string>>> targets = {
        {constants::get_configuration_directory(), {core_configuration_file_path}},
    };
    file_monitor_ = std::make_unique<file_monitor>(logger_, targets, std::bind(&configuration_manager::reload_core_configuration, this, std::placeholders::_1));

    reload_core_configuration(core_configuration_file_path);
  }

  ~configuration_manager(void) {
    file_monitor_ = nullptr;
  }

private:
  void reload_core_configuration(const std::string& file_path) {
    auto new_ptr = std::make_unique<core_configuration>(logger_, file_path);
    // skip if karabiner.json is broken.
    if (core_configuration_ && !new_ptr->is_loaded()) {
      return;
    }

    core_configuration_ = std::move(new_ptr);
    logger_.info("core_configuration_ was loaded.");

    grabber_client_.clear_simple_modifications();
    for (const auto& pair : core_configuration_->get_current_profile_simple_modifications()) {
      grabber_client_.add_simple_modification(pair.first, pair.second);
    }

    grabber_client_.clear_fn_function_keys();
    for (const auto& pair : core_configuration_->get_current_profile_fn_function_keys()) {
      grabber_client_.add_fn_function_key(pair.first, pair.second);
    }

    grabber_client_.clear_devices();
    for (const auto& tuple : core_configuration_->get_current_profile_devices()) {
      grabber_client_.add_device(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple));
    }
    grabber_client_.complete_devices();
  }

  spdlog::logger& logger_;
  grabber_client& grabber_client_;

  std::unique_ptr<file_monitor> file_monitor_;

  std::unique_ptr<core_configuration> core_configuration_;
};
<commit_msg>use device_configuration_struct<commit_after>#pragma once

#include "constants.hpp"
#include "core_configuration.hpp"
#include "file_monitor.hpp"
#include "filesystem.hpp"
#include "grabber_client.hpp"
#include <CoreServices/CoreServices.h>
#include <memory>

class configuration_manager final {
public:
  configuration_manager(const configuration_manager&) = delete;

  configuration_manager(spdlog::logger& logger,
                        grabber_client& grabber_client) : logger_(logger),
                                                          grabber_client_(grabber_client) {
    mkdir(constants::get_configuration_directory(), 0700);

    auto core_configuration_file_path = constants::get_core_configuration_file_path();

    std::vector<std::pair<std::string, std::vector<std::string>>> targets = {
        {constants::get_configuration_directory(), {core_configuration_file_path}},
    };
    file_monitor_ = std::make_unique<file_monitor>(logger_, targets, std::bind(&configuration_manager::reload_core_configuration, this, std::placeholders::_1));

    reload_core_configuration(core_configuration_file_path);
  }

  ~configuration_manager(void) {
    file_monitor_ = nullptr;
  }

private:
  void reload_core_configuration(const std::string& file_path) {
    auto new_ptr = std::make_unique<core_configuration>(logger_, file_path);
    // skip if karabiner.json is broken.
    if (core_configuration_ && !new_ptr->is_loaded()) {
      return;
    }

    core_configuration_ = std::move(new_ptr);
    logger_.info("core_configuration_ was loaded.");

    grabber_client_.clear_simple_modifications();
    for (const auto& pair : core_configuration_->get_current_profile_simple_modifications()) {
      grabber_client_.add_simple_modification(pair.first, pair.second);
    }

    grabber_client_.clear_fn_function_keys();
    for (const auto& pair : core_configuration_->get_current_profile_fn_function_keys()) {
      grabber_client_.add_fn_function_key(pair.first, pair.second);
    }

    grabber_client_.clear_devices();
    for (const auto& pair : core_configuration_->get_current_profile_devices()) {
      grabber_client_.add_device(pair.first, pair.second);
    }
    grabber_client_.complete_devices();
  }

  spdlog::logger& logger_;
  grabber_client& grabber_client_;

  std::unique_ptr<file_monitor> file_monitor_;

  std::unique_ptr<core_configuration> core_configuration_;
};
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_sbe_chiplet_reset.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_sbe_chiplet_reset.H
///
/// @brief Steps:-
///     1) Identify Partical good chiplet and configure Multicasting register
///     2) Similar way, Configure hang pulse counter for Nest/MC/OBus/XBus/PCIe
///     3) Similar way,  set fence for Nest and MC chiplet
///     4) Similar way,  Reset sys.config and OPCG setting for Nest and MC chiplet in sync mode
///
/// Done
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V. Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Brian Silver <bsilver@us.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SBE_CHIPLET_RESET_H_
#define _P9_SBE_CHIPLET_RESET_H_

#include <fapi2.H>

namespace p9SbeChipletReset
{
enum P9_SBE_CHIPLET_RESET_Public_Constants
{
    MCGR_CNFG_SETTING_EMPTY  = 0xFC00000000000000ull,
    MCGR_CNFG_SETTING_GROUP0 = 0xE0001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP1 = 0xE4001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP2 = 0xE8001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP3 = 0xEC001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP4 = 0xF0001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP5 = 0xF4001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP6 = 0xF8001C0000000000ull,
    NET_CNTL0_HW_INIT_VALUE = 0x7C06222000000000ull,
    NET_CNTL0_HW_INIT_VALUE_FOR_DD1 = 0x7C16222000000000ull,
    HANG_PULSE_0X10 = 0x10,
    HANG_PULSE_0X0F = 0x0F,
    HANG_PULSE_0X06 = 0x06,
    HANG_PULSE_0X17 = 0x17,
    HANG_PULSE_0X18 = 0x18,
    HANG_PULSE_0X22 = 0x22,
    HANG_PULSE_0X23 = 0x23,
    HANG_PULSE_0X13 = 0x13,
    HANG_PULSE_0X03 = 0x03,
    OPCG_ALIGN_SETTING = 0x5000000000003020ull,
    INOP_ALIGN_SETTING_0X5 = 0x5,
    OPCG_WAIT_CYCLE_0X020 = 0x020,
    SCAN_RATIO_0X3 = 0x3,
    SYNC_PULSE_DELAY_0X0 = 0X00,
    SYNC_CONFIG_DEFAULT = 0X0000000000000000,
    HANG_PULSE_0X00 = 0x00,
    HANG_PULSE_0X01 = 0x01,
    HANG_PULSE_0X04 = 0x04,
    HANG_PULSE_0X1A = 0x1A,
    NET_CNTL1_HW_INIT_VALUE = 0x7200000000000000ull,
    REGIONS_EXCEPT_VITAL = 0x7FF,
    SCAN_TYPES_EXCEPT_TIME_GPTR_REPR = 0xDCF,
    SCAN_TYPES_TIME_GPTR_REPR = 0x230,
    SCAN_RATIO_0X0 = 0x0,
    SYNC_CONFIG_4TO1 = 0X0800000000000000,
    HW_NS_DELAY = 200000, // unit is nano seconds
    SIM_CYCLE_DELAY = 10000, // unit is cycles
    HANG_PULSE_0X12 = 0x12,
    HANG_PULSE_0X1C = 0x1C,
    HANG_PULSE_0X08 = 0x08
};
}

typedef fapi2::ReturnCode (*p9_sbe_chiplet_reset_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Identify all good chiplets excluding EQ/EC
///  -- All chiplets will be reset and PLLs started
///  -- Partial bad - All nest Chiplets must be good, MC, IO can be partial bad
/// Setup multicast groups for all chiplets
///  -- Can't use the multicast for all non-nest chiplets
///  -- This is intended to be the eventual product setting
///  -- This includes the core/cache chiplets
/// For all good chiplets excluding EQ/EC
/// -- Setup Chiplet GP3 regs
///  -- Reset to default state
///  -- Set chiplet enable on all all good chiplets excluding EQ/EC
/// For all enabled chiplets excluding EQ/EC/Buses
///  -- Start vital clocks and release endpoint reset
///  -- PCB Slave error register Reset
///
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_sbe_chiplet_reset(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<commit_msg>p9_sbe_chiplet_reset: Revert NX_1 hang pulse back to 34s<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_sbe_chiplet_reset.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_sbe_chiplet_reset.H
///
/// @brief Steps:-
///     1) Identify Partical good chiplet and configure Multicasting register
///     2) Similar way, Configure hang pulse counter for Nest/MC/OBus/XBus/PCIe
///     3) Similar way,  set fence for Nest and MC chiplet
///     4) Similar way,  Reset sys.config and OPCG setting for Nest and MC chiplet in sync mode
///
/// Done
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V. Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Brian Silver <bsilver@us.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SBE_CHIPLET_RESET_H_
#define _P9_SBE_CHIPLET_RESET_H_

#include <fapi2.H>

namespace p9SbeChipletReset
{
enum P9_SBE_CHIPLET_RESET_Public_Constants
{
    MCGR_CNFG_SETTING_EMPTY  = 0xFC00000000000000ull,
    MCGR_CNFG_SETTING_GROUP0 = 0xE0001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP1 = 0xE4001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP2 = 0xE8001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP3 = 0xEC001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP4 = 0xF0001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP5 = 0xF4001C0000000000ull,
    MCGR_CNFG_SETTING_GROUP6 = 0xF8001C0000000000ull,
    NET_CNTL0_HW_INIT_VALUE = 0x7C06222000000000ull,
    NET_CNTL0_HW_INIT_VALUE_FOR_DD1 = 0x7C16222000000000ull,
    HANG_PULSE_0X10 = 0x10,
    HANG_PULSE_0X0F = 0x0F,
    HANG_PULSE_0X06 = 0x06,
    HANG_PULSE_0X17 = 0x17,
    HANG_PULSE_0X18 = 0x18,
    HANG_PULSE_0X22 = 0x22,
    HANG_PULSE_0X13 = 0x13,
    HANG_PULSE_0X03 = 0x03,
    OPCG_ALIGN_SETTING = 0x5000000000003020ull,
    INOP_ALIGN_SETTING_0X5 = 0x5,
    OPCG_WAIT_CYCLE_0X020 = 0x020,
    SCAN_RATIO_0X3 = 0x3,
    SYNC_PULSE_DELAY_0X0 = 0X00,
    SYNC_CONFIG_DEFAULT = 0X0000000000000000,
    HANG_PULSE_0X00 = 0x00,
    HANG_PULSE_0X01 = 0x01,
    HANG_PULSE_0X04 = 0x04,
    HANG_PULSE_0X1A = 0x1A,
    NET_CNTL1_HW_INIT_VALUE = 0x7200000000000000ull,
    REGIONS_EXCEPT_VITAL = 0x7FF,
    SCAN_TYPES_EXCEPT_TIME_GPTR_REPR = 0xDCF,
    SCAN_TYPES_TIME_GPTR_REPR = 0x230,
    SCAN_RATIO_0X0 = 0x0,
    SYNC_CONFIG_4TO1 = 0X0800000000000000,
    HW_NS_DELAY = 200000, // unit is nano seconds
    SIM_CYCLE_DELAY = 10000, // unit is cycles
    HANG_PULSE_0X12 = 0x12,
    HANG_PULSE_0X1C = 0x1C,
    HANG_PULSE_0X08 = 0x08
};
}

typedef fapi2::ReturnCode (*p9_sbe_chiplet_reset_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Identify all good chiplets excluding EQ/EC
///  -- All chiplets will be reset and PLLs started
///  -- Partial bad - All nest Chiplets must be good, MC, IO can be partial bad
/// Setup multicast groups for all chiplets
///  -- Can't use the multicast for all non-nest chiplets
///  -- This is intended to be the eventual product setting
///  -- This includes the core/cache chiplets
/// For all good chiplets excluding EQ/EC
/// -- Setup Chiplet GP3 regs
///  -- Reset to default state
///  -- Set chiplet enable on all all good chiplets excluding EQ/EC
/// For all enabled chiplets excluding EQ/EC/Buses
///  -- Start vital clocks and release endpoint reset
///  -- PCB Slave error register Reset
///
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_sbe_chiplet_reset(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <mist/mist.h>

int main( int argc, char *argv[] )
{
	using namespace std;

	typedef size_t size_type;
	size_type i, j;

	{
		mist::array1< size_type > a( 2, 1.0 ), b( 1, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) <<endl;
		cout << b << endl;
	}

	{
		mist::array2< size_type > a( 2, 2, 1.0, 1.0 ), b( 3, 3, 0.5, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) <<endl;
		cout << b << endl;
	}

	{
		mist::array3< size_type > a( 2, 2, 2, 1.0, 1.0, 1.0 ), b( 3, 3, 3, 0.5, 0.5, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) << ", " << a.reso3( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) << ", " << b.reso3( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) << ", " << a.reso3( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) << ", " << b.reso3( ) <<endl;
		cout << b << endl;
	}

	return( 0 );
}
<commit_msg>改行コードの属性を変更．<commit_after>#include <iostream>
#include <mist/mist.h>

int main( int argc, char *argv[] )
{
	using namespace std;

	typedef size_t size_type;
	size_type i, j;

	{
		mist::array1< size_type > a( 2, 1.0 ), b( 1, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) <<endl;
		cout << b << endl;
	}

	{
		mist::array2< size_type > a( 2, 2, 1.0, 1.0 ), b( 3, 3, 0.5, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) <<endl;
		cout << b << endl;
	}

	{
		mist::array3< size_type > a( 2, 2, 2, 1.0, 1.0, 1.0 ), b( 3, 3, 3, 0.5, 0.5, 0.5 );
		for( i = 0 ; i < a.size( ) ; i++ )
		{
			a[ i ] = i;
		}
		for( j = 0 ; j < b.size( ) ; j++, i++ )
		{
			b[ j ] = i;
		}
		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) << ", " << a.reso3( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) << ", " << b.reso3( ) <<endl;
		cout << b << endl;

		a.swap( b );

		cout << "a: " << a.reso1( ) << ", " << a.reso2( ) << ", " << a.reso3( ) <<endl;
		cout << a;
		cout << "-----------------------" << endl;
		cout << "b: " << b.reso1( ) << ", " << b.reso2( ) << ", " << b.reso3( ) <<endl;
		cout << b << endl;
	}

	return( 0 );
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"
#include <Utils/ResponseUtils.h>
#include <Utils/TestUtils.h>

#include <hspp/Tasks/BasicTasks/CombatTask.h>
#include <hspp/Tasks/BasicTasks/InitAttackCountTask.h>

using namespace Hearthstonepp;

class CombatTester
{
 public:
    CombatTester()
        : m_gen(CardClass::DRUID, CardClass::ROGUE),
          m_agent(std::move(m_gen.player1), std::move(m_gen.player2)),
          m_resp(m_agent),
          m_combat(m_agent.GetTaskAgent())
    {
        // Do Nothing
    }

    std::tuple<Player&, Player&> GetPlayer()
    {
        return { m_agent.GetPlayer1(), m_agent.GetPlayer2() };
    }

    void Attack(size_t src, size_t dst, MetaData expected, bool init = false)
    {
        if (init)
        {
            m_init.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
            m_init.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
        }
        auto target = m_resp.Target(src, dst);
        MetaData result =
            m_combat.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
        EXPECT_EQ(result, expected);

        TaskMeta meta = target.get();
        EXPECT_EQ(meta.id, +TaskID::REQUIRE);
    }

 private:
    TestUtils::PlayerGenerator m_gen;

    GameAgent m_agent;
    TestUtils::AutoResponder m_resp;

    BasicTasks::CombatTask m_combat;
    BasicTasks::InitAttackCountTask m_init;
};

TEST(CombatTask, GetTaskID)
{
    TaskAgent agent;
    BasicTasks::CombatTask combat(agent);
    EXPECT_EQ(combat.GetTaskID(), +TaskID::COMBAT);
}

TEST(CombatTask, Default)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();

    auto card1 = TestUtils::GenerateMinionCard("minion1", 3, 6);
    auto card2 = TestUtils::GenerateMinionCard("minion2", 5, 4);

    player1.field.emplace_back(new Minion(card1));
    player2.field.emplace_back(new Minion(card2));

    tester.Attack(1, 0, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.hero->health,
              player2.hero->maxHealth - player1.field[0]->attack);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(1));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card3 = TestUtils::GenerateMinionCard("minion3", 5, 6);
    auto card4 = TestUtils::GenerateMinionCard("minion4", 5, 4);

    player1.field.emplace_back(new Minion(card3));
    player2.field.emplace_back(new Minion(card4));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card5 = TestUtils::GenerateMinionCard("minion5", 5, 4);

    player1.field[0]->attack = 1;
    player2.field.emplace_back(new Minion(card5));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(3));
}

TEST(CombatTask, IndexOutOfRange)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 2, MetaData::COMBAT_DST_IDX_OUT_OF_RANGE, true);
    tester.Attack(2, 1, MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE, true);
}

TEST(CombatTask, Charge)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    // player2.field[0]->gameTags[+GameTag::CHARGE] = 1;
    player1.field[0]->SetAbility(GameTag::CHARGE, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, false);

    // player2.field[0]->gameTags[+GameTag::CHARGE] = 0;
    player1.field[0]->SetAbility(GameTag::CHARGE, false);
    // tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED, false);
}

TEST(CombatTask, Taunt)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[1]->gameTags[+GameTag::TAUNT] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_FIELD_HAVE_TAUNT, true);

    player2.field[1]->gameTags[+GameTag::TAUNT] = 0;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
}

TEST(CombatTask, Stealth)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->gameTags[+GameTag::STEALTH] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_STEALTH, true);

    player1.field[0]->gameTags[+GameTag::STEALTH] = 1;
    player2.field[0]->gameTags[+GameTag::STEALTH] = 0;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->gameTags[+GameTag::STEALTH], 0);
}

TEST(CombatTask, Immune)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->gameTags[+GameTag::IMMUNE] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_IMMUNE, true);
}

TEST(CombatTask, Windfury)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);

    player1.field[0]->gameTags[+GameTag::WINDFURY] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);
}

TEST(CombatTask, DivineShield)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::DIVINE_SHIELD] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));

    player2.field[0]->gameTags[+GameTag::DIVINE_SHIELD] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}

TEST(CombatTask, Poisonous)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::POISONOUS] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::POISONOUS] = 0;
    player2.field[0]->gameTags[+GameTag::POISONOUS] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}
<commit_msg>[ci skip] test: Uncomment failed test case<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include "gtest/gtest.h"
#include <Utils/ResponseUtils.h>
#include <Utils/TestUtils.h>

#include <hspp/Tasks/BasicTasks/CombatTask.h>
#include <hspp/Tasks/BasicTasks/InitAttackCountTask.h>

using namespace Hearthstonepp;

class CombatTester
{
 public:
    CombatTester()
        : m_gen(CardClass::DRUID, CardClass::ROGUE),
          m_agent(std::move(m_gen.player1), std::move(m_gen.player2)),
          m_resp(m_agent),
          m_combat(m_agent.GetTaskAgent())
    {
        // Do Nothing
    }

    std::tuple<Player&, Player&> GetPlayer()
    {
        return { m_agent.GetPlayer1(), m_agent.GetPlayer2() };
    }

    void Attack(size_t src, size_t dst, MetaData expected, bool init = false)
    {
        if (init)
        {
            m_init.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
            m_init.Run(m_agent.GetPlayer2(), m_agent.GetPlayer1());
        }
        auto target = m_resp.Target(src, dst);
        MetaData result =
            m_combat.Run(m_agent.GetPlayer1(), m_agent.GetPlayer2());
        EXPECT_EQ(result, expected);

        TaskMeta meta = target.get();
        EXPECT_EQ(meta.id, +TaskID::REQUIRE);
    }

 private:
    TestUtils::PlayerGenerator m_gen;

    GameAgent m_agent;
    TestUtils::AutoResponder m_resp;

    BasicTasks::CombatTask m_combat;
    BasicTasks::InitAttackCountTask m_init;
};

TEST(CombatTask, GetTaskID)
{
    TaskAgent agent;
    BasicTasks::CombatTask combat(agent);
    EXPECT_EQ(combat.GetTaskID(), +TaskID::COMBAT);
}

TEST(CombatTask, Default)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();

    auto card1 = TestUtils::GenerateMinionCard("minion1", 3, 6);
    auto card2 = TestUtils::GenerateMinionCard("minion2", 5, 4);

    player1.field.emplace_back(new Minion(card1));
    player2.field.emplace_back(new Minion(card2));

    tester.Attack(1, 0, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.hero->health,
              player2.hero->maxHealth - player1.field[0]->attack);

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(1));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card3 = TestUtils::GenerateMinionCard("minion3", 5, 6);
    auto card4 = TestUtils::GenerateMinionCard("minion4", 5, 4);

    player1.field.emplace_back(new Minion(card3));
    player2.field.emplace_back(new Minion(card4));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(1));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    auto card5 = TestUtils::GenerateMinionCard("minion5", 5, 4);

    player1.field[0]->attack = 1;
    player2.field.emplace_back(new Minion(card5));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(3));
}

TEST(CombatTask, IndexOutOfRange)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 2, MetaData::COMBAT_DST_IDX_OUT_OF_RANGE, true);
    tester.Attack(2, 1, MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE, true);
}

TEST(CombatTask, Charge)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->SetAbility(GameTag::CHARGE, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, false);

    player1.field[0]->SetAbility(GameTag::CHARGE, false);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED, false);
}

TEST(CombatTask, Taunt)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion1", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[1]->gameTags[+GameTag::TAUNT] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_FIELD_HAVE_TAUNT, true);

    player2.field[1]->gameTags[+GameTag::TAUNT] = 0;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
}

TEST(CombatTask, Stealth)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->gameTags[+GameTag::STEALTH] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_STEALTH, true);

    player1.field[0]->gameTags[+GameTag::STEALTH] = 1;
    player2.field[0]->gameTags[+GameTag::STEALTH] = 0;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field[0]->gameTags[+GameTag::STEALTH], 0);
}

TEST(CombatTask, Immune)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player2.field[0]->gameTags[+GameTag::IMMUNE] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_TARGET_IMMUNE, true);
}

TEST(CombatTask, Windfury)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);

    player1.field[0]->gameTags[+GameTag::WINDFURY] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS);
    tester.Attack(1, 1, MetaData::COMBAT_ALREADY_ATTACKED);
}

TEST(CombatTask, DivineShield)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::DIVINE_SHIELD] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, player1.field[0]->maxHealth);
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));

    player2.field[0]->gameTags[+GameTag::DIVINE_SHIELD] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}

TEST(CombatTask, Poisonous)
{
    CombatTester tester;
    auto [player1, player2] = tester.GetPlayer();
    auto card = TestUtils::GenerateMinionCard("minion", 1, 10);

    player1.field.emplace_back(new Minion(card));
    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::POISONOUS] = 1;
    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);

    EXPECT_EQ(player1.field[0]->health, static_cast<size_t>(9));
    EXPECT_EQ(player2.field.size(), static_cast<size_t>(0));

    player2.field.emplace_back(new Minion(card));

    player1.field[0]->gameTags[+GameTag::POISONOUS] = 0;
    player2.field[0]->gameTags[+GameTag::POISONOUS] = 1;

    tester.Attack(1, 1, MetaData::COMBAT_SUCCESS, true);
    EXPECT_EQ(player1.field.size(), static_cast<size_t>(0));
    EXPECT_EQ(player2.field[0]->health, static_cast<size_t>(9));
}
<|endoftext|>