<commit_before>#include "AliHLTTRDTracklet.h"

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDTracklet::AliHLTTRDTracklet():
  fN(0),
  fdX(-1),
  fS2Y(-1),
  fPt(-1),
  fX0(-1),
  fChi2(-1),
  // fExB(-1),
  // fVD(-1),
  // fT0(-1),
  // fS2PRF(-1),
  // fDiffL(-1),
  // fDiffT(-1),
  // fX(-1),
  // fY(-1),
  // fZ(-1),
  // fS2Z(-1),
  fDet(-1),
  fBits(0),
  fCount(0),
#if defined(__HP_aCC) || defined(__DECCXX) || defined(__SUNPRO_CC)
  fSize(sizeof(AliHLTTRDTracklet)-sizeof(AliHLTTRDCluster)),
#else
  fSize(sizeof(AliHLTTRDTracklet))
#endif
{
  InitArrays();
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDTracklet::AliHLTTRDTracklet(const AliTRDseedV1* const inTracklet):
  fN(inTracklet->fN),
  fdX(inTracklet->fdX),
  fS2Y(inTracklet->fS2Y),
  fPt(inTracklet->fPt),
  fX0(inTracklet->fX0),
  fChi2(inTracklet->fChi2),
  // fExB(inTracklet->fExB),
  // fVD(inTracklet->fVD),
  // fT0(inTracklet->fT0),
  // fS2PRF(inTracklet->fS2PRF),
  // fDiffL(inTracklet->fDiffL),
  // fDiffT(inTracklet->fDiffT),
  // fX(inTracklet->fX),
  // fY(inTracklet->fY),
  // fZ(inTracklet->fZ),
  // fS2Z(inTracklet->fS2Z),
  fDet(inTracklet->fDet),
  fBits(0),
  fCount(0),
#if defined(__HP_aCC) || defined(__DECCXX) || defined(__SUNPRO_CC)
  fSize(sizeof(AliHLTTRDTracklet)-sizeof(AliHLTTRDCluster)),
#else
  fSize(sizeof(AliHLTTRDTracklet))
#endif
{
  CopyDataMembers(inTracklet);
}

/**
 * Copy simple (non-pointer) data members from TRDTracklet to HLTTRDTracklet
 */
//============================================================================
void AliHLTTRDTracklet::CopyDataMembers(const AliTRDseedV1* const inTracklet)
{
  for (Int_t i=0; i < 2; i++){
    fYref[i]   = inTracklet->fYref[i];
    fZref[i]   = inTracklet->fZref[i];
    fYfit[i]   = inTracklet->fYfit[i];
    fZfit[i]   = inTracklet->fZfit[i];
  }
  fC[0] = inTracklet->fC[0];fC[1] = inTracklet->fC[1];
  for (Int_t i=0; i < 3; i++){
    fPad[i] = inTracklet->fPad[i];
    // fCov[i] = inTracklet->fCov[i];
  }

  // for (Int_t i=0; i < 7; i++){
  //   fRefCov[i] = inTracklet->fRefCov[i];
  // }

  // for (Int_t i=0; i < AliTRDseedV1::kNslices; i++){
  //   fdEdx[i] = inTracklet->fdEdx[i];
  // }

  for (Int_t i=0; i < AliPID::kSPECIES; i++){
    fProb[i] = inTracklet->fProb[i];
  }

  fBits = UInt_t(inTracklet->TestBits(-1)) >> 14;

  for (Int_t iTimeBin = 0; iTimeBin < AliTRDseedV1::kNclusters; iTimeBin++){
    AliTRDcluster* trdCluster = inTracklet->GetClusters(iTimeBin);
    if (trdCluster){
      fPos[fCount] = iTimeBin;
      new (&fClusters[fCount]) AliHLTTRDCluster(trdCluster);
      fCount++;
      fSize += sizeof(AliHLTTRDCluster);
    }
  }
  //if((void*)&fClusters[fCount]!=(void*)GetEndPointer()){printf("ERRR");return;}
}

/**
 * Copy data to the output TRDseedV1
 */
//============================================================================
void AliHLTTRDTracklet::ExportTRDTracklet(AliTRDseedV1* const outTracklet) const
{
  //outTracklet->Reset(); we always use a fresh trdtracklet as input, so this is useless
  outTracklet->SetBit(AliTRDseedV1::kOwner);

  outTracklet->fN      = fN;
  outTracklet->fdX     = fdX;
  outTracklet->fX0     = fX0;
  outTracklet->fS2Y    = fS2Y;
  outTracklet->fPt     = fPt;
  outTracklet->fC[0]   = fC[0];
  outTracklet->fC[1]   = fC[1];
  outTracklet->fChi2   = fChi2;
  // outTracklet->fExB    = fExB;
  // outTracklet->fVD     = fVD;
  // outTracklet->fT0     = fT0;
  // outTracklet->fS2PRF  = fS2PRF;
  // outTracklet->fDiffL  = fDiffL;
  // outTracklet->fDiffT  = fDiffT;
  // outTracklet->fX      = fX;
  // outTracklet->fY      = fY;
  // outTracklet->fZ      = fZ;
  // outTracklet->fS2Z    = fS2Z;
  outTracklet->fDet    = fDet;

  for (Int_t i=0; i < 2; i++){
    outTracklet->fYref[i]   = fYref[i];
    outTracklet->fZref[i]   = fZref[i];
    outTracklet->fYfit[i]   = fYfit[i];
    outTracklet->fZfit[i]   = fZfit[i];
  }

  for (Int_t i=0; i < 3; i++){
    outTracklet->fPad[i] = fPad[i];
    // outTracklet->fCov[i] = fCov[i];
  }

  // for (Int_t i=0; i < 7; i++){
  //   outTracklet->fRefCov[i] = fRefCov[i];
  // }

  // for (Int_t i=0; i < AliTRDseedV1::kNslices; i++){
  //   outTracklet->fdEdx[i] = fdEdx[i];
  // }

  for (Int_t i=0; i < AliPID::kSPECIES; i++){
    outTracklet->fProb[i] = fProb[i];
  }

  outTracklet->SetBit(UInt_t(fBits)<<14);

  for(Int_t iCluster=0; iCluster < fCount; iCluster++){
    AliTRDcluster *trdCluster = new AliTRDcluster();
    fClusters[iCluster].ExportTRDCluster(trdCluster);
    outTracklet->fClusters[fPos[iCluster]] = trdCluster;
    outTracklet->fIndexes[fPos[iCluster]] = iCluster;
  }
}

/**
 * Init arrays
 */
//============================================================================
void AliHLTTRDTracklet::InitArrays()
{
  for (Int_t i=0; i < 2; i++){
    fYref[i] = -1;
    fZref[i] = -1;
    fYfit[i] = -1;
    fZfit[i] = -1;
  }
  fC[0] = 0.; fC[1] = 0.;
  for (Int_t i=0; i < AliPID::kSPECIES; i++)
    fProb[i]=0;
}

/**
 * Prints main info about tracklet
 */
//============================================================================
void AliHLTTRDTracklet::Print(Bool_t printClusters) const
{
  //printf("--hltTracklet-- addr 0x%p(%i); fSize %i\n", this, (int)this, fSize);
  printf("      fDet %i; fPt %f; fdX %f fN %i\n", fDet, fPt, fdX, fN);

  if(!printClusters) return;
  for (UInt_t iCluster = 0; iCluster < fCount; iCluster++){
    printf(" [%i] ",iCluster);
    fClusters[iCluster].Print();
  }
}

/**
 * Read clusters to TRDtracklet from the memory
 */
//============================================================================
// void AliHLTTRDTracklet::ReadClustersFromMemory(void *input)
// {
//   AliHLTUInt8_t *iterPtr = (AliHLTUInt8_t*) input;
//   AliHLTTRDCluster* hltCluster = NULL;

//   for (Int_t iCluster = 0; iCluster < AliTRDseedV1::kNclusters; iCluster++){
//     // if we had something in the fClusters[iCluster] before copying,
//     // then this entry in the array should not be empty. Fill it.
//     if (fClusters[iCluster]){
//       hltCluster = (AliHLTTRDCluster*) iterPtr;
//       fClusters[iCluster] = hltCluster;
//       iterPtr += hltCluster->GetSize();
//       //hltCluster->Print();
//     }

//   }
// }

<commit_msg>restoring backward compatibility after changes in AliTRDseedV1 r39693<commit_after>#include "AliHLTTRDTracklet.h"

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDTracklet::AliHLTTRDTracklet():
  fN(0),
  fdX(-1),
  fS2Y(-1),
  fPt(-1),
  fX0(-1),
  fChi2(-1),
  // fExB(-1),
  // fVD(-1),
  // fT0(-1),
  // fS2PRF(-1),
  // fDiffL(-1),
  // fDiffT(-1),
  // fX(-1),
  // fY(-1),
  // fZ(-1),
  // fS2Z(-1),
  fDet(-1),
  fBits(0),
  fCount(0),
#if defined(__HP_aCC) || defined(__DECCXX) || defined(__SUNPRO_CC)
  fSize(sizeof(AliHLTTRDTracklet)-sizeof(AliHLTTRDCluster)),
#else
  fSize(sizeof(AliHLTTRDTracklet))
#endif
{
  InitArrays();
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDTracklet::AliHLTTRDTracklet(const AliTRDseedV1* const inTracklet):
  fN(inTracklet->fN),
  fdX(inTracklet->fdX),
  fS2Y(inTracklet->fS2Y),
  fPt(inTracklet->fPt),
  fX0(inTracklet->fX0),
  fChi2(inTracklet->fChi2),
  // fExB(inTracklet->fExB),
  // fVD(inTracklet->fVD),
  // fT0(inTracklet->fT0),
  // fS2PRF(inTracklet->fS2PRF),
  // fDiffL(inTracklet->fDiffL),
  // fDiffT(inTracklet->fDiffT),
  // fX(inTracklet->fX),
  // fY(inTracklet->fY),
  // fZ(inTracklet->fZ),
  // fS2Z(inTracklet->fS2Z),
  fDet(inTracklet->fDet),
  fBits(0),
  fCount(0),
#if defined(__HP_aCC) || defined(__DECCXX) || defined(__SUNPRO_CC)
  fSize(sizeof(AliHLTTRDTracklet)-sizeof(AliHLTTRDCluster)),
#else
  fSize(sizeof(AliHLTTRDTracklet))
#endif
{
  CopyDataMembers(inTracklet);
}

/**
 * Copy simple (non-pointer) data members from TRDTracklet to HLTTRDTracklet
 */
//============================================================================
void AliHLTTRDTracklet::CopyDataMembers(const AliTRDseedV1* const inTracklet)
{
  for (Int_t i=0; i < 2; i++){
    fYref[i]   = inTracklet->fYref[i];
    fZref[i]   = inTracklet->fZref[i];
    fYfit[i]   = inTracklet->fYfit[i];
    fZfit[i]   = inTracklet->fZfit[i];
  }
  fC[0] = inTracklet->GetC();
#ifndef HAVE_NOT_ALITRD_SEEDV1_r39693
  fC[1] = inTracklet->GetC(1);
#endif //HAVE_NOT_ALITRD_SEEDV1_r39693
  for (Int_t i=0; i < 3; i++){
    fPad[i] = inTracklet->fPad[i];
    // fCov[i] = inTracklet->fCov[i];
  }

  // for (Int_t i=0; i < 7; i++){
  //   fRefCov[i] = inTracklet->fRefCov[i];
  // }

  // for (Int_t i=0; i < AliTRDseedV1::kNslices; i++){
  //   fdEdx[i] = inTracklet->fdEdx[i];
  // }

  for (Int_t i=0; i < AliPID::kSPECIES; i++){
    fProb[i] = inTracklet->fProb[i];
  }

  fBits = UInt_t(inTracklet->TestBits(-1)) >> 14;

  for (Int_t iTimeBin = 0; iTimeBin < AliTRDseedV1::kNclusters; iTimeBin++){
    AliTRDcluster* trdCluster = inTracklet->GetClusters(iTimeBin);
    if (trdCluster){
      fPos[fCount] = iTimeBin;
      new (&fClusters[fCount]) AliHLTTRDCluster(trdCluster);
      fCount++;
      fSize += sizeof(AliHLTTRDCluster);
    }
  }
  //if((void*)&fClusters[fCount]!=(void*)GetEndPointer()){printf("ERRR");return;}
}

/**
 * Copy data to the output TRDseedV1
 */
//============================================================================
void AliHLTTRDTracklet::ExportTRDTracklet(AliTRDseedV1* const outTracklet) const
{
  //outTracklet->Reset(); we always use a fresh trdtracklet as input, so this is useless
  outTracklet->SetBit(AliTRDseedV1::kOwner);

  outTracklet->fN      = fN;
  outTracklet->fdX     = fdX;
  outTracklet->fX0     = fX0;
  outTracklet->fS2Y    = fS2Y;
  outTracklet->fPt     = fPt;
  outTracklet->SetC(fC[0]);
#ifndef HAVE_NOT_ALITRD_SEEDV1_r39693
  outTracklet->SetC(fC[1], 1);
#endif //HAVE_NOT_ALITRD_SEEDV1_r39693
  outTracklet->fChi2   = fChi2;
  // outTracklet->fExB    = fExB;
  // outTracklet->fVD     = fVD;
  // outTracklet->fT0     = fT0;
  // outTracklet->fS2PRF  = fS2PRF;
  // outTracklet->fDiffL  = fDiffL;
  // outTracklet->fDiffT  = fDiffT;
  // outTracklet->fX      = fX;
  // outTracklet->fY      = fY;
  // outTracklet->fZ      = fZ;
  // outTracklet->fS2Z    = fS2Z;
  outTracklet->fDet    = fDet;

  for (Int_t i=0; i < 2; i++){
    outTracklet->fYref[i]   = fYref[i];
    outTracklet->fZref[i]   = fZref[i];
    outTracklet->fYfit[i]   = fYfit[i];
    outTracklet->fZfit[i]   = fZfit[i];
  }

  for (Int_t i=0; i < 3; i++){
    outTracklet->fPad[i] = fPad[i];
    // outTracklet->fCov[i] = fCov[i];
  }

  // for (Int_t i=0; i < 7; i++){
  //   outTracklet->fRefCov[i] = fRefCov[i];
  // }

  // for (Int_t i=0; i < AliTRDseedV1::kNslices; i++){
  //   outTracklet->fdEdx[i] = fdEdx[i];
  // }

  for (Int_t i=0; i < AliPID::kSPECIES; i++){
    outTracklet->fProb[i] = fProb[i];
  }

  outTracklet->SetBit(UInt_t(fBits)<<14);

  for(Int_t iCluster=0; iCluster < fCount; iCluster++){
    AliTRDcluster *trdCluster = new AliTRDcluster();
    fClusters[iCluster].ExportTRDCluster(trdCluster);
    outTracklet->fClusters[fPos[iCluster]] = trdCluster;
    outTracklet->fIndexes[fPos[iCluster]] = iCluster;
  }
}

/**
 * Init arrays
 */
//============================================================================
void AliHLTTRDTracklet::InitArrays()
{
  for (Int_t i=0; i < 2; i++){
    fYref[i] = -1;
    fZref[i] = -1;
    fYfit[i] = -1;
    fZfit[i] = -1;
  }
  fC[0] = 0.; fC[1] = 0.;
  for (Int_t i=0; i < AliPID::kSPECIES; i++)
    fProb[i]=0;
}

/**
 * Prints main info about tracklet
 */
//============================================================================
void AliHLTTRDTracklet::Print(Bool_t printClusters) const
{
  //printf("--hltTracklet-- addr 0x%p(%i); fSize %i\n", this, (int)this, fSize);
  printf("      fDet %i; fPt %f; fdX %f fN %i\n", fDet, fPt, fdX, fN);

  if(!printClusters) return;
  for (UInt_t iCluster = 0; iCluster < fCount; iCluster++){
    printf(" [%i] ",iCluster);
    fClusters[iCluster].Print();
  }
}

/**
 * Read clusters to TRDtracklet from the memory
 */
//============================================================================
// void AliHLTTRDTracklet::ReadClustersFromMemory(void *input)
// {
//   AliHLTUInt8_t *iterPtr = (AliHLTUInt8_t*) input;
//   AliHLTTRDCluster* hltCluster = NULL;

//   for (Int_t iCluster = 0; iCluster < AliTRDseedV1::kNclusters; iCluster++){
//     // if we had something in the fClusters[iCluster] before copying,
//     // then this entry in the array should not be empty. Fill it.
//     if (fClusters[iCluster]){
//       hltCluster = (AliHLTTRDCluster*) iterPtr;
//       fClusters[iCluster] = hltCluster;
//       iterPtr += hltCluster->GetSize();
//       //hltCluster->Print();
//     }

//   }
// }

<|endoftext|>


<commit_before>/**
 *   @file checkFinite.cpp Declarations for routines that check for the
 *       presence of NaNs in the code.
 */
/*
 * Copyright 2004 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 * See file License.txt for licensing information.
 */

#include "cantera/base/ct_defs.h"

#include <stdexcept>
#include <cstdio>

// We expect that there will be special casing based on the computer
// system here

#ifdef SOLARIS
#include <ieeefp.h>
#include <sunmath.h>
#endif

#ifdef _WIN32
#include <float.h>
#endif

using namespace std;

namespace Cantera {

void checkFinite(const double tmp)
{
#ifdef _WIN32
    if (_finite(tmp)) {
        if (_isnan(tmp)) {
            printf("checkFinite() ERROR: we have encountered a nan!\n");
        } else if (_fpclass(tmp) == _FPCLASS_PINF) {
            printf("checkFinite() ERROR: we have encountered a pos inf!\n");
        } else {
            printf("checkFinite() ERROR: we have encountered a neg inf!\n");
        }
        throw std::range_error("checkFinite()");
    }
#else
    if (!finite(tmp)) {
        if (isnan(tmp)) {
            printf("checkFinite() ERROR: we have encountered a nan!\n");
        } else if (isinf(tmp) == 1) {
            printf("checkFinite() ERROR: we have encountered a pos inf!\n");
        } else {
            printf("checkFinite() ERROR: we have encountered a neg inf!\n");
        }
        throw std::range_error("checkFinite()");
    }
#endif
}

}
<commit_msg>Use fully qualified names for isnan, isinf, and finite<commit_after>/**
 *   @file checkFinite.cpp Declarations for routines that check for the
 *       presence of NaNs in the code.
 */
/*
 * Copyright 2004 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 * See file License.txt for licensing information.
 */

#include "cantera/base/ct_defs.h"

#include <stdexcept>
#include <cstdio>

// We expect that there will be special casing based on the computer
// system here

#ifdef SOLARIS
#include <ieeefp.h>
#include <sunmath.h>
#endif

#ifdef _WIN32
#include <float.h>
#endif

using namespace std;

namespace Cantera {

void checkFinite(const double tmp)
{
#ifdef _WIN32
    if (_finite(tmp)) {
        if (_isnan(tmp)) {
            printf("checkFinite() ERROR: we have encountered a nan!\n");
        } else if (_fpclass(tmp) == _FPCLASS_PINF) {
            printf("checkFinite() ERROR: we have encountered a pos inf!\n");
        } else {
            printf("checkFinite() ERROR: we have encountered a neg inf!\n");
        }
        throw std::range_error("checkFinite()");
    }
#else
    if (!::finite(tmp)) {
        if (::isnan(tmp)) {
            printf("checkFinite() ERROR: we have encountered a nan!\n");
        } else if (::isinf(tmp) == 1) {
            printf("checkFinite() ERROR: we have encountered a pos inf!\n");
        } else {
            printf("checkFinite() ERROR: we have encountered a neg inf!\n");
        }
        throw std::range_error("checkFinite()");
    }
#endif
}

}
<|endoftext|>


<commit_before>#include <functional>
#include <vector>
#include "lexer.hh"
#include "value.hh"
#include "chunk.hh"
#include "vm.hh"
#include "compiler.hh"

namespace tadpole {

enum class Precedence {
  NONE,

  ASSIGN, // =
  TERM,   // - +
  FACTOR, // / *
  CALL,   // ()

  PRIMARY,
};

template <typename T> inline Precedence operator+(Precedence a, T b) noexcept {
  return as_type<Precedence>(as_type<int>(a) + as_type<int>(b));
}

struct ParseRule {
  using ParseFn = std::function<void (TadpoleParser&, bool)>;

  ParseFn prefix;
  ParseFn infix;
  Precedence precedence;
};

struct LocalVar {
  Token name;
  int depth{};
  bool is_upvalue{};

  LocalVar(const Token& _name, int _depth = -1, bool _is_upvalue = false) noexcept
    : name(_name), depth(_depth), is_upvalue(_is_upvalue) {
  }
};

struct Upvalue {
  u8_t index{};
  bool is_local{};

  Upvalue(u8_t _index = 0, bool _is_local = false) noexcept
    : index(_index), is_local(_is_local) {
  }

  inline bool operator==(Upvalue r) const noexcept {
    return index == r.index && is_local == r.is_local;
  }

  inline bool operator!=(Upvalue r) const noexcept {
    return !(*this == r);
  }

  inline bool is_equal(u8_t _index, bool _is_local) const noexcept {
    return index == _index && is_local == _is_local;
  }
};

enum class FunType {
  FUNCTION,
  TOPLEVEL,
};

class Compiler final : private UnCopyable {
  using ErrorFn = std::function<void (const str_t&)>;

  Compiler* enclosing_{};
  FunctionObject* fn_{};
  FunType fn_type_{};

  int scope_depth_{};

  std::vector<LocalVar> locals_;
  std::vector<Upvalue> upvalues_;
public:
  Compiler() noexcept {}

  Compiler(Compiler* enclosing,
    FunctionObject* fn, FunType fn_type, int scope_depth = 0) noexcept
    : enclosing_(enclosing), fn_(fn), fn_type_(fn_type), scope_depth_(scope_depth) {
  }

  inline void set_compiler(Compiler* enclosing,
    FunctionObject* fn, FunType fn_type, int scope_depth = 0) noexcept {
    enclosing_ = enclosing;
    fn_ = fn;
    fn_type_ = fn_type;
    scope_depth_ = scope_depth;
  }

  inline Compiler* enclosing() const noexcept { return enclosing_; }
  inline FunctionObject* fn() const noexcept { return fn_; }
  inline FunType fn_type() const noexcept { return fn_type_; }
  inline int scope_depth() const noexcept { return scope_depth_; }
  inline void set_scope_depth(int depth) noexcept { scope_depth_ = depth; }
  inline int locals_count() const noexcept { return as_type<int>(locals_.size()); }
  inline LocalVar& get_local(sz_t i) noexcept { return locals_[i]; }
  inline const LocalVar& get_local(sz_t i) const noexcept { return locals_[i]; }
  inline LocalVar& peek_local() noexcept { return locals_.back(); }
  inline const LocalVar& peek_local() const noexcept { return locals_.back(); }
  inline void append_local(const LocalVar& var) noexcept { locals_.push_back(var); }
  inline Upvalue& get_upvalue(sz_t i) noexcept { return upvalues_[i]; }
  inline const Upvalue& get_upvalue(sz_t i) const noexcept { return upvalues_[i]; }
  inline void append_upvalue(const Upvalue& u) noexcept { upvalues_.push_back(u); }

  void enter_scope() noexcept { ++scope_depth_; }
  template <typename Fn> void leave_scope(Fn&& visitor) {
    --scope_depth_;
    while (!locals_.empty() && peek_local().depth > scope_depth_) {
      visitor(peek_local());
      locals_.pop_back();
    }
  }

  int resolve_local(const Token& name, const ErrorFn& errfn) {
    for (int i = locals_count() - 1; i >= 0; --i) {
      auto& local = locals_[i];
      if (local.name == name) {
        if (local.depth == -1)
          errfn(string_format("cannot load local variable `%s` in its own initializer", name.as_cstring()));
        return i;
      }
    }
    return -1;
  }

  int add_upvalue(u8_t index, bool is_local) {
    for (int i = 0; i < fn_->upvalues_count(); ++i) {
      if (upvalues_[i].is_equal(index, is_local))
        return i;
    }

    upvalues_.push_back(Upvalue(index, is_local));
    return as_type<int>(fn_->inc_upvalues_count());
  }

  int resolve_upvalue(const Token& name, const ErrorFn& errfn) {
    if (enclosing_ == nullptr)
      return -1;

    if (int local = enclosing_->resolve_local(name, errfn); local != -1) {
      enclosing_->locals_[local].is_upvalue = true;
      return add_upvalue(as_type<u8_t>(local), true);
    }
    if (int upvalue = enclosing_->resolve_upvalue(name, errfn); upvalue != -1)
      return add_upvalue(as_type<u8_t>(upvalue), false);
    return -1;
  }

  void declare_localvar(const Token& name, const ErrorFn& errfn) {
    if (scope_depth_ == 0)
      return;

    for (auto it = locals_.rbegin(); it != locals_.rend(); ++it) {
      if (it->depth != -1 && it->depth < scope_depth_)
        break;

      if (it->name == name)
        errfn(string_format("name `%s` is redefined", name.as_cstring()));
    }
    locals_.push_back(LocalVar(name, -1, false));
  }
};

FunctionObject* TadpoleCompiler::compile(VM& vm, const str_t& source_bytes) {
  // TODO:

  return nullptr;
}

void TadpoleCompiler::mark_compiler() {}

}<commit_msg>:construction: chore(parser): add basic functional of tadpole parser<commit_after>#include <functional>
#include <iostream>
#include <vector>
#include "lexer.hh"
#include "value.hh"
#include "chunk.hh"
#include "vm.hh"
#include "compiler.hh"

namespace tadpole {

enum class Precedence {
  NONE,

  ASSIGN, // =
  TERM,   // - +
  FACTOR, // / *
  CALL,   // ()

  PRIMARY,
};

template <typename T> inline Precedence operator+(Precedence a, T b) noexcept {
  return as_type<Precedence>(as_type<int>(a) + as_type<int>(b));
}

struct ParseRule {
  using ParseFn = std::function<void (TadpoleParser&, bool)>;

  ParseFn prefix;
  ParseFn infix;
  Precedence precedence;
};

struct LocalVar {
  Token name;
  int depth{};
  bool is_upvalue{};

  LocalVar(const Token& _name, int _depth = -1, bool _is_upvalue = false) noexcept
    : name(_name), depth(_depth), is_upvalue(_is_upvalue) {
  }
};

struct Upvalue {
  u8_t index{};
  bool is_local{};

  Upvalue(u8_t _index = 0, bool _is_local = false) noexcept
    : index(_index), is_local(_is_local) {
  }

  inline bool operator==(Upvalue r) const noexcept {
    return index == r.index && is_local == r.is_local;
  }

  inline bool operator!=(Upvalue r) const noexcept {
    return !(*this == r);
  }

  inline bool is_equal(u8_t _index, bool _is_local) const noexcept {
    return index == _index && is_local == _is_local;
  }
};

enum class FunType {
  FUNCTION,
  TOPLEVEL,
};

class Compiler final : private UnCopyable {
  using ErrorFn = std::function<void (const str_t&)>;

  Compiler* enclosing_{};
  FunctionObject* fn_{};
  FunType fn_type_{};

  int scope_depth_{};

  std::vector<LocalVar> locals_;
  std::vector<Upvalue> upvalues_;
public:
  Compiler() noexcept {}

  Compiler(Compiler* enclosing,
    FunctionObject* fn, FunType fn_type, int scope_depth = 0) noexcept
    : enclosing_(enclosing), fn_(fn), fn_type_(fn_type), scope_depth_(scope_depth) {
  }

  inline void set_compiler(Compiler* enclosing,
    FunctionObject* fn, FunType fn_type, int scope_depth = 0) noexcept {
    enclosing_ = enclosing;
    fn_ = fn;
    fn_type_ = fn_type;
    scope_depth_ = scope_depth;
  }

  inline Compiler* enclosing() const noexcept { return enclosing_; }
  inline FunctionObject* fn() const noexcept { return fn_; }
  inline FunType fn_type() const noexcept { return fn_type_; }
  inline int scope_depth() const noexcept { return scope_depth_; }
  inline void set_scope_depth(int depth) noexcept { scope_depth_ = depth; }
  inline int locals_count() const noexcept { return as_type<int>(locals_.size()); }
  inline LocalVar& get_local(sz_t i) noexcept { return locals_[i]; }
  inline const LocalVar& get_local(sz_t i) const noexcept { return locals_[i]; }
  inline LocalVar& peek_local() noexcept { return locals_.back(); }
  inline const LocalVar& peek_local() const noexcept { return locals_.back(); }
  inline void append_local(const LocalVar& var) noexcept { locals_.push_back(var); }
  inline Upvalue& get_upvalue(sz_t i) noexcept { return upvalues_[i]; }
  inline const Upvalue& get_upvalue(sz_t i) const noexcept { return upvalues_[i]; }
  inline void append_upvalue(const Upvalue& u) noexcept { upvalues_.push_back(u); }

  void enter_scope() noexcept { ++scope_depth_; }
  template <typename Fn> void leave_scope(Fn&& visitor) {
    --scope_depth_;
    while (!locals_.empty() && peek_local().depth > scope_depth_) {
      visitor(peek_local());
      locals_.pop_back();
    }
  }

  int resolve_local(const Token& name, const ErrorFn& errfn) {
    for (int i = locals_count() - 1; i >= 0; --i) {
      auto& local = locals_[i];
      if (local.name == name) {
        if (local.depth == -1)
          errfn(string_format("cannot load local variable `%s` in its own initializer", name.as_cstring()));
        return i;
      }
    }
    return -1;
  }

  int add_upvalue(u8_t index, bool is_local) {
    for (int i = 0; i < fn_->upvalues_count(); ++i) {
      if (upvalues_[i].is_equal(index, is_local))
        return i;
    }

    upvalues_.push_back(Upvalue(index, is_local));
    return as_type<int>(fn_->inc_upvalues_count());
  }

  int resolve_upvalue(const Token& name, const ErrorFn& errfn) {
    if (enclosing_ == nullptr)
      return -1;

    if (int local = enclosing_->resolve_local(name, errfn); local != -1) {
      enclosing_->locals_[local].is_upvalue = true;
      return add_upvalue(as_type<u8_t>(local), true);
    }
    if (int upvalue = enclosing_->resolve_upvalue(name, errfn); upvalue != -1)
      return add_upvalue(as_type<u8_t>(upvalue), false);
    return -1;
  }

  void declare_localvar(const Token& name, const ErrorFn& errfn) {
    if (scope_depth_ == 0)
      return;

    for (auto it = locals_.rbegin(); it != locals_.rend(); ++it) {
      if (it->depth != -1 && it->depth < scope_depth_)
        break;

      if (it->name == name)
        errfn(string_format("name `%s` is redefined", name.as_cstring()));
    }
    locals_.push_back(LocalVar(name, -1, false));
  }
};

class TadpoleParser final : private UnCopyable {
  static constexpr int kMaxArguments = 8;

  VM& vm_;
  Lexer& lex_;
  Token prev_;
  Token curr_;

  bool had_error_{};
  bool panic_mode_{};

  Compiler* curr_compiler_{};

  void error_at(const Token& tok, const str_t& msg) noexcept {
    if (panic_mode_)
      return;
    panic_mode_ = true;

    std::cerr
      << "SyntaxError:" << std::endl
      << "  [LINE: " << tok.lineno() << "] ERROR ";
    if (tok.kind() == TokenKind::TK_EOF)
      std::cerr << "at end ";
    else if (tok.kind() == TokenKind::TK_ERR)
      (void)0;
    else
      std::cerr << "at `" << tok.literal() << "` ";
    std::cerr << ": " << msg << std::endl;

    had_error_ = true;
  }

  inline void error_at_current(const str_t& msg) noexcept { error_at(curr_, msg); }
  inline void error(const str_t& msg) noexcept { error_at(prev_, msg); }
  inline Chunk* curr_chunk() const noexcept { return curr_compiler_->fn()->chunk(); }
  inline bool check(TokenKind kind) const noexcept { return curr_.kind() == kind; }

  void advance() {
    prev_ = curr_;

    for (;;) {
      curr_ = lex_.next_token();
      if (!check(TokenKind::TK_ERR))
        break;

      error_at_current(curr_.as_string());
    }
  }

  void consume(TokenKind kind, const str_t& msg) {
    if (check(kind))
      advance();
    else
      error_at_current(msg);
  }

  bool match(TokenKind kind) {
    if (check(kind)) {
      advance();
      return true;
    }
    return false;
  }

  template <typename T> inline void emit_byte(T byte) noexcept {
    curr_chunk()->write(byte, prev_.lineno());
  }

  template <typename T, typename U> inline void emit_bytes(T b1, U b2) noexcept {
    emit_byte(b1);
    emit_byte(b2);
  }

  inline void emit_return() noexcept { emit_bytes(Code::NIL, Code::RETURN); }

  inline void emit_constant(const Value& v) noexcept {
    emit_bytes(Code::CONSTANT, curr_chunk()->add_constant(v));
  }

  void init_compiler(Compiler* compiler, int scope_depth, FunType fn_type) {
    StringObject* func_name{};
    if (fn_type == FunType::FUNCTION)
      func_name = StringObject::create(vm_, prev_.as_string());

    compiler->set_compiler(
      curr_compiler_,
      FunctionObject::create(vm_, func_name),
      fn_type,
      scope_depth);
    curr_compiler_ = compiler;

    curr_compiler_->append_local(LocalVar(Token::make(""), curr_compiler_->scope_depth(), false));
  }

  FunctionObject* finish_compiler() {
    emit_return();

    FunctionObject* fn = curr_compiler_->fn();

#if defined(TADPOLE_DEBUG_VM)
    if (!had_error_)
      curr_chunk()->dis(fn->name_asstr());
#endif

    curr_compiler_ = curr_compiler_->enclosing();
    return fn;
  }

  inline void enter_scope() {
    curr_compiler_->enter_scope();
  }

  inline void leave_scope() {
    curr_compiler_->leave_scope([this](const LocalVar& var) {
      emit_byte(var.is_upvalue ? Code::CLOSE_UPVALUE : Code::POP);
      });
  }

  inline u8_t identifier_constant(const Token& name) noexcept {
    return curr_chunk()->add_constant(StringObject::create(vm_, name.as_string()));
  }
};

FunctionObject* TadpoleCompiler::compile(VM& vm, const str_t& source_bytes) {
  // TODO:

  return nullptr;
}

void TadpoleCompiler::mark_compiler() {}

}<|endoftext|>


<commit_before>#include "logger.h"
#include "config.h"
#include "util.h"
#include "exec.h"
#include "taskserver.h"
#include "system/system.h"
#include "task/task.h"
#include "web/webpage.h"
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <cstdio>
#include <string>
#include <thread>
#include <json11.hpp>

namespace {

using namespace shanghai;
using namespace std::string_literals;

// 処理したいシグナルを全てブロックし、シグナル処理スレッドでハンドルする
// ブロックしたシグナルセットを sigset に返す
void SetupSignalMask(sigset_t &sigset)
{
	int ret;

	util::SysCall(sigemptyset(&sigset));
	util::SysCall(sigaddset(&sigset, SIGINT));
	util::SysCall(sigaddset(&sigset, SIGTERM));
	util::SysCall(sigaddset(&sigset, SIGHUP));
	util::SysCall(sigaddset(&sigset, SIGUSR1));
	ret = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
	if (ret != 0) {
		throw std::system_error(ret, std::generic_category());
	}
}

// シグナル処理スレッド (SIGUSR1 で終了)
void SignalThreadEntry(const sigset_t &sigset,
	std::unique_ptr<TaskServer> &server)
{
	int ret, sig;

	while (1) {
		// このスレッドでブロックを解除し sigset のうちどれかが届くまで待つ
		// 戻るときに再度ブロック
		ret = sigwait(&sigset, &sig);
		if (ret != 0) {
			throw std::system_error(ret, std::generic_category());
		}
		logger.Log(LogLevel::Info, "Signal: %d", sig);

		switch (sig) {
		case SIGINT:
			logger.Log(LogLevel::Info, "SIGINT");
			server->RequestShutdown(ServerResult::Shutdown);
			break;
		case SIGTERM:
			logger.Log(LogLevel::Info, "SIGTERM");
			server->RequestShutdown(ServerResult::Shutdown);
			break;
		case SIGHUP:
			logger.Log(LogLevel::Info, "SIGHUP");
			server->RequestShutdown(ServerResult::Reboot);
			break;
		case SIGUSR1:
			logger.Log(LogLevel::Info, "SIGUSR1");
			goto EXIT;
		default:
			logger.Log(LogLevel::Fatal, "Unknown signal: %d", sig);
			throw std::logic_error("unknown signal");
		}
	}
EXIT:
	logger.Log(LogLevel::Info, "Signal thread exit");
}

struct BootOpts {
	bool daemon = false;
};
BootOpts boot_opts;

void ParseArgs(int argc, char * const argv[])
{
	static const struct option long_opts[] = {
		{ "help",	no_argument,	nullptr,	'h' },
		{ "daemon",	no_argument,	nullptr,	'd' },
		{ 0, 0, 0, 0 },
	};
	const char *help_msg = R"(Usage:
--help
    Print this help and exit.
--daemon
    Start as daemon mode. (no stdin/stdout/stderr)
)";

	int c;
	int option_index = 0;
	while ((c = getopt_long(argc, argv, "", long_opts, &option_index)) != -1) {
		switch (c) {
		case 'h':
			std::puts(help_msg);
			std::exit(0);
		case 'd':
			boot_opts.daemon = true;
			break;
		case '?':
			// エラーは stderr に出してくれるのでそれに任せることにする
			std::exit(EXIT_FAILURE);
		default:
			throw std::logic_error("unknown getopt_long");
		}
	}
}

// 設定ファイル名
const char * const ConfigFile = "config.json";
const char * const ConfigFileFallback = "config.template.json";

// タスクの登録
void SetupTasks(const std::unique_ptr<TaskServer> &server)
{
	server->RegisterPeriodicTask(
		std::make_unique<task::HealthCheckTask>([](const struct tm &) {
			return true;
		}));
	server->RegisterPeriodicTask(
		std::make_unique<task::DdnsTask>([](const struct tm &) {
			return true;
		}));
	server->RegisterPeriodicTask(
		std::make_unique<task::TwitterTask>([](const struct tm &) {
			return true;
		}));
}

void BootMsg(TaskServer &server, const std::atomic<bool> &cancel)
{
	auto &twitter = system::Get().TwitterSystem;

	std::string git_branch, git_hash;
	{
		Process p("/usr/bin/git",
			{"rev-parse", "--symbolic-full-name", "HEAD"});
		p.WaitForExit();
		git_branch = util::OneLine(p.GetOut());
	}
	{
		Process p("/usr/bin/git", {"rev-parse", "HEAD"});
		p.WaitForExit();
		git_hash = util::OneLine(p.GetOut());
	}

	std::string msg;
	msg += '[';
	msg += util::DateTimeStr();
	msg += "] Boot... (C++ testing)\n";
	msg += git_branch;
	msg += '\n';
	msg += git_hash;

	twitter.Tweet(msg);
}

}	// namespace

#ifndef DISABLE_MAIN
int main(int argc, char *argv[])
{
	// コマンドライン引数のパース
	ParseArgs(argc, argv);

	// ログシステムの設定
	logger.AddStdOut(LogLevel::Trace);
	logger.AddFile(LogLevel::Info);

	// メインスレッドでシグナルマスクを設定する
	// メインスレッドから生成されたサブスレッドはこの設定を継承する
	// ref. man pthread_sigmask
	sigset_t sigset;
	SetupSignalMask(sigset);

	try {
		while (1) {
			// 設定ファイルのロード
			try {
				logger.Log(LogLevel::Info, "Load: %s", ConfigFile);
				config.LoadFile(ConfigFile);
			}
			catch (std::runtime_error &e) {
#ifndef NDEBUG
				// DEBUG
				logger.Log(LogLevel::Error, "Load config failed");
				logger.Log(LogLevel::Error, "%s", e.what());
				logger.Log(LogLevel::Warn,
					"DEBUG BUILD ONLY: load template file instead");
				logger.Log(LogLevel::Info, "Load: %s", ConfigFileFallback);
				config.LoadFile(ConfigFileFallback);
#else
				// RELEASE
				throw;
#endif
			}

			// システムコンポーネントの全初期化
			system::SafeSystem system;
			// web ページの初期化
			web::SetupPages();

			// サーバの作成、初期化
			auto server = std::make_unique<TaskServer>();
			SetupTasks(server);
			if (config.GetBool({"System", "AllTasksFirst"})) {
				logger.Log(LogLevel::Info, "Release all tasks for test");
				server->ReleaseAllForTest();
			}
			// 起動メッセージタスクを追加
			server->RegisterOneShotTask(std::make_unique<OneShotTask>(
				"BootMsg", BootMsg));

			// シグナル処理スレッドを立ち上げる
			// シグナルセットとタスクサーバへの参照を渡す
			std::thread sigth(SignalThreadEntry, sigset, std::ref(server));
			auto teardown = [&sigth]() {
				// シグナル処理スレッドを SIGUSR1 で終了させて join
				util::SysCall(kill(getpid(), SIGUSR1));
				sigth.join();
			};
			ServerResult result = ServerResult::None;
			try {
				// サーバスタート
				result = server->Run();
			}
			catch(...) {
				teardown();
				throw;
			}
			teardown();

			switch (result) {
			case ServerResult::Reboot:
			case ServerResult::ErrorReboot:
				break;
			case ServerResult::Shutdown:
				goto EXIT;
			case ServerResult::FatalShutdown:
				std::terminate();
				break;
			default:
				std::terminate();
				break;
			}
			// destruct server
			// destruct system
		}
	}
	catch (std::runtime_error &e) {
		logger.Log(LogLevel::Fatal, "Runtime error");
		logger.Log(LogLevel::Fatal, "%s", e.what());
		return 1;
	}
	catch (std::exception &e) {
		logger.Log(LogLevel::Fatal, "Fatal error");
		logger.Log(LogLevel::Fatal, "%s", e.what());
		throw;
	}
	catch (...) {
		throw;
	}
EXIT:
	return 0;
}
#endif
<commit_msg>周期タスクの時間を本番向けにする<commit_after>#include "logger.h"
#include "config.h"
#include "util.h"
#include "exec.h"
#include "taskserver.h"
#include "system/system.h"
#include "task/task.h"
#include "web/webpage.h"
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <cstdio>
#include <string>
#include <thread>
#include <json11.hpp>

namespace {

using namespace shanghai;
using namespace std::string_literals;

// 処理したいシグナルを全てブロックし、シグナル処理スレッドでハンドルする
// ブロックしたシグナルセットを sigset に返す
void SetupSignalMask(sigset_t &sigset)
{
	int ret;

	util::SysCall(sigemptyset(&sigset));
	util::SysCall(sigaddset(&sigset, SIGINT));
	util::SysCall(sigaddset(&sigset, SIGTERM));
	util::SysCall(sigaddset(&sigset, SIGHUP));
	util::SysCall(sigaddset(&sigset, SIGUSR1));
	ret = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
	if (ret != 0) {
		throw std::system_error(ret, std::generic_category());
	}
}

// シグナル処理スレッド (SIGUSR1 で終了)
void SignalThreadEntry(const sigset_t &sigset,
	std::unique_ptr<TaskServer> &server)
{
	int ret, sig;

	while (1) {
		// このスレッドでブロックを解除し sigset のうちどれかが届くまで待つ
		// 戻るときに再度ブロック
		ret = sigwait(&sigset, &sig);
		if (ret != 0) {
			throw std::system_error(ret, std::generic_category());
		}
		logger.Log(LogLevel::Info, "Signal: %d", sig);

		switch (sig) {
		case SIGINT:
			logger.Log(LogLevel::Info, "SIGINT");
			server->RequestShutdown(ServerResult::Shutdown);
			break;
		case SIGTERM:
			logger.Log(LogLevel::Info, "SIGTERM");
			server->RequestShutdown(ServerResult::Shutdown);
			break;
		case SIGHUP:
			logger.Log(LogLevel::Info, "SIGHUP");
			server->RequestShutdown(ServerResult::Reboot);
			break;
		case SIGUSR1:
			logger.Log(LogLevel::Info, "SIGUSR1");
			goto EXIT;
		default:
			logger.Log(LogLevel::Fatal, "Unknown signal: %d", sig);
			throw std::logic_error("unknown signal");
		}
	}
EXIT:
	logger.Log(LogLevel::Info, "Signal thread exit");
}

struct BootOpts {
	bool daemon = false;
};
BootOpts boot_opts;

void ParseArgs(int argc, char * const argv[])
{
	static const struct option long_opts[] = {
		{ "help",	no_argument,	nullptr,	'h' },
		{ "daemon",	no_argument,	nullptr,	'd' },
		{ 0, 0, 0, 0 },
	};
	const char *help_msg = R"(Usage:
--help
    Print this help and exit.
--daemon
    Start as daemon mode. (no stdin/stdout/stderr)
)";

	int c;
	int option_index = 0;
	while ((c = getopt_long(argc, argv, "", long_opts, &option_index)) != -1) {
		switch (c) {
		case 'h':
			std::puts(help_msg);
			std::exit(0);
		case 'd':
			boot_opts.daemon = true;
			break;
		case '?':
			// エラーは stderr に出してくれるのでそれに任せることにする
			std::exit(EXIT_FAILURE);
		default:
			throw std::logic_error("unknown getopt_long");
		}
	}
}

// 設定ファイル名
const char * const ConfigFile = "config.json";
const char * const ConfigFileFallback = "config.template.json";

// タスクの登録
void SetupTasks(const std::unique_ptr<TaskServer> &server)
{
	server->RegisterPeriodicTask(
		std::make_unique<task::HealthCheckTask>([](const struct tm &tm) {
			const std::array<int, 2> hours = { 6, 18 };
			return tm.tm_min == 0 && std::find(
				hours.begin(), hours.end(), tm.tm_hour) != hours.end();
		}));
	server->RegisterPeriodicTask(
		std::make_unique<task::DdnsTask>([](const struct tm &tm) {
			return tm.tm_min == 0 && tm.tm_hour == 3;
		}));
	server->RegisterPeriodicTask(
		std::make_unique<task::TwitterTask>([](const struct tm &tm) {
			return (tm.tm_min + 2) % 5 == 0;
		}));
}

void BootMsg(TaskServer &server, const std::atomic<bool> &cancel)
{
	auto &twitter = system::Get().TwitterSystem;

	std::string git_branch, git_hash;
	{
		Process p("/usr/bin/git",
			{"rev-parse", "--symbolic-full-name", "HEAD"});
		p.WaitForExit();
		git_branch = util::OneLine(p.GetOut());
	}
	{
		Process p("/usr/bin/git", {"rev-parse", "HEAD"});
		p.WaitForExit();
		git_hash = util::OneLine(p.GetOut());
	}

	std::string msg;
	msg += '[';
	msg += util::DateTimeStr();
	msg += "] Boot... (C++ testing)\n";
	msg += git_branch;
	msg += '\n';
	msg += git_hash;

	twitter.Tweet(msg);
}

}	// namespace

#ifndef DISABLE_MAIN
int main(int argc, char *argv[])
{
	// コマンドライン引数のパース
	ParseArgs(argc, argv);

	// ログシステムの設定
	logger.AddStdOut(LogLevel::Trace);
	logger.AddFile(LogLevel::Info);

	// メインスレッドでシグナルマスクを設定する
	// メインスレッドから生成されたサブスレッドはこの設定を継承する
	// ref. man pthread_sigmask
	sigset_t sigset;
	SetupSignalMask(sigset);

	try {
		while (1) {
			// 設定ファイルのロード
			try {
				logger.Log(LogLevel::Info, "Load: %s", ConfigFile);
				config.LoadFile(ConfigFile);
			}
			catch (std::runtime_error &e) {
#ifndef NDEBUG
				// DEBUG
				logger.Log(LogLevel::Error, "Load config failed");
				logger.Log(LogLevel::Error, "%s", e.what());
				logger.Log(LogLevel::Warn,
					"DEBUG BUILD ONLY: load template file instead");
				logger.Log(LogLevel::Info, "Load: %s", ConfigFileFallback);
				config.LoadFile(ConfigFileFallback);
#else
				// RELEASE
				throw;
#endif
			}

			// システムコンポーネントの全初期化
			system::SafeSystem system;
			// web ページの初期化
			web::SetupPages();

			// サーバの作成、初期化
			auto server = std::make_unique<TaskServer>();
			SetupTasks(server);
			if (config.GetBool({"System", "AllTasksFirst"})) {
				logger.Log(LogLevel::Info, "Release all tasks for test");
				server->ReleaseAllForTest();
			}
			// 起動メッセージタスクを追加
			server->RegisterOneShotTask(std::make_unique<OneShotTask>(
				"BootMsg", BootMsg));

			// シグナル処理スレッドを立ち上げる
			// シグナルセットとタスクサーバへの参照を渡す
			std::thread sigth(SignalThreadEntry, sigset, std::ref(server));
			auto teardown = [&sigth]() {
				// シグナル処理スレッドを SIGUSR1 で終了させて join
				util::SysCall(kill(getpid(), SIGUSR1));
				sigth.join();
			};
			ServerResult result = ServerResult::None;
			try {
				// サーバスタート
				result = server->Run();
			}
			catch(...) {
				teardown();
				throw;
			}
			teardown();

			switch (result) {
			case ServerResult::Reboot:
			case ServerResult::ErrorReboot:
				break;
			case ServerResult::Shutdown:
				goto EXIT;
			case ServerResult::FatalShutdown:
				std::terminate();
				break;
			default:
				std::terminate();
				break;
			}
			// destruct server
			// destruct system
		}
	}
	catch (std::runtime_error &e) {
		logger.Log(LogLevel::Fatal, "Runtime error");
		logger.Log(LogLevel::Fatal, "%s", e.what());
		return 1;
	}
	catch (std::exception &e) {
		logger.Log(LogLevel::Fatal, "Fatal error");
		logger.Log(LogLevel::Fatal, "%s", e.what());
		throw;
	}
	catch (...) {
		throw;
	}
EXIT:
	return 0;
}
#endif
<|endoftext|>


<commit_before><commit_msg>Remove unused inline constructor<commit_after><|endoftext|>


<commit_before>/*
Contact: cvetan.cheshkov@cern.ch
Link: http://alisoft.cern.ch/viewvc/trunk/ITS/ITSSPDVertexDiamondda.cxx?root=AliRoot&view=log , /afs/cern.ch/user/c/cheshkov/public/ITS/VD_da_test.date , /afs/cern.ch/user/c/cheshkov/public/08000058338016.30.root.date.gz
Reference Run: 58338
Run Type: PHYSICS
DA Type: MON
Number of events needed: 100
Input Files: GRP/Geometry/Data , ITS/Align/Data , spd_noisy_ocdb , spd_dead_ocdb , TRIGGER/SPD/PITConditions (all the files are taken from SPD daqDetDB)
Output Files: SPDVertexDiamondDA.root
Trigger types used: PHYSICS, SPD-F0
*/

#define OUTPUT_FILE "SPDVertexDiamondDA.root"
#define N_EVENTS_AUTOSAVE 50

extern "C" {
#include "daqDA.h"
}

#include "event.h"
#include "monitor.h"

#ifdef ALI_AMORE
#include <AmoreDA.h>
//int amore::da::Updated(char const*) {}
#endif

#include <TPluginManager.h>
#include <TROOT.h>
#include <TH1.h>
#include <TH2.h>
#include <TSystem.h>
#include <TGeoGlobalMagField.h>

#include "AliLog.h"
#include "AliMagF.h"
#include "AliRawReaderDate.h"
#include "AliCDBManager.h"
#include "AliITSMeanVertexer.h"

int main(int argc, char **argv) {

  gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
					"*",
					"TStreamerInfo",
					"RIO",
					"TStreamerInfo()");

  int status;
  if (argc<2) {
    printf("Wrong number of arguments\n");
    return -1;
  }

  /* define data source : this is argument 1 */
  status=monitorSetDataSource( argv[1] );
  if (status!=0) {
    printf("monitorSetDataSource() failed : %s\n",monitorDecodeError(status));
    return -1;
  }

  /* declare monitoring program */
  status=monitorDeclareMp( __FILE__ );
  if (status!=0) {
    printf("monitorDeclareMp() failed : %s\n",monitorDecodeError(status));
    return -1;
  }

  /* define wait event timeout - 1s max */
  monitorSetNowait();
  monitorSetNoWaitNetworkTimeout(1000);

  /* log start of process */
  printf("Vertex-Diamond SPD DA started\n");

  /* init some counters */
  int nevents_with_vertex = 0;
  int nevents_physics=0;
  int nevents_total=0;

  struct eventHeaderStruct *event;
  eventTypeType eventT;

  // Get run number
  if (getenv("DATE_RUN_NUMBER")==0) {
    printf("DATE_RUN_NUMBER not properly set.\n");
    return -1;
  }
  int runNr = atoi(getenv("DATE_RUN_NUMBER"));

  // Get the necessary OCDB files from the DAQ detector DB
  if (gSystem->AccessPathName("localOCDB/GRP/Geometry/Data",kFileExists)) {
    if (gSystem->mkdir("localOCDB/GRP/Geometry/Data",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/GRP/Geometry/Data");
      return -1;
    }
  }
  status = daqDA_DB_getFile("GRP/Geometry/Data","localOCDB/GRP/Geometry/Data/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get geometry file (GRP/Geometry/Data) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Align/Data",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Align/Data",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Align/Data");
      return -1;
    }
  }
  status = daqDA_DB_getFile("ITS/Align/Data","localOCDB/ITS/Align/Data/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get its-alignment file (ITS/Align/Data) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Calib/SPDNoisy",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Calib/SPDNoisy",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Calib/SPDNoisy");
      return -1;
    }
  }
  status = daqDA_DB_getFile("spd_noisy_ocdb","localOCDB/ITS/Calib/SPDNoisy/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd file (spd_noisy_ocdb) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Calib/SPDDead",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Calib/SPDDead",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Calib/SPDDead");
      return -1;
    }
  }
  status = daqDA_DB_getFile("spd_dead_ocdb","localOCDB/ITS/Calib/SPDDead/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd file (spd_dead_ocdb) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/TRIGGER/SPD/PITConditions",kFileExists)) {
    if (gSystem->mkdir("localOCDB/TRIGGER/SPD/PITConditions",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/TRIGGER/SPD/PITConditions");
      return -1;
    }
  }
  status = daqDA_DB_getFile("TRIGGER/SPD/PITConditions","localOCDB/TRIGGER/SPD/PITConditions/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd trigger file (TRIGGER/SPD/PITConditions) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  // Global initializations

  // The B filed is required in AliITSClusterFinderV2SPD
  // for the Lorentz angle correction. B set to 0.
  TGeoGlobalMagField::Instance()->SetField(new AliMagF("Maps","Maps", 0., 0., AliMagF::k5kGUniform));
  AliLog::SetGlobalLogLevel(AliLog::kError);
  AliCDBManager *man = AliCDBManager::Instance();
  man->SetDefaultStorage("local://localOCDB");
  man->SetRun(runNr);

  // Init mean vertexer
  AliITSMeanVertexer *mv = new AliITSMeanVertexer();
  if (!mv->Init()) {
    printf("Initialization of mean vertexer object failed ! Check the log for details");
    return -1;
  }

  // Initialization of AMORE sender
#ifdef ALI_AMORE
  amore::da::AmoreDA vtxAmore(amore::da::AmoreDA::kSender);
#endif
  /* main loop (infinite) */
  for(;;) {

    /* check shutdown condition */
    if (daqDA_checkShutdown()) {break;}

    /* get next event (blocking call until timeout) */
    status=monitorGetEventDynamic((void **)&event);
    if (status==MON_ERR_EOF) {
      printf ("End of File detected\n");
      break; /* end of monitoring file has been reached */
    }

    if (status!=0) {
      printf("monitorGetEventDynamic() failed : %s\n",monitorDecodeError(status));
      break;
    }

    /* retry if got no event */
    if (event==NULL) {
      continue;
    }

    nevents_total++;
    eventT=event->eventType;
    switch (event->eventType){

      /* START OF RUN */
    case START_OF_RUN:
      break;
      /* END START OF RUN */

    /* END OF RUN */
    case END_OF_RUN:
      break;

    case PHYSICS_EVENT:
      nevents_physics++;
      AliRawReader *rawReader = new AliRawReaderDate((void*)event);

      // Run mean-vertexer reco
      if (mv->Reconstruct(rawReader)) nevents_with_vertex++;

      // Auto save
      if ((nevents_physics%N_EVENTS_AUTOSAVE) == 0) {
	mv->WriteVertices(OUTPUT_FILE);

#ifdef ALI_AMORE
      // send the histos to AMORE pool
	printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexXY()->GetName(),mv->GetVertexXY()));
	printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexZ()->GetName(),mv->GetVertexZ()));
#endif
      }

      delete rawReader;
    }

    /* free resources */
    free(event);

    /* exit when last event received, no need to wait for TERM signal */
    if (eventT==END_OF_RUN) {
      printf("EOR event detected\n");
      break;
    }
  }

  mv->WriteVertices(OUTPUT_FILE);

#ifdef ALI_AMORE
  // send the histos to AMORE pool
  printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexXY()->GetName(),mv->GetVertexXY()));
  printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexZ()->GetName(),mv->GetVertexZ()));
#endif

  delete mv;

  /* write report */
  printf("Run #%s, received %d events with vertex, out of %d physics and out of %d total events\n",getenv("DATE_RUN_NUMBER"),nevents_with_vertex,nevents_physics,nevents_total);

  status=0;

  /* export file to FXS */
  if (daqDA_FES_storeFile(OUTPUT_FILE, "VertexDiamond")) {
    status=-2;
  }

  return status;
}
<commit_msg>mods to use mfchebKGI_sym.root in online mode (AliMagF constructor) - Annalisa<commit_after>/*
Contact: cvetan.cheshkov@cern.ch
Link: http://alisoft.cern.ch/viewvc/trunk/ITS/ITSSPDVertexDiamondda.cxx?root=AliRoot&view=log , /afs/cern.ch/user/c/cheshkov/public/ITS/VD_da_test.date , /afs/cern.ch/user/c/cheshkov/public/08000058338016.30.root.date.gz
Reference Run: 58338
Run Type: PHYSICS
DA Type: MON
Number of events needed: 100
Input Files: GRP/Geometry/Data , ITS/Align/Data , spd_noisy_ocdb , spd_dead_ocdb , TRIGGER/SPD/PITConditions (all the files are taken from SPD daqDetDB)
Output Files: SPDVertexDiamondDA.root
Trigger types used: PHYSICS, SPD-F0
*/

#define OUTPUT_FILE "SPDVertexDiamondDA.root"
#define N_EVENTS_AUTOSAVE 50

extern "C" {
#include "daqDA.h"
}

#include "event.h"
#include "monitor.h"

#ifdef ALI_AMORE
#include <AmoreDA.h>
//int amore::da::Updated(char const*) {}
#endif

#include <TPluginManager.h>
#include <TROOT.h>
#include <TH1.h>
#include <TH2.h>
#include <TSystem.h>
#include <TGeoGlobalMagField.h>

#include "AliLog.h"
#include "AliMagF.h"
#include "AliRawReaderDate.h"
#include "AliCDBManager.h"
#include "AliITSMeanVertexer.h"

int main(int argc, char **argv) {

  gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
					"*",
					"TStreamerInfo",
					"RIO",
					"TStreamerInfo()");

  int status;
  if (argc<2) {
    printf("Wrong number of arguments\n");
    return -1;
  }

  /* define data source : this is argument 1 */
  status=monitorSetDataSource( argv[1] );
  if (status!=0) {
    printf("monitorSetDataSource() failed : %s\n",monitorDecodeError(status));
    return -1;
  }

  /* declare monitoring program */
  status=monitorDeclareMp( __FILE__ );
  if (status!=0) {
    printf("monitorDeclareMp() failed : %s\n",monitorDecodeError(status));
    return -1;
  }

  /* define wait event timeout - 1s max */
  monitorSetNowait();
  monitorSetNoWaitNetworkTimeout(1000);

  /* log start of process */
  printf("Vertex-Diamond SPD DA started\n");

  /* init some counters */
  int nevents_with_vertex = 0;
  int nevents_physics=0;
  int nevents_total=0;

  struct eventHeaderStruct *event;
  eventTypeType eventT;

  // Get run number
  if (getenv("DATE_RUN_NUMBER")==0) {
    printf("DATE_RUN_NUMBER not properly set.\n");
    return -1;
  }
  int runNr = atoi(getenv("DATE_RUN_NUMBER"));

  // Get the necessary OCDB files from the DAQ detector DB
  if (gSystem->AccessPathName("localOCDB/GRP/Geometry/Data",kFileExists)) {
    if (gSystem->mkdir("localOCDB/GRP/Geometry/Data",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/GRP/Geometry/Data");
      return -1;
    }
  }
  status = daqDA_DB_getFile("GRP/Geometry/Data","localOCDB/GRP/Geometry/Data/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get geometry file (GRP/Geometry/Data) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Align/Data",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Align/Data",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Align/Data");
      return -1;
    }
  }
  status = daqDA_DB_getFile("ITS/Align/Data","localOCDB/ITS/Align/Data/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get its-alignment file (ITS/Align/Data) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Calib/SPDNoisy",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Calib/SPDNoisy",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Calib/SPDNoisy");
      return -1;
    }
  }
  status = daqDA_DB_getFile("spd_noisy_ocdb","localOCDB/ITS/Calib/SPDNoisy/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd file (spd_noisy_ocdb) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/ITS/Calib/SPDDead",kFileExists)) {
    if (gSystem->mkdir("localOCDB/ITS/Calib/SPDDead",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/ITS/Calib/SPDDead");
      return -1;
    }
  }
  status = daqDA_DB_getFile("spd_dead_ocdb","localOCDB/ITS/Calib/SPDDead/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd file (spd_dead_ocdb) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  if (gSystem->AccessPathName("localOCDB/TRIGGER/SPD/PITConditions",kFileExists)) {
    if (gSystem->mkdir("localOCDB/TRIGGER/SPD/PITConditions",kTRUE) != 0) {
      printf("Failed to create directory: localOCDB/TRIGGER/SPD/PITConditions");
      return -1;
    }
  }
  status = daqDA_DB_getFile("TRIGGER/SPD/PITConditions","localOCDB/TRIGGER/SPD/PITConditions/Run0_999999999_v0_s0.root");
  if (status) {
    printf("Failed to get spd trigger file (TRIGGER/SPD/PITConditions) from DAQdetDB, status=%d\n", status);
    return -1;
  }

 status = daqDA_DB_getFile("mfchebKGI_sym.root","localOCDB/mfchebKGI_sym.root");
  if (status) {
    printf("Failed to get spd file (mfchebKGI_sym.root) from DAQdetDB, status=%d\n", status);
    return -1;
  }

  // Global initializations

  // The B filed is required in AliITSClusterFinderV2SPD
  // for the Lorentz angle correction. B set to 0.
  TGeoGlobalMagField::Instance()->SetField(new AliMagF("Maps","Maps", 0., 0., AliMagF::k5kGUniform,AliMagF::kBeamTypeAA,-1,2,15,"localOCDB/mfchebKGI_sym.root"));
  AliLog::SetGlobalLogLevel(AliLog::kError);
  AliCDBManager *man = AliCDBManager::Instance();
  man->SetDefaultStorage("local://localOCDB");
  man->SetRun(runNr);

  // Init mean vertexer
  AliITSMeanVertexer *mv = new AliITSMeanVertexer();
  if (!mv->Init()) {
    printf("Initialization of mean vertexer object failed ! Check the log for details");
    return -1;
  }

  // Initialization of AMORE sender
#ifdef ALI_AMORE
  amore::da::AmoreDA vtxAmore(amore::da::AmoreDA::kSender);
#endif
  /* main loop (infinite) */
  for(;;) {

    /* check shutdown condition */
    if (daqDA_checkShutdown()) {break;}

    /* get next event (blocking call until timeout) */
    status=monitorGetEventDynamic((void **)&event);
    if (status==MON_ERR_EOF) {
      printf ("End of File detected\n");
      break; /* end of monitoring file has been reached */
    }

    if (status!=0) {
      printf("monitorGetEventDynamic() failed : %s\n",monitorDecodeError(status));
      break;
    }

    /* retry if got no event */
    if (event==NULL) {
      continue;
    }

    nevents_total++;
    eventT=event->eventType;
    switch (event->eventType){

      /* START OF RUN */
    case START_OF_RUN:
      break;
      /* END START OF RUN */

    /* END OF RUN */
    case END_OF_RUN:
      break;

    case PHYSICS_EVENT:
      nevents_physics++;
      AliRawReader *rawReader = new AliRawReaderDate((void*)event);

      // Run mean-vertexer reco
      if (mv->Reconstruct(rawReader)) nevents_with_vertex++;

      // Auto save
      if ((nevents_physics%N_EVENTS_AUTOSAVE) == 0) {
	mv->WriteVertices(OUTPUT_FILE);

#ifdef ALI_AMORE
      // send the histos to AMORE pool
	printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexXY()->GetName(),mv->GetVertexXY()));
	printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexZ()->GetName(),mv->GetVertexZ()));
#endif
      }

      delete rawReader;
    }

    /* free resources */
    free(event);

    /* exit when last event received, no need to wait for TERM signal */
    if (eventT==END_OF_RUN) {
      printf("EOR event detected\n");
      break;
    }
  }

  mv->WriteVertices(OUTPUT_FILE);

#ifdef ALI_AMORE
  // send the histos to AMORE pool
  printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexXY()->GetName(),mv->GetVertexXY()));
  printf("AMORE send status: %d\n",vtxAmore.Send(mv->GetVertexZ()->GetName(),mv->GetVertexZ()));
#endif

  delete mv;

  /* write report */
  printf("Run #%s, received %d events with vertex, out of %d physics and out of %d total events\n",getenv("DATE_RUN_NUMBER"),nevents_with_vertex,nevents_physics,nevents_total);

  status=0;

  /* export file to FXS */
  if (daqDA_FES_storeFile(OUTPUT_FILE, "VertexDiamond")) {
    status=-2;
  }

  return status;
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 <string.h>
#include <cmath>
#include <vector>
#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace strided_slice {

enum KernelType {
  kReference,
  // TODO(soroosh): add kGenericOptimized
};

constexpr int kInputTensor = 0;
constexpr int kBeginTensor = 1;
constexpr int kEndTensor = 2;
constexpr int kStridesTensor = 3;
constexpr int kOutputTensor = 0;

struct StridedSliceContext {
  StridedSliceContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteStridedSliceParams*>(node->builtin_data);
    input = GetInput(context, node, kInputTensor);
    begin = GetInput(context, node, kBeginTensor);
    end = GetInput(context, node, kEndTensor);
    strides = GetInput(context, node, kStridesTensor);
    output = GetOutput(context, node, kOutputTensor);
    dims = NumDimensions(input);
  }
  const TfLiteStridedSliceParams* params;
  const TfLiteTensor* input;
  const TfLiteTensor* begin;
  const TfLiteTensor* end;
  const TfLiteTensor* strides;
  TfLiteTensor* output;
  int dims;
};

// This Op only supports 1-4D cases and since we use the reference 4D
// implementation, the 1-3D tensors are mapped to 4D.
const int kMaxDim = 4;

inline int32_t PositiveRemainder(int32_t dividend, int32_t divisor) {
  return (divisor + (dividend % divisor)) % divisor;
}

inline int32_t ClampedIndex(int32_t index, int dim, bool pos_stride) {
  return pos_stride
             ? (index >= dim ? dim
                             : PositiveRemainder(
                                   std::min(std::max(index, -dim), dim), dim))
             : (index < -dim
                    ? -1
                    : PositiveRemainder(
                          std::min(std::max(index, -dim), dim - 1), dim));
}

// TODO(b/77971377) this logic should be removed, as it's a duplication of
// StartForAxis() & StopForAxis() in kernels/internal/reference/reference_ops.h
inline int32_t GetBeginValueAtIndex(StridedSliceContext* op_context, int idx) {
  const int dim = op_context->input->dims->data[idx];
  const bool pos_stride = GetTensorData<int32_t>(op_context->strides)[idx] > 0;
  return op_context->params->begin_mask & (1 << idx)
             ? pos_stride ? 0 : dim - 1
             : ClampedIndex(GetTensorData<int32_t>(op_context->begin)[idx], dim,
                            pos_stride);
}

inline int32_t GetEndValueAtIndex(StridedSliceContext* op_context, int idx) {
  const int dim = op_context->input->dims->data[idx];
  const bool pos_stride = GetTensorData<int32_t>(op_context->strides)[idx] > 0;
  return op_context->params->end_mask & (1 << idx)
             ? pos_stride ? dim : -1
             : ClampedIndex(GetTensorData<int32_t>(op_context->end)[idx], dim,
                            pos_stride);
}

// Processes the indexing tensors (begin, end and strides) to resize the
// output tensor. This function is callable from both Prepare() and Eval() as
// long as the caller ensures the indexing tensors are present.
TfLiteStatus ResizeOutputTensor(TfLiteContext* context,
                                StridedSliceContext* op_context) {
  std::vector<int> output_shape_vector;

  for (int idx = op_context->dims - 1; idx >= 0; --idx) {
    int32_t stride = GetTensorData<int32_t>(op_context->strides)[idx];
    TF_LITE_ENSURE_MSG(context, stride != 0, "stride value has to be non-zero");

    int32_t begin = GetBeginValueAtIndex(op_context, idx);
    int32_t end = GetEndValueAtIndex(op_context, idx);

    // When shrinking an axis, the end position does not matter (and can be
    // incorrect when negative indexing is used, see Issue #19260). Always use
    // begin + 1 to generate a length 1 slice, since begin has
    // already been adjusted for negative indices by GetBeginValueAtIndex.
    const bool shrink_axis = op_context->params->shrink_axis_mask & (1 << idx);
    if (shrink_axis) {
      end = begin + 1;
    }

    // This is valid for both positive and negative strides
    int32_t dim_shape = ceil((end - begin) / static_cast<float>(stride));
    dim_shape = dim_shape < 0 ? 0 : dim_shape;
    if (!shrink_axis) {
      output_shape_vector.push_back(dim_shape);
    }
  }

  TfLiteIntArray* output_shape =
      TfLiteIntArrayCreate(output_shape_vector.size());

  std::reverse_copy(output_shape_vector.begin(), output_shape_vector.end(),
                    output_shape->data);

  TF_LITE_ENSURE_STATUS(
      context->ResizeTensor(context, op_context->output, output_shape));

  return kTfLiteOk;
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 4);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  StridedSliceContext op_context(context, node);

  // Ensure validity of input tensor and its dimension
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.begin), 1);
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.end), 1);
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.strides), 1);
  TF_LITE_ENSURE_EQ(context, op_context.input->type, op_context.output->type);
  // Only INT32 begin/end/strides are supported
  // TODO(soroosh) add support for INT64
  TF_LITE_ENSURE_EQ(context, op_context.begin->type, kTfLiteInt32);
  TF_LITE_ENSURE_EQ(context, op_context.end->type, kTfLiteInt32);
  TF_LITE_ENSURE_EQ(context, op_context.strides->type, kTfLiteInt32);
  TF_LITE_ENSURE_MSG(context, op_context.dims <= 4,
                     "StridedSlice op only supports 1D-4D input arrays.");

  // TODO(soroosh): add the following missing functionalities
  TF_LITE_ENSURE_MSG(context, op_context.params->ellipsis_mask == 0,
                     "ellipsis_mask is not implemented yet.");
  TF_LITE_ENSURE_MSG(context, op_context.params->new_axis_mask == 0,
                     "new_axis_mask is not implemented yet.");

  // Postpone allocation of output if any of the indexing tensors is not
  // constant
  if (!(IsConstantTensor(op_context.begin) &&
        IsConstantTensor(op_context.end) &&
        IsConstantTensor(op_context.strides))) {
    SetTensorToDynamic(op_context.output);
    return kTfLiteOk;
  }
  return ResizeOutputTensor(context, &op_context);
}

template <KernelType kernel_type>
TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  StridedSliceContext op_context(context, node);

  if (IsDynamicTensor(op_context.output)) {
    TF_LITE_ENSURE_OK(context, ResizeOutputTensor(context, &op_context));
  }

  std::vector<int32_t> starts;
  std::vector<int32_t> stops;
  std::vector<int32_t> strides;

  for (int i = op_context.dims; i < kMaxDim; i++) {
    starts.emplace_back(0);
    stops.emplace_back(1);
    strides.emplace_back(1);
  }

  for (int idx = 0; idx < op_context.dims; ++idx) {
    starts.emplace_back(GetTensorData<int32_t>(op_context.begin)[idx]);
    stops.emplace_back(GetTensorData<int32_t>(op_context.end)[idx]);
    strides.emplace_back(GetTensorData<int32_t>(op_context.strides)[idx]);
  }

  int begin_mask = op_context.params->begin_mask << (4 - op_context.dims);
  int end_mask = op_context.params->end_mask << (4 - op_context.dims);
  int shrink_axis_mask = op_context.params->shrink_axis_mask
                         << (4 - op_context.dims);
  TF_LITE_ENSURE_EQ(context, starts.size(), 4);
  auto op_params = ::tflite::strided_slice::BuildStridedSliceParams(
      begin_mask, end_mask, shrink_axis_mask, starts, stops, strides);

#define TF_LITE_STRIDED_SLICE(kernel_type, data_type)                    \
  kernel_type::StridedSlice(op_params, GetTensorShape(op_context.input), \
                            GetTensorData<data_type>(op_context.input),  \
                            GetTensorShape(op_context.output),           \
                            GetTensorData<data_type>(op_context.output))

  switch (op_context.input->type) {
    case kTfLiteFloat32:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, float);
      }
      break;
    case kTfLiteInt32:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int32_t);
      }
      break;
    case kTfLiteInt64:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int64_t);
      }
      break;
    case kTfLiteUInt8:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, uint8_t);
      }
      break;
    case kTfLiteInt8:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int8_t);
      }
      break;
    default:
      context->ReportError(context,
                           "Type %d is currently not supported "
                           "by StridedSlice.",
                           op_context.input->type);
      return kTfLiteError;
  }
#undef TF_LITE_STRIDED_SLICE
  return kTfLiteOk;
}

}  // namespace strided_slice

TfLiteRegistration* Register_STRIDED_SLICE_REF() {
  static TfLiteRegistration r = {
      nullptr, nullptr, strided_slice::Prepare,
      strided_slice::Eval<strided_slice::kReference>};
  return &r;
}

// TODO(soroosh): add optimized
TfLiteRegistration* Register_STRIDED_SLICE() {
  return Register_STRIDED_SLICE_REF();
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<commit_msg>Qualify calls to some functions from <cmath>.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 <string.h>
#include <cmath>
#include <vector>
#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace strided_slice {

enum KernelType {
  kReference,
  // TODO(soroosh): add kGenericOptimized
};

constexpr int kInputTensor = 0;
constexpr int kBeginTensor = 1;
constexpr int kEndTensor = 2;
constexpr int kStridesTensor = 3;
constexpr int kOutputTensor = 0;

struct StridedSliceContext {
  StridedSliceContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteStridedSliceParams*>(node->builtin_data);
    input = GetInput(context, node, kInputTensor);
    begin = GetInput(context, node, kBeginTensor);
    end = GetInput(context, node, kEndTensor);
    strides = GetInput(context, node, kStridesTensor);
    output = GetOutput(context, node, kOutputTensor);
    dims = NumDimensions(input);
  }
  const TfLiteStridedSliceParams* params;
  const TfLiteTensor* input;
  const TfLiteTensor* begin;
  const TfLiteTensor* end;
  const TfLiteTensor* strides;
  TfLiteTensor* output;
  int dims;
};

// This Op only supports 1-4D cases and since we use the reference 4D
// implementation, the 1-3D tensors are mapped to 4D.
const int kMaxDim = 4;

inline int32_t PositiveRemainder(int32_t dividend, int32_t divisor) {
  return (divisor + (dividend % divisor)) % divisor;
}

inline int32_t ClampedIndex(int32_t index, int dim, bool pos_stride) {
  return pos_stride
             ? (index >= dim ? dim
                             : PositiveRemainder(
                                   std::min(std::max(index, -dim), dim), dim))
             : (index < -dim
                    ? -1
                    : PositiveRemainder(
                          std::min(std::max(index, -dim), dim - 1), dim));
}

// TODO(b/77971377) this logic should be removed, as it's a duplication of
// StartForAxis() & StopForAxis() in kernels/internal/reference/reference_ops.h
inline int32_t GetBeginValueAtIndex(StridedSliceContext* op_context, int idx) {
  const int dim = op_context->input->dims->data[idx];
  const bool pos_stride = GetTensorData<int32_t>(op_context->strides)[idx] > 0;
  return op_context->params->begin_mask & (1 << idx)
             ? pos_stride ? 0 : dim - 1
             : ClampedIndex(GetTensorData<int32_t>(op_context->begin)[idx], dim,
                            pos_stride);
}

inline int32_t GetEndValueAtIndex(StridedSliceContext* op_context, int idx) {
  const int dim = op_context->input->dims->data[idx];
  const bool pos_stride = GetTensorData<int32_t>(op_context->strides)[idx] > 0;
  return op_context->params->end_mask & (1 << idx)
             ? pos_stride ? dim : -1
             : ClampedIndex(GetTensorData<int32_t>(op_context->end)[idx], dim,
                            pos_stride);
}

// Processes the indexing tensors (begin, end and strides) to resize the
// output tensor. This function is callable from both Prepare() and Eval() as
// long as the caller ensures the indexing tensors are present.
TfLiteStatus ResizeOutputTensor(TfLiteContext* context,
                                StridedSliceContext* op_context) {
  std::vector<int> output_shape_vector;

  for (int idx = op_context->dims - 1; idx >= 0; --idx) {
    int32_t stride = GetTensorData<int32_t>(op_context->strides)[idx];
    TF_LITE_ENSURE_MSG(context, stride != 0, "stride value has to be non-zero");

    int32_t begin = GetBeginValueAtIndex(op_context, idx);
    int32_t end = GetEndValueAtIndex(op_context, idx);

    // When shrinking an axis, the end position does not matter (and can be
    // incorrect when negative indexing is used, see Issue #19260). Always use
    // begin + 1 to generate a length 1 slice, since begin has
    // already been adjusted for negative indices by GetBeginValueAtIndex.
    const bool shrink_axis = op_context->params->shrink_axis_mask & (1 << idx);
    if (shrink_axis) {
      end = begin + 1;
    }

    // This is valid for both positive and negative strides
    int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
    dim_shape = dim_shape < 0 ? 0 : dim_shape;
    if (!shrink_axis) {
      output_shape_vector.push_back(dim_shape);
    }
  }

  TfLiteIntArray* output_shape =
      TfLiteIntArrayCreate(output_shape_vector.size());

  std::reverse_copy(output_shape_vector.begin(), output_shape_vector.end(),
                    output_shape->data);

  TF_LITE_ENSURE_STATUS(
      context->ResizeTensor(context, op_context->output, output_shape));

  return kTfLiteOk;
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 4);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  StridedSliceContext op_context(context, node);

  // Ensure validity of input tensor and its dimension
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.begin), 1);
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.end), 1);
  TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.strides), 1);
  TF_LITE_ENSURE_EQ(context, op_context.input->type, op_context.output->type);
  // Only INT32 begin/end/strides are supported
  // TODO(soroosh) add support for INT64
  TF_LITE_ENSURE_EQ(context, op_context.begin->type, kTfLiteInt32);
  TF_LITE_ENSURE_EQ(context, op_context.end->type, kTfLiteInt32);
  TF_LITE_ENSURE_EQ(context, op_context.strides->type, kTfLiteInt32);
  TF_LITE_ENSURE_MSG(context, op_context.dims <= 4,
                     "StridedSlice op only supports 1D-4D input arrays.");

  // TODO(soroosh): add the following missing functionalities
  TF_LITE_ENSURE_MSG(context, op_context.params->ellipsis_mask == 0,
                     "ellipsis_mask is not implemented yet.");
  TF_LITE_ENSURE_MSG(context, op_context.params->new_axis_mask == 0,
                     "new_axis_mask is not implemented yet.");

  // Postpone allocation of output if any of the indexing tensors is not
  // constant
  if (!(IsConstantTensor(op_context.begin) &&
        IsConstantTensor(op_context.end) &&
        IsConstantTensor(op_context.strides))) {
    SetTensorToDynamic(op_context.output);
    return kTfLiteOk;
  }
  return ResizeOutputTensor(context, &op_context);
}

template <KernelType kernel_type>
TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  StridedSliceContext op_context(context, node);

  if (IsDynamicTensor(op_context.output)) {
    TF_LITE_ENSURE_OK(context, ResizeOutputTensor(context, &op_context));
  }

  std::vector<int32_t> starts;
  std::vector<int32_t> stops;
  std::vector<int32_t> strides;

  for (int i = op_context.dims; i < kMaxDim; i++) {
    starts.emplace_back(0);
    stops.emplace_back(1);
    strides.emplace_back(1);
  }

  for (int idx = 0; idx < op_context.dims; ++idx) {
    starts.emplace_back(GetTensorData<int32_t>(op_context.begin)[idx]);
    stops.emplace_back(GetTensorData<int32_t>(op_context.end)[idx]);
    strides.emplace_back(GetTensorData<int32_t>(op_context.strides)[idx]);
  }

  int begin_mask = op_context.params->begin_mask << (4 - op_context.dims);
  int end_mask = op_context.params->end_mask << (4 - op_context.dims);
  int shrink_axis_mask = op_context.params->shrink_axis_mask
                         << (4 - op_context.dims);
  TF_LITE_ENSURE_EQ(context, starts.size(), 4);
  auto op_params = ::tflite::strided_slice::BuildStridedSliceParams(
      begin_mask, end_mask, shrink_axis_mask, starts, stops, strides);

#define TF_LITE_STRIDED_SLICE(kernel_type, data_type)                    \
  kernel_type::StridedSlice(op_params, GetTensorShape(op_context.input), \
                            GetTensorData<data_type>(op_context.input),  \
                            GetTensorShape(op_context.output),           \
                            GetTensorData<data_type>(op_context.output))

  switch (op_context.input->type) {
    case kTfLiteFloat32:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, float);
      }
      break;
    case kTfLiteInt32:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int32_t);
      }
      break;
    case kTfLiteInt64:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int64_t);
      }
      break;
    case kTfLiteUInt8:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, uint8_t);
      }
      break;
    case kTfLiteInt8:
      if (kernel_type == kReference) {
        TF_LITE_STRIDED_SLICE(reference_ops, int8_t);
      }
      break;
    default:
      context->ReportError(context,
                           "Type %d is currently not supported "
                           "by StridedSlice.",
                           op_context.input->type);
      return kTfLiteError;
  }
#undef TF_LITE_STRIDED_SLICE
  return kTfLiteOk;
}

}  // namespace strided_slice

TfLiteRegistration* Register_STRIDED_SLICE_REF() {
  static TfLiteRegistration r = {
      nullptr, nullptr, strided_slice::Prepare,
      strided_slice::Eval<strided_slice::kReference>};
  return &r;
}

// TODO(soroosh): add optimized
TfLiteRegistration* Register_STRIDED_SLICE() {
  return Register_STRIDED_SLICE_REF();
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<|endoftext|>


<commit_before>// RUN: %clang  -g -S -emit-llvm %s -o - | FileCheck %s

namespace A {
#line 1 "foo.cpp"
namespace B {
int i;
}
}

// CHECK: [[FILE:![0-9]*]]} ; [ DW_TAG_file_type ] [{{.*}}/test/CodeGenCXX/debug-info-namespace.cpp]
// CHECK: [[VAR:![0-9]*]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
// CHECK: [[NS]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE:![0-9]*]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 3]
// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
<commit_msg>Debug info - generalize namespace test to not depend on a DW_TAG_file_type entry<commit_after>// RUN: %clang  -g -S -emit-llvm %s -o - | FileCheck %s

namespace A {
#line 1 "foo.cpp"
namespace B {
int i;
}
}

// CHECK: [[FILE:![0-9]*]] {{.*}}debug-info-namespace.cpp"
// CHECK: [[VAR:![0-9]*]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
// CHECK: [[NS]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 3]
// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
<|endoftext|>


<commit_before>// Copyright 2020 gRPC authors.
//
// 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 <grpc/support/port_platform.h>

#include <gtest/gtest.h>
#include "absl/strings/string_view.h"

#include "src/core/lib/security/authorization/evaluate_args.h"
#include "test/core/util/eval_args_mock_endpoint.h"

namespace grpc_core {

class EvaluateArgsTest : public ::testing::Test {
 protected:
  void SetUp() override {
    local_address_ = "255.255.255.255";
    peer_address_ = "128.128.128.128";
    local_port_ = 413;
    peer_port_ = 314;
    endpoint_ = CreateEvalArgsMockEndpoint(local_address_.c_str(), local_port_,
                                           peer_address_.c_str(), peer_port_);
    evaluate_args_ =
        absl::make_unique<EvaluateArgs>(nullptr, nullptr, endpoint_);
  }
  void TearDown() override { grpc_endpoint_destroy(endpoint_); }
  grpc_endpoint* endpoint_;
  std::unique_ptr<EvaluateArgs> evaluate_args_;
  std::string local_address_;
  std::string peer_address_;
  int local_port_;
  int peer_port_;
};

TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalAddress) {
  absl::string_view src_address = evaluate_args_->GetLocalAddress();
  EXPECT_EQ(src_address, local_address_)
      << "Error: Failed to extract correct Local address from EvaluateArgs.";
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalPort) {
  int src_port = evaluate_args_->GetLocalPort();
  EXPECT_EQ(src_port, local_port_)
      << "Error: Failed to extract correct Local port from EvaluateArgs.";
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerAddress) {
  absl::string_view dest_address = evaluate_args_->GetPeerAddress();
  EXPECT_EQ(dest_address, peer_address_)
      << "Error: Failed to extract correct Peer address from "
         "EvaluateArgs. ";
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerPort) {
  int dest_port = evaluate_args_->GetPeerPort();
  EXPECT_EQ(dest_port, peer_port_)
      << "Error: Failed to extract correct Peer port from EvaluateArgs.";
}

}  // namespace grpc_core

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Add EvaluateArgs test.<commit_after>// Copyright 2020 gRPC authors.
//
// 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 <grpc/support/port_platform.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "absl/strings/string_view.h"

#include "src/core/lib/security/authorization/evaluate_args.h"
#include "test/core/util/eval_args_mock_endpoint.h"

namespace grpc_core {

class EvaluateArgsTest : public ::testing::Test {
 protected:
  void SetUp() override {
    local_address_ = "255.255.255.255";
    peer_address_ = "128.128.128.128";
    local_port_ = 413;
    peer_port_ = 314;
    endpoint_ = CreateEvalArgsMockEndpoint(local_address_.c_str(), local_port_,
                                           peer_address_.c_str(), peer_port_);
    evaluate_args_ =
        absl::make_unique<EvaluateArgs>(nullptr, nullptr, endpoint_);
  }
  void TearDown() override { grpc_endpoint_destroy(endpoint_); }
  grpc_endpoint* endpoint_;
  std::unique_ptr<EvaluateArgs> evaluate_args_;
  std::string local_address_;
  std::string peer_address_;
  int local_port_;
  int peer_port_;
};

TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalAddress) {
  absl::string_view src_address = evaluate_args_->GetLocalAddress();
  EXPECT_EQ(src_address, local_address_);
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalPort) {
  int src_port = evaluate_args_->GetLocalPort();
  EXPECT_EQ(src_port, local_port_);
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerAddress) {
  absl::string_view dest_address = evaluate_args_->GetPeerAddress();
  EXPECT_EQ(dest_address, peer_address_);
}

TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerPort) {
  int dest_port = evaluate_args_->GetPeerPort();
  EXPECT_EQ(dest_port, peer_port_);
}

TEST(EvaluateArgsMetadataTest, HandlesNullMetadata) {
  EvaluateArgs eval_args(nullptr, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetPath(), nullptr);
  EXPECT_EQ(eval_args.GetMethod(), nullptr);
  EXPECT_EQ(eval_args.GetHost(), nullptr);
  EXPECT_THAT(eval_args.GetHeaders(), ::testing::ElementsAre());
}

TEST(EvaluateArgsMetadataTest, HandlesEmptyMetadata) {
  grpc_metadata_batch metadata;
  grpc_metadata_batch_init(&metadata);
  EvaluateArgs eval_args(&metadata, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetPath(), nullptr);
  EXPECT_EQ(eval_args.GetMethod(), nullptr);
  EXPECT_EQ(eval_args.GetHost(), nullptr);
  EXPECT_THAT(eval_args.GetHeaders(), ::testing::ElementsAre());
  grpc_metadata_batch_destroy(&metadata);
}

TEST(EvaluateArgsMetadataTest, GetPathSuccess) {
  grpc_init();
  const char* kPath = "/some/path";
  grpc_metadata_batch metadata;
  grpc_metadata_batch_init(&metadata);
  grpc_slice fake_val = grpc_slice_intern(grpc_slice_from_static_string(kPath));
  grpc_mdelem fake_val_md = grpc_mdelem_from_slices(GRPC_MDSTR_PATH, fake_val);
  grpc_linked_mdelem storage;
  storage.md = fake_val_md;
  ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage),
            GRPC_ERROR_NONE);
  EvaluateArgs eval_args(&metadata, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetPath(), kPath);
  grpc_metadata_batch_destroy(&metadata);
  grpc_shutdown();
}

TEST(EvaluateArgsMetadataTest, GetHostSuccess) {
  grpc_init();
  const char* kHost = "host";
  grpc_metadata_batch metadata;
  grpc_metadata_batch_init(&metadata);
  grpc_slice fake_val = grpc_slice_intern(grpc_slice_from_static_string(kHost));
  grpc_mdelem fake_val_md = grpc_mdelem_from_slices(GRPC_MDSTR_HOST, fake_val);
  grpc_linked_mdelem storage;
  storage.md = fake_val_md;
  ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage),
            GRPC_ERROR_NONE);
  EvaluateArgs eval_args(&metadata, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetHost(), kHost);
  grpc_metadata_batch_destroy(&metadata);
  grpc_shutdown();
}

TEST(EvaluateArgsMetadataTest, GetMethodSuccess) {
  grpc_init();
  const char* kMethod = "GET";
  grpc_metadata_batch metadata;
  grpc_metadata_batch_init(&metadata);
  grpc_slice fake_val =
      grpc_slice_intern(grpc_slice_from_static_string(kMethod));
  grpc_mdelem fake_val_md =
      grpc_mdelem_from_slices(GRPC_MDSTR_METHOD, fake_val);
  grpc_linked_mdelem storage;
  storage.md = fake_val_md;
  ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage),
            GRPC_ERROR_NONE);
  EvaluateArgs eval_args(&metadata, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetMethod(), kMethod);
  grpc_metadata_batch_destroy(&metadata);
  grpc_shutdown();
}

TEST(EvaluateArgsMetadataTest, GetHeadersSuccess) {
  grpc_init();
  const char* kPath = "/some/path";
  const char* kHost = "host";
  grpc_metadata_batch metadata;
  grpc_metadata_batch_init(&metadata);
  grpc_slice fake_path =
      grpc_slice_intern(grpc_slice_from_static_string(kPath));
  grpc_mdelem fake_path_md =
      grpc_mdelem_from_slices(GRPC_MDSTR_PATH, fake_path);
  grpc_linked_mdelem storage;
  storage.md = fake_path_md;
  ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage, GRPC_BATCH_PATH),
            GRPC_ERROR_NONE);
  grpc_slice fake_host =
      grpc_slice_intern(grpc_slice_from_static_string(kHost));
  grpc_mdelem fake_host_md =
      grpc_mdelem_from_slices(GRPC_MDSTR_HOST, fake_host);
  grpc_linked_mdelem storage2;
  storage2.md = fake_host_md;
  ASSERT_EQ(
      grpc_metadata_batch_link_tail(&metadata, &storage2, GRPC_BATCH_HOST),
      GRPC_ERROR_NONE);
  EvaluateArgs eval_args(&metadata, nullptr, nullptr);
  EXPECT_THAT(
      eval_args.GetHeaders(),
      ::testing::UnorderedElementsAre(
          ::testing::Pair(StringViewFromSlice(GRPC_MDSTR_HOST), kHost),
          ::testing::Pair(StringViewFromSlice(GRPC_MDSTR_PATH), kPath)));
  grpc_metadata_batch_destroy(&metadata);
  grpc_shutdown();
}

TEST(EvaluateArgsAuthContextTest, HandlesNullAuthContext) {
  EvaluateArgs eval_args(nullptr, nullptr, nullptr);
  EXPECT_EQ(eval_args.GetSpiffeId(), nullptr);
  EXPECT_EQ(eval_args.GetCertServerName(), nullptr);
}

TEST(EvaluateArgsAuthContextTest, HandlesEmptyAuthCtx) {
  grpc_auth_context auth_context(nullptr);
  EvaluateArgs eval_args(nullptr, &auth_context, nullptr);
  EXPECT_EQ(eval_args.GetSpiffeId(), nullptr);
  EXPECT_EQ(eval_args.GetCertServerName(), nullptr);
}

TEST(EvaluateArgsAuthContextTest, GetSpiffeIdSuccessOneProperty) {
  grpc_auth_context auth_context(nullptr);
  const char* kId = "spiffeid";
  auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, kId);
  EvaluateArgs eval_args(nullptr, &auth_context, nullptr);
  EXPECT_EQ(eval_args.GetSpiffeId(), kId);
}

TEST(EvaluateArgsAuthContextTest, GetSpiffeIdFailDuplicateProperty) {
  grpc_auth_context auth_context(nullptr);
  auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id1");
  auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id2");
  EvaluateArgs eval_args(nullptr, &auth_context, nullptr);
  EXPECT_EQ(eval_args.GetSpiffeId(), nullptr);
}

TEST(EvaluateArgsAuthContextTest, GetCertServerNameSuccessOneProperty) {
  grpc_auth_context auth_context(nullptr);
  const char* kServer = "server";
  auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, kServer);
  EvaluateArgs eval_args(nullptr, &auth_context, nullptr);
  EXPECT_EQ(eval_args.GetCertServerName(), kServer);
}

TEST(EvaluateArgsAuthContextTest, GetCertServerNameFailDuplicateProperty) {
  grpc_auth_context auth_context(nullptr);
  auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, "server1");
  auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, "server2");
  EvaluateArgs eval_args(nullptr, &auth_context, nullptr);
  EXPECT_EQ(eval_args.GetCertServerName(), nullptr);
}

}  // namespace grpc_core

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#pragma once

#include <memory>
#include <google/protobuf/message.h>
#include "singleton.hpp"

using message_ptr = std::shared_ptr<google::protobuf::Message>;

namespace czrpc
{
namespace base
{
class serialize_util
{
    DEFINE_SINGLETON(serialize_util);
public:
    serialize_util() = default;

    std::string serialize(const message_ptr& message)
    {
        check_message(message);
        return message->SerializeAsString();
    }

    message_ptr deserialize(const std::string& message_name, const std::string& body)
    {
        auto message = create_message(message_name);
        if (message == nullptr)
        {
            throw std::runtime_error("Message is nullptr");
        }
        if (!message->ParseFromString(body))
        {
            throw std::runtime_error("Parse from string failed");
        }
        if (!message->IsInitialized())
        {
            throw std::runtime_error("Message initialized failed");
        }
        return message;
    }

    void check_message(const message_ptr& message)
    {
        if (message == nullptr)
        {
            throw std::runtime_error("Message is nullptr");
        }
        if (!message->IsInitialized())
        {
            throw std::runtime_error("Message initialized failed");
        }
    }

private:
    message_ptr create_message(const std::string& message_name)
    {
        const auto descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(message_name);
        if (descriptor)
        {
            const auto prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
            if (prototype)
            {
                return message_ptr(prototype->New());
            }
        }
        return nullptr;
    }
};

}
}
<commit_msg>update<commit_after>#pragma once

#include <memory>
#include <google/protobuf/message.h>
#include "singleton.hpp"

using message_ptr = std::shared_ptr<google::protobuf::Message>;

namespace czrpc
{
namespace base
{
class serialize_util
{
    DEFINE_SINGLETON(serialize_util);
public:
    serialize_util() = default;

    std::string serialize(const message_ptr& message)
    {
        check_message(message);
        return message->SerializeAsString();
    }

    message_ptr deserialize(const std::string& message_name, const std::string& body)
    {
        if (message_name.empty())
        {
            throw std::runtime_error("Message name is empty");
        }
        auto message = create_message(message_name);
        if (message == nullptr)
        {
            throw std::runtime_error("Message is nullptr");
        }
        if (!message->ParseFromString(body))
        {
            throw std::runtime_error("Parse from string failed");
        }
        if (!message->IsInitialized())
        {
            throw std::runtime_error("Message initialized failed");
        }
        return message;
    }

    void check_message(const message_ptr& message)
    {
        if (message == nullptr)
        {
            throw std::runtime_error("Message is nullptr");
        }
        if (!message->IsInitialized())
        {
            throw std::runtime_error("Message initialized failed");
        }
    }

private:
    message_ptr create_message(const std::string& message_name)
    {
        const auto descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(message_name);
        if (descriptor)
        {
            const auto prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
            if (prototype)
            {
                return message_ptr(prototype->New());
            }
        }
        return nullptr;
    }
};

}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "chainparams.h"
#include "main.h"
#include "consensus/validation.h"

namespace block_bench {
#include "bench/data/block413567.raw.h"
}

// These are the two major time-sinks which happen after we have fully received
// a block off the wire, but before we can relay the block on to peers using
// compact block relay.

static void DeserializeBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a;
    stream.write(&a, 1); // Prevent compaction

    while (state.KeepRunning()) {
        CBlock block;
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));
    }
}

static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a;
    stream.write(&a, 1); // Prevent compaction

    Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();

    while (state.KeepRunning()) {
        CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));

        CValidationState state;
        assert(CheckBlock(block, state, params));
    }
}

BENCHMARK(DeserializeBlockTest);
BENCHMARK(DeserializeAndCheckBlockTest);
<commit_msg>Use better name for local variable to prevent -Wshadow compiler warning<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "chainparams.h"
#include "main.h"
#include "consensus/validation.h"

namespace block_bench {
#include "bench/data/block413567.raw.h"
}

// These are the two major time-sinks which happen after we have fully received
// a block off the wire, but before we can relay the block on to peers using
// compact block relay.

static void DeserializeBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a;
    stream.write(&a, 1); // Prevent compaction

    while (state.KeepRunning()) {
        CBlock block;
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));
    }
}

static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
    CDataStream stream((const char*)block_bench::block413567,
            (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
            SER_NETWORK, PROTOCOL_VERSION);
    char a;
    stream.write(&a, 1); // Prevent compaction

    Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();

    while (state.KeepRunning()) {
        CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
        stream >> block;
        assert(stream.Rewind(sizeof(block_bench::block413567)));

        CValidationState validationState;
        assert(CheckBlock(block, validationState, params));
    }
}

BENCHMARK(DeserializeBlockTest);
BENCHMARK(DeserializeAndCheckBlockTest);
<|endoftext|>