<commit_before>#include "functional.hpp"
#include "constants.hpp"

template<class num>
static num Gc(const num &r,
	      const parameter A,
	      const parameter a1,
	      const parameter b1,
	      const parameter b2,
	      const parameter b3,
	      const parameter b4,
	      const parameter p)
{
  num sqrtr = sqrt(r);
  return -2*A*(1+a1*r)*log(1 + 0.5/(A*(sqrtr*(b1 + sqrtr*(b2 + sqrtr*b3)) + b4*pow(r,p+1))));
}

template<class num>
static num pw91c(const densvars<num> &d)
{
  const parameter pa = 1.0;
  const parameter Aa = 0.016887;
  const parameter a1a = 0.11125;
  const parameter b1a = 10.357;
  const parameter b2a = 3.6231;
  const parameter b3a = 0.88026;
  const parameter b4a = 0.49671;
  const parameter pe = 1;
  const parameter c0p = 0.031091;
  const parameter a1p = 0.21370;
  const parameter b1p = 7.5957;
  const parameter b2p = 3.5876;
  const parameter b3p = 1.6382;
  const parameter b4p = 0.49294;
  const parameter c0f = 0.015545;
  const parameter a1f = 0.20548;
  const parameter b1f = 14.1189;
  const parameter b2f = 6.1977;
  const parameter b3f = 3.3662;
  const parameter b4f = 0.62517;
  const parameter d2fz0 = 1.709921;
  num fz  = (ufunc(d.zeta,4.0/3.0)-2)/(2*pow(2,1.0/3.0)-2);
  num Ac  = Gc(d.r_s,  Aa, a1a, b1a, b2a, b3a, b4a, pa);
  num EcP = Gc(d.r_s, c0p, a1p, b1p, b2p, b3p, b4p, pe);
  num EcF = Gc(d.r_s, c0f, a1f, b1f, b2f, b3f, b4f, pe);
  num Ec = EcP - Ac*fz*(1-pow(d.zeta,4))/d2fz0 + (EcF - EcP)*fz*pow(d.zeta,4);
  num kF = cbrt(3*M_PI*M_PI*d.n);
  num ks = sqrt(4)*sqrt(kF/M_PI);
  num gs = 0.5*ufunc(d.zeta,2.0/3.0);
  num T2 = 0.25*d.gnn/pow(gs*ks*d.n,2);
  const parameter alpha = 0.09;
  const parameter Cc0 = 0.004235;
  const parameter Cx = -0.001667;
  const parameter nu = 16*cbrt(3*M_PI*M_PI)/M_PI;
  const parameter beta = nu*Cc0;
  num A = 2*alpha/beta/expm1(-2*(alpha*Ec)/(pow(gs,3)*beta*beta));
  num Cc = 1.0/1000*((2.568 + d.n*(23.266 + 0.007389*d.n))/
		     (1 + d.n*(8.723 + d.n*(0.472 + d.n*0.073890)))) - Cx;
  num H0 = 0.5*pow(gs,3)*beta*beta*log((1 + 2*(alpha*(T2+A*T2*T2))/(beta*(1 + A*T2*(1 + A*T2)))))/alpha;
  num H1 = nu*(Cc - Cc0 - 3.0/7.0*Cx)*pow(gs,3)*T2*exp(-100*pow(gs,4)*pow(ks,2)*T2/pow(kF,2));
  return d.n*(Ec + H0 + H1);
}

FUNCTIONAL(XC_PW91C) = {
  "PW91 Correlation",
  "J.P. Perdew, J.A. Chevary, S.H. Vosko, K.A. Jackson, M.R. Pederson, D.J. Singh and"
  "C. Fiolhais, 'Atoms, molecules, solids and surfaces: Applications of the generalized"
  "gradient approximation for exchange and correlation', Phys. Rev. B, 46(11):6671"
  "6687, 1992"
  "Implemented by Ulf Ekstrom. Test from ftp://ftp.dl.ac.uk/qcg/dft_library/data_pt_c_pw91.html\n",
  XC_DENSITY | XC_GRADIENT,
  ENERGY_FUNCTION(pw91c)
  XC_A_B_GAA_GAB_GBB,
  XC_PARTIAL_DERIVATIVES,
  2, // test order
  1e-11, // test threshold
  {0.78E-01,0.31E-01, 0.41E-02, 0.38E-02, 0.36E-02},
  {
    -0.450106022368E-02,
    -0.568426120793E-01,
    -0.876498238182E-01,
    0.531751834129E-01,
    0.106350366826E+00,
    0.531751834129E-01,
    0.192611490688E+00,
    -0.331153469676E+00,
    -0.308498888708E+00,
    -0.616997777417E+00,
    -0.308498888708E+00,
    0.645433404561E+00,
    -0.129198778272E+00,
    -0.258397556545E+00,
    -0.129198778272E+00,
    -0.119074508391E+01,
    -0.238149016782E+01,
    -0.119074508391E+01,
    -0.476298033563E+01,
    -0.238149016782E+01,
    -0.119074508391E+01,
  },
};
<commit_msg>PW91c now working.<commit_after>#include "functional.hpp"
#include "constants.hpp"

template<class num>
static num Gc(const num &r,
	      const parameter A,
	      const parameter a1,
	      const parameter b1,
	      const parameter b2,
	      const parameter b3,
	      const parameter b4,
	      const parameter p)
{
  num sqrtr = sqrt(r);
  return -2*A*(1+a1*r)*log(1 + 0.5/(A*(sqrtr*(b1 + sqrtr*(b2 + sqrtr*b3)) + b4*pow(r,p+1))));
}

// (1+(a-b)/(a+b))^p + (1-(a-b)/(a+b))^p =
// ((b^p+a^p)*2^p)/(b+a)^p
template<class num>
static num uf(const densvars<num> &d, const parameter p)
{
  return (pow(d.a,p) + pow(d.b,p))*pow(2/d.n,p);
}

template<class num>
static num pw91c(const densvars<num> &d)
{
  const parameter pa = 1.0;
  const parameter Aa = 0.016887;
  const parameter a1a = 0.11125;
  const parameter b1a = 10.357;
  const parameter b2a = 3.6231;
  const parameter b3a = 0.88026;
  const parameter b4a = 0.49671;
  const parameter pe = 1;
  const parameter c0p = 0.031091;
  const parameter a1p = 0.21370;
  const parameter b1p = 7.5957;
  const parameter b2p = 3.5876;
  const parameter b3p = 1.6382;
  const parameter b4p = 0.49294;
  const parameter c0f = 0.015545;
  const parameter a1f = 0.20548;
  const parameter b1f = 14.1189;
  const parameter b2f = 6.1977;
  const parameter b3f = 3.3662;
  const parameter b4f = 0.62517;
  const parameter d2fz0 = 1.709921;
  num fz  = (uf(d,4.0/3.0)-2)/(2*pow(2,1.0/3.0)-2);
  num Ac  = Gc(d.r_s,  Aa, a1a, b1a, b2a, b3a, b4a, pa);
  num EcP = Gc(d.r_s, c0p, a1p, b1p, b2p, b3p, b4p, pe);
  num EcF = Gc(d.r_s, c0f, a1f, b1f, b2f, b3f, b4f, pe);
  num Ec = EcP - Ac*fz*(1-pow(d.zeta,4))/d2fz0 + (EcF - EcP)*fz*pow(d.zeta,4);
  num kF = cbrt(3*M_PI*M_PI*d.n);
  num ks = sqrt(4)*sqrt(kF/M_PI);
  num gs = 0.5*uf(d,2.0/3.0);
  num T2 = 0.25*d.gnn/pow(gs*ks*d.n,2);
  const parameter alpha = 0.09;
  const parameter Cc0 = 0.004235;
  const parameter Cx = -0.001667;
  const parameter nu = 16*cbrt(3*M_PI*M_PI)/M_PI;
  const parameter beta = nu*Cc0;
  num A = 2*alpha/beta/expm1(-2*(alpha*Ec)/(pow(gs,3)*beta*beta));
  num Cc = 1.0/1000*((2.568 + d.r_s*(23.266 + 0.007389*d.r_s))/
		     (1 + d.r_s*(8.723 + d.r_s*(0.472 + d.r_s*0.073890)))) - Cx;
  num H0 = 0.5*pow(gs,3)*beta*beta/alpha*log((1 + 2*(alpha*(T2+A*T2*T2))/(beta*(1 + A*T2*(1 + A*T2)))));
  num H1 = nu*(Cc - Cc0 - 3.0/7.0*Cx)*pow(gs,3)*T2*exp(-100*pow(gs,4)*pow(ks,2)*T2/pow(kF,2));
  return d.n*(Ec + H0 + H1);
}

#define TEST2
FUNCTIONAL(XC_PW91C) = {
  "PW91 Correlation",
  "J.P. Perdew, J.A. Chevary, S.H. Vosko, K.A. Jackson, M.R. Pederson, D.J. Singh and"
  "C. Fiolhais, 'Atoms, molecules, solids and surfaces: Applications of the generalized"
  "gradient approximation for exchange and correlation', Phys. Rev. B, 46(11):6671"
  "6687, 1992"
  "Implemented by Ulf Ekstrom. Test from ftp://ftp.dl.ac.uk/qcg/dft_library/data_pt_c_pw91.html\n",
  XC_DENSITY | XC_GRADIENT,
  ENERGY_FUNCTION(pw91c)
  XC_A_B_GAA_GAB_GBB,
  XC_PARTIAL_DERIVATIVES,
  2, // test order
  1e-11, // test threshold
#ifdef TEST1
  {0.78E-01,0.31E-01, 0.41E-02, 0.38E-02, 0.36E-02},
  {
    -0.450106022368E-02,
    -0.568426120793E-01,
    -0.876498238182E-01,
    0.531751834129E-01,
    0.106350366826E+00,
    0.531751834129E-01,
    0.192611490688E+00,
    -0.331153469676E+00,
    -0.308498888708E+00,
    -0.616997777417E+00,
    -0.308498888708E+00,
    0.645433404561E+00,
    -0.129198778272E+00,
    -0.258397556545E+00,
    -0.129198778272E+00,
    -0.119074508391E+01,
    -0.238149016782E+01,
    -0.119074508391E+01,
    -0.476298033563E+01,
    -0.238149016782E+01,
    -0.119074508391E+01,
  },
#else
#ifdef TEST2
  {0.17E+01, 0.17E+01, 0.81E-11, 0.81E-11, 0.81E-11},
  {-0.277344423214E+00,
   -0.902549628505E-01,
   -0.902549628505E-01,
   0.973880560793E-03,
   0.194776112159E-02,
   0.973880560793E-03,
   0.129726626281E-01,
   -0.182704041173E-01,
   -0.381075641669E-03,
   -0.762151283338E-03,
   -0.381075641669E-03,
   0.129726626281E-01,
   -0.381075641669E-03,
   -0.762151283338E-03,
   -0.381075641669E-03,
   -0.372455307820E-04,
   -0.744910615639E-04,
   -0.372455307820E-04,
   -0.148982123128E-03,
   -0.744910615639E-04,
   -0.372455307820E-04,}
#else
#ifdef TEST4
  {0.39E+02, 0.38E+02, 0.81E+06, 0.82E+06, 0.82E+06},
  { -0.258051271460E+01,
    -0.917654870253E-01,
    -0.924958459953E-01,
    0.504340587823E-06,
    0.100868117565E-05,
    0.504340587823E-06,
    /*
 v2rhoa2       = -0.673510067892E-03
 v2rhoab       = -0.140781632726E-02
 v2rhob2       = -0.681437355666E-03

 v2rhoasigmaaa =  0.880806595654E-08
 v2rhoasigmaab =  0.176161319131E-07
 v2rhoasigmabb =  0.880806595654E-08
 v2rhobsigmaaa =  0.892599758143E-08
 v2rhobsigmaab =  0.178519951629E-07
 v2rhobsigmabb =  0.892599758143E-08

 v2sigmaaa2    = -0.173276860156E-12
 v2sigmaaaab   = -0.346553720312E-12
 v2sigmaaabb   = -0.173276860156E-12
 v2sigmaab2    = -0.693107440625E-12
 v2sigmaabbb   = -0.346553720312E-12
 v2sigmabb2    = -0.173276860156E-12
    */
  }
#else
  {0.13E+00, 0.95E-01, 0.15E+00, 0.18E+00, 0.22E+00},
  { -0.475398805591E-02,
    -0.614930812180E-01,
    -0.682665101239E-01,
    0.486210103008E-02,
    0.972420206015E-02,
    0.486210103008E-02,}
  /*
 v2rhoa2       = -0.180150058142E+00
 v2rhoab       = -0.388435750226E+00
 v2rhob2       = -0.208827666674E+00

 v2rhoasigmaaa =  0.288797891283E-01
 v2rhoasigmaab =  0.577595782566E-01
 v2rhoasigmabb =  0.288797891283E-01
 v2rhobsigmaaa =  0.338842245007E-01
 v2rhobsigmaab =  0.677684490015E-01
 v2rhobsigmabb =  0.338842245007E-01

 v2sigmaaa2    = -0.755929074438E-02
 v2sigmaaaab   = -0.151185814888E-01
 v2sigmaaabb   = -0.755929074438E-02
 v2sigmaab2    = -0.302371629775E-01
 v2sigmaabbb   = -0.151185814888E-01
 v2sigmabb2    = -0.755929074438E-02
  */
#endif
#endif
#endif
};
<|endoftext|>


<commit_before><commit_msg>Fix for restoring the current directory after writing AliDirList to file.<commit_after><|endoftext|>


<commit_before>//==- UninitializedValues.cpp - Find Unintialized Values --------*- C++ --*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Uninitialized Values analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/UninitializedValues.h"
#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/FlowSensitive/DataflowSolver.h"

#include "llvm/ADT/SmallPtrSet.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Dataflow initialization logic.
//===----------------------------------------------------------------------===//

namespace {

class RegisterDeclsExprs : public CFGRecStmtDeclVisitor<RegisterDeclsExprs> {
  UninitializedValues::AnalysisDataTy& AD;
public:
  RegisterDeclsExprs(UninitializedValues::AnalysisDataTy& ad) :  AD(ad) {}

  void VisitBlockVarDecl(BlockVarDecl* VD) { AD.Register(VD); }
  void BlockStmt_VisitExpr(Expr* E) { AD.Register(E); }
};

} // end anonymous namespace

void UninitializedValues::InitializeValues(const CFG& cfg) {
  RegisterDeclsExprs R(this->getAnalysisData());
  cfg.VisitBlockStmts(R);
}

//===----------------------------------------------------------------------===//
// Transfer functions.
//===----------------------------------------------------------------------===//

namespace {

class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
  UninitializedValues::ValTy V;
  UninitializedValues::AnalysisDataTy& AD;
public:
  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
    V.resetValues(AD);
  }

  UninitializedValues::ValTy& getVal() { return V; }

  bool VisitDeclRefExpr(DeclRefExpr* DR);
  bool VisitBinaryOperator(BinaryOperator* B);
  bool VisitUnaryOperator(UnaryOperator* U);
  bool VisitStmt(Stmt* S);
  bool VisitCallExpr(CallExpr* C);
  bool VisitDeclStmt(DeclStmt* D);
  bool VisitConditionalOperator(ConditionalOperator* C);

  bool Visit(Stmt *S);
  bool BlockStmt_VisitExpr(Expr* E);

  BlockVarDecl* FindBlockVarDecl(Stmt* S);
};

static const bool Initialized = true;
static const bool Uninitialized = false;

bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
  if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) {
    if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);

    // Pseudo-hack to prevent cascade of warnings.  If an accessed variable
    // is uninitialized, then we are already going to flag a warning for
    // this variable, which a "source" of uninitialized values.
    // We can otherwise do a full "taint" of uninitialized values.  The
    // client has both options by toggling AD.FullUninitTaint.

    return AD.FullUninitTaint ? V(VD,AD) : Initialized;
  }
  else return Initialized;
}

BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
  for (;;)
    if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
      S = P->getSubExpr(); continue;
    }
    else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
      if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl()))
        return VD;
    }
    else return NULL;
}

bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
  if (B->isAssignmentOp())
    if (BlockVarDecl* VD = FindBlockVarDecl(B->getLHS()))
      return V(VD,AD) = AD.FullUninitTaint ? Visit(B->getRHS()) : Initialized;

  return VisitStmt(B);
}

bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
  for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
    if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) {
      if (Stmt* I = VD->getInit())
        V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
      else V(VD,AD) = Uninitialized;
    }

  return Uninitialized; // Value is never consumed.
}

bool TransferFuncs::VisitCallExpr(CallExpr* C) {
  VisitChildren(C);
  return Initialized;
}

bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
  if (U->getOpcode() == UnaryOperator::AddrOf)
    if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr()))
      return V(VD,AD) = Initialized;

  return Visit(U->getSubExpr());
}

bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) {
  Visit(C->getCond());
  return Visit(C->getLHS()) & Visit(C->getRHS());  // Yes: we want &, not &&.
}

bool TransferFuncs::VisitStmt(Stmt* S) {
  bool x = Initialized;

  // We don't stop at the first subexpression that is Uninitialized because
  // evaluating some subexpressions may result in propogating "Uninitialized"
  // or "Initialized" to variables referenced in the other subexpressions.
  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
    if (*I && Visit(*I) == Uninitialized) x = Uninitialized;

  return x;
}

bool TransferFuncs::Visit(Stmt *S) {
  if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD);
  else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S);
}

bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
  assert (AD.isTracked(E));
  return V(E,AD) =
    static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E);
}

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Merge operator.
//
//  In our transfer functions we take the approach that any
//  combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
//
//  Merges take the opposite approach.
//
//  In the merge of dataflow values we prefer unsoundness, and
//  prefer false negatives to false positives.  At merges, if a value for a
//  tracked Decl is EVER initialized in any of the predecessors we treat it as
//  initialized at the confluence point.
//===----------------------------------------------------------------------===//

namespace {
  typedef ExprDeclBitVector_Types::Union Merge;
  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
}

//===----------------------------------------------------------------------===//
// Unitialized values checker.   Scan an AST and flag variable uses
//===----------------------------------------------------------------------===//

UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}

namespace {
class UninitializedValuesChecker : public UninitializedValues::ObserverTy {
  ASTContext &Ctx;
  Diagnostic &Diags;
  llvm::SmallPtrSet<BlockVarDecl*,10> AlreadyWarned;

public:
  UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
    : Ctx(ctx), Diags(diags) {}

  virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
                                  UninitializedValues::AnalysisDataTy& AD,
                                  DeclRefExpr* DR, BlockVarDecl* VD) {

    assert ( AD.isTracked(VD) && "Unknown VarDecl.");

    if (V(VD,AD) == Uninitialized)
      if (AlreadyWarned.insert(VD))
        Diags.Report(DR->getSourceRange().Begin(), diag::warn_uninit_val);
  }
};
} // end anonymous namespace

namespace clang {
void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags,
                              bool FullUninitTaint) {

  // Compute the unitialized values information.
  UninitializedValues U;
  U.getAnalysisData().FullUninitTaint = FullUninitTaint;
  Solver S(U);
  S.runOnCFG(cfg);

  // Scan for DeclRefExprs that use uninitialized values.
  UninitializedValuesChecker Observer(Ctx,Diags);
  U.getAnalysisData().Observer = &Observer;
  S.runOnAllBlocks(cfg);
}
} // end namespace clang
<commit_msg>Fixed UninitializedValues to properly propagate uninitialized "taint" in assignment operations of the form +=, -=, *=, etc.<commit_after>//==- UninitializedValues.cpp - Find Unintialized Values --------*- C++ --*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Uninitialized Values analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/UninitializedValues.h"
#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/FlowSensitive/DataflowSolver.h"

#include "llvm/ADT/SmallPtrSet.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Dataflow initialization logic.
//===----------------------------------------------------------------------===//

namespace {

class RegisterDeclsExprs : public CFGRecStmtDeclVisitor<RegisterDeclsExprs> {
  UninitializedValues::AnalysisDataTy& AD;
public:
  RegisterDeclsExprs(UninitializedValues::AnalysisDataTy& ad) :  AD(ad) {}

  void VisitBlockVarDecl(BlockVarDecl* VD) { AD.Register(VD); }
  void BlockStmt_VisitExpr(Expr* E) { AD.Register(E); }
};

} // end anonymous namespace

void UninitializedValues::InitializeValues(const CFG& cfg) {
  RegisterDeclsExprs R(this->getAnalysisData());
  cfg.VisitBlockStmts(R);
}

//===----------------------------------------------------------------------===//
// Transfer functions.
//===----------------------------------------------------------------------===//

namespace {

class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
  UninitializedValues::ValTy V;
  UninitializedValues::AnalysisDataTy& AD;
public:
  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
    V.resetValues(AD);
  }

  UninitializedValues::ValTy& getVal() { return V; }

  bool VisitDeclRefExpr(DeclRefExpr* DR);
  bool VisitBinaryOperator(BinaryOperator* B);
  bool VisitUnaryOperator(UnaryOperator* U);
  bool VisitStmt(Stmt* S);
  bool VisitCallExpr(CallExpr* C);
  bool VisitDeclStmt(DeclStmt* D);
  bool VisitConditionalOperator(ConditionalOperator* C);

  bool Visit(Stmt *S);
  bool BlockStmt_VisitExpr(Expr* E);

  BlockVarDecl* FindBlockVarDecl(Stmt* S);
};

static const bool Initialized = true;
static const bool Uninitialized = false;

bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
  if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) {
    if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);

    // Pseudo-hack to prevent cascade of warnings.  If an accessed variable
    // is uninitialized, then we are already going to flag a warning for
    // this variable, which a "source" of uninitialized values.
    // We can otherwise do a full "taint" of uninitialized values.  The
    // client has both options by toggling AD.FullUninitTaint.

    return AD.FullUninitTaint ? V(VD,AD) : Initialized;
  }
  else return Initialized;
}

BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
  for (;;)
    if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
      S = P->getSubExpr(); continue;
    }
    else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
      if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl()))
        return VD;
    }
    else return NULL;
}

bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
  if (BlockVarDecl* VD = FindBlockVarDecl(B->getLHS()))
    if (B->isAssignmentOp()) {
      if (AD.FullUninitTaint) {
        if (B->getOpcode() == BinaryOperator::Assign)
          return V(VD,AD) = Visit(B->getRHS());
        else // Handle +=, -=, *=, etc.  We do want '&', not '&&'.
          return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS());
      }
      else {
        Visit(B->getLHS()); Visit(B->getRHS());
        return Initialized;
      }
    }

  return VisitStmt(B);
}

bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
  for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
    if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) {
      if (Stmt* I = VD->getInit())
        V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
      else V(VD,AD) = Uninitialized;
    }

  return Uninitialized; // Value is never consumed.
}

bool TransferFuncs::VisitCallExpr(CallExpr* C) {
  VisitChildren(C);
  return Initialized;
}

bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
  if (U->getOpcode() == UnaryOperator::AddrOf)
    if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr()))
      return V(VD,AD) = Initialized;

  return Visit(U->getSubExpr());
}

bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) {
  Visit(C->getCond());
  return Visit(C->getLHS()) & Visit(C->getRHS());  // Yes: we want &, not &&.
}

bool TransferFuncs::VisitStmt(Stmt* S) {
  bool x = Initialized;

  // We don't stop at the first subexpression that is Uninitialized because
  // evaluating some subexpressions may result in propogating "Uninitialized"
  // or "Initialized" to variables referenced in the other subexpressions.
  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
    if (*I && Visit(*I) == Uninitialized) x = Uninitialized;

  return x;
}

bool TransferFuncs::Visit(Stmt *S) {
  if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD);
  else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S);
}

bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
  assert (AD.isTracked(E));
  return V(E,AD) =
    static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E);
}

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Merge operator.
//
//  In our transfer functions we take the approach that any
//  combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
//
//  Merges take the opposite approach.
//
//  In the merge of dataflow values we prefer unsoundness, and
//  prefer false negatives to false positives.  At merges, if a value for a
//  tracked Decl is EVER initialized in any of the predecessors we treat it as
//  initialized at the confluence point.
//===----------------------------------------------------------------------===//

namespace {
  typedef ExprDeclBitVector_Types::Union Merge;
  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
}

//===----------------------------------------------------------------------===//
// Unitialized values checker.   Scan an AST and flag variable uses
//===----------------------------------------------------------------------===//

UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}

namespace {
class UninitializedValuesChecker : public UninitializedValues::ObserverTy {
  ASTContext &Ctx;
  Diagnostic &Diags;
  llvm::SmallPtrSet<BlockVarDecl*,10> AlreadyWarned;

public:
  UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
    : Ctx(ctx), Diags(diags) {}

  virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
                                  UninitializedValues::AnalysisDataTy& AD,
                                  DeclRefExpr* DR, BlockVarDecl* VD) {

    assert ( AD.isTracked(VD) && "Unknown VarDecl.");

    if (V(VD,AD) == Uninitialized)
      if (AlreadyWarned.insert(VD))
        Diags.Report(DR->getSourceRange().Begin(), diag::warn_uninit_val);
  }
};
} // end anonymous namespace

namespace clang {
void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags,
                              bool FullUninitTaint) {

  // Compute the unitialized values information.
  UninitializedValues U;
  U.getAnalysisData().FullUninitTaint = FullUninitTaint;
  Solver S(U);
  S.runOnCFG(cfg);

  // Scan for DeclRefExprs that use uninitialized values.
  UninitializedValuesChecker Observer(Ctx,Diags);
  U.getAnalysisData().Observer = &Observer;
  S.runOnAllBlocks(cfg);
}
} // end namespace clang
<|endoftext|>


<commit_before><commit_msg>trimming code space<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <iostream>

#include <nix/hdf5/PropertyHDF5.hpp>

using namespace std;
using namespace boost;

namespace nix {
namespace hdf5 {

PropertyHDF5::PropertyHDF5(const PropertyHDF5 &property)
    : PropertyHDF5(property.file(), property.group(), property.dataset(), property.id(), property.name())
{
}

    PropertyHDF5::PropertyHDF5(const File &file, const Group &group, const DataSet &dataset, const string &id, const string &name)
        : PropertyHDF5(file, group, dataset, id, name, util::getTime())
{
}

    PropertyHDF5::PropertyHDF5(const File &file, const Group &group, const DataSet &dataset, const string &id, const string &name, time_t time)
    : EntityHDF5(file, group, id, time)
{
    this->entity_dataset = dataset;
    this->name(name);
}

void PropertyHDF5::name(const string &name) {
    if(name.empty()) {
        throw EmptyString("name");
    }
    else {
        dataset().setAttr("name", name);
        forceUpdatedAt();
    }
}

string PropertyHDF5::name() const {
    string name;
    if(dataset().hasAttr("name")) {
        dataset().getAttr("name", name);
        return name;
    } else {
        throw MissingAttr("name");
    }
}

void PropertyHDF5::definition(const string &definition) {
    if(definition.empty()) {
        throw EmptyString("definition");
    }
    else {
        dataset().setAttr("definition", definition);
        forceUpdatedAt();
    }
}

optional<string> PropertyHDF5::definition() const {
    optional<string> ret;
    string definition;
    bool have_attr = dataset().getAttr("definition", definition);
    if (have_attr) {
        ret = definition;
    }
    return ret;
}

void PropertyHDF5::definition(const none_t t) {
    if(dataset().hasAttr("definition")) {
        dataset().removeAttr("definition");
    }
    forceUpdatedAt();
}

boost::optional<DataType> PropertyHDF5::dataType() const {
    boost::optional<DataType> result;
    result = this->values()[0].type();
    return result;
}

void PropertyHDF5::mapping(const string &mapping) {
    if (mapping.empty()) {
        throw EmptyString("mapping");
    }
    dataset().setAttr("mapping", mapping);
    forceUpdatedAt();
}

boost::optional<string> PropertyHDF5::mapping() const {
    boost::optional<string> ret;
    string mapping;
    if (dataset().getAttr("mapping", mapping)) {
        ret = mapping;
    }
    return ret;
}

void PropertyHDF5::mapping(const none_t t) {
    if (dataset().hasAttr("mapping")) {
        dataset().removeAttr("mapping");
        forceUpdatedAt();
    }
}

void PropertyHDF5::unit(const string &unit) {
    if (unit.empty()) {
        throw EmptyString("unit");
    }
    dataset().setAttr("unit", unit);
    forceUpdatedAt();
}

boost::optional<string> PropertyHDF5::unit() const {
    boost::optional<std::string> ret;
    string unit;
    if(dataset().getAttr("unit", unit)) {
        ret = unit;
    }
    return ret;
}

void PropertyHDF5::unit(const none_t t) {
    if(dataset().hasAttr("unit")) {
        dataset().removeAttr("unit");
    }
    forceUpdatedAt();
}

void PropertyHDF5::deleteValues() {
    dataset().setExtent({0});
}

size_t PropertyHDF5::valueCount() const {
    size_t count = 0;
    NDSize size = dataset().size();
    return size[0];
    return count;
}

void PropertyHDF5::values(const std::vector<Value> &values)
{
    if (values.size() < 1) {
        return; //Nothing to do, since we also cannot guess the correct DataType
    }
    NDSize size = {1};
    DataType dtype = values[0].type();
    H5::DataType fileType = DataSet::fileTypeForValue(dtype);
    dataset().write(values);
}

std::vector<Value> PropertyHDF5::values(void) const
{
    std::vector<Value> values;
    dataset().read(values);
    return values;
}

void PropertyHDF5::values(const none_t t) {
    if(group().hasData("values")) {
        group().removeData("values");
    }
    forceUpdatedAt();
}

int PropertyHDF5::compare(const IProperty &other) const {
    int cmp = 0;
    if (!name().empty() && !other.name().empty()) {
        cmp = (name()).compare(other.name());
    }
    if (cmp == 0) {
        cmp = id().compare(other.id());
    }
    return cmp;
}

PropertyHDF5::~PropertyHDF5() {}

} // namespace hdf5
} // namespace nix
<commit_msg>retrieval of data type no longer using values but dataset.dataType<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <iostream>

#include <nix/hdf5/PropertyHDF5.hpp>

using namespace std;
using namespace boost;

namespace nix {
namespace hdf5 {

PropertyHDF5::PropertyHDF5(const PropertyHDF5 &property)
    : PropertyHDF5(property.file(), property.group(), property.dataset(), property.id(), property.name())
{
}

    PropertyHDF5::PropertyHDF5(const File &file, const Group &group, const DataSet &dataset, const string &id, const string &name)
        : PropertyHDF5(file, group, dataset, id, name, util::getTime())
{
}

    PropertyHDF5::PropertyHDF5(const File &file, const Group &group, const DataSet &dataset, const string &id, const string &name, time_t time)
    : EntityHDF5(file, group, id, time)
{
    this->entity_dataset = dataset;
    this->name(name);
}

void PropertyHDF5::name(const string &name) {
    if(name.empty()) {
        throw EmptyString("name");
    }
    else {
        dataset().setAttr("name", name);
        forceUpdatedAt();
    }
}

string PropertyHDF5::name() const {
    string name;
    if(dataset().hasAttr("name")) {
        dataset().getAttr("name", name);
        return name;
    } else {
        throw MissingAttr("name");
    }
}

void PropertyHDF5::definition(const string &definition) {
    if(definition.empty()) {
        throw EmptyString("definition");
    }
    else {
        dataset().setAttr("definition", definition);
        forceUpdatedAt();
    }
}

optional<string> PropertyHDF5::definition() const {
    optional<string> ret;
    string definition;
    bool have_attr = dataset().getAttr("definition", definition);
    if (have_attr) {
        ret = definition;
    }
    return ret;
}

void PropertyHDF5::definition(const none_t t) {
    if(dataset().hasAttr("definition")) {
        dataset().removeAttr("definition");
    }
    forceUpdatedAt();
}

boost::optional<DataType> PropertyHDF5::dataType() const {
    boost::optional<DataType> result;
    result = this->dataset().dataType();
    return result;
}

void PropertyHDF5::mapping(const string &mapping) {
    if (mapping.empty()) {
        throw EmptyString("mapping");
    }
    dataset().setAttr("mapping", mapping);
    forceUpdatedAt();
}

boost::optional<string> PropertyHDF5::mapping() const {
    boost::optional<string> ret;
    string mapping;
    if (dataset().getAttr("mapping", mapping)) {
        ret = mapping;
    }
    return ret;
}

void PropertyHDF5::mapping(const none_t t) {
    if (dataset().hasAttr("mapping")) {
        dataset().removeAttr("mapping");
        forceUpdatedAt();
    }
}

void PropertyHDF5::unit(const string &unit) {
    if (unit.empty()) {
        throw EmptyString("unit");
    }
    dataset().setAttr("unit", unit);
    forceUpdatedAt();
}

boost::optional<string> PropertyHDF5::unit() const {
    boost::optional<std::string> ret;
    string unit;
    if(dataset().getAttr("unit", unit)) {
        ret = unit;
    }
    return ret;
}

void PropertyHDF5::unit(const none_t t) {
    if(dataset().hasAttr("unit")) {
        dataset().removeAttr("unit");
    }
    forceUpdatedAt();
}

void PropertyHDF5::deleteValues() {
    dataset().setExtent({0});
}

size_t PropertyHDF5::valueCount() const {
    size_t count = 0;
    NDSize size = dataset().size();
    return size[0];
    return count;
}

void PropertyHDF5::values(const std::vector<Value> &values)
{
    if (values.size() < 1) {
        return; //Nothing to do, since we also cannot guess the correct DataType
    }
    NDSize size = {1};
    DataType dtype = values[0].type();
    H5::DataType fileType = DataSet::fileTypeForValue(dtype);
    dataset().write(values);
}

std::vector<Value> PropertyHDF5::values(void) const
{
    std::vector<Value> values;
    dataset().read(values);
    return values;
}

void PropertyHDF5::values(const none_t t) {
    if(group().hasData("values")) {
        group().removeData("values");
    }
    forceUpdatedAt();
}

int PropertyHDF5::compare(const IProperty &other) const {
    int cmp = 0;
    if (!name().empty() && !other.name().empty()) {
        cmp = (name()).compare(other.name());
    }
    if (cmp == 0) {
        cmp = id().compare(other.id());
    }
    return cmp;
}

PropertyHDF5::~PropertyHDF5() {}

} // namespace hdf5
} // namespace nix
<|endoftext|>


<commit_before><?hh // strict

/**
 * This file is part of hhpack\process package.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\process\input;

use hhpack\process\PipeType;
use hhpack\process\output\BufferedOutput;
use hhpack\process\Writable;

final class ReadablePipe implements ReadableStream
{

    private bool $opened = true;
    private Writable<int> $output;

    public function __construct(
        private PipeType $type,
        private resource $handle
    )
    {
        $this->output = new BufferedOutput();
    }

    public function eof() : bool
    {
        return feof($this->handle);
    }

    public function isOpened() : bool
    {
        return $this->opened;
    }

    public function isClosed() : bool
    {
        return $this->isOpened() === false;
    }

    public function read(int $length) : void
    {
        $chunk = fread($this->handle, $length);
        $this->output->write($chunk);
    }

    public function getOutput() : Writable<int>
    {
        return $this->output;
    }

    public function pipeTo(Writable<int> $output) : void
    {
        $this->output = $output;
    }

    public function isStdout() : bool
    {
        return $this->type === PipeType::Stdout;
    }

    public function isStderr() : bool
    {
        return $this->type === PipeType::Stderr;
    }

    public function close() : void
    {
        fclose($this->handle);
        $this->opened = false;
    }

}
<commit_msg><commit_after><?hh // strict

/**
 * This file is part of hhpack\process package.
 *
 * (c) Noritaka Horio <holy.shared.design@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace hhpack\process\input;

use hhpack\process\PipeType;
use hhpack\process\output\BufferedOutput;
use hhpack\process\Writable;

final class ReadablePipe implements ReadableStream
{

    private bool $opened = true;

    public function __construct(
        private PipeType $type,
        private resource $handle,
        private Writable<int> $output = new BufferedOutput()
    )
    {
    }

    public function eof() : bool
    {
        return feof($this->handle);
    }

    public function isOpened() : bool
    {
        return $this->opened;
    }

    public function isClosed() : bool
    {
        return $this->isOpened() === false;
    }

    public function read(int $length) : void
    {
        $chunk = fread($this->handle, $length);
        $this->output->write($chunk);
    }

    public function getOutput() : Writable<int>
    {
        return $this->output;
    }

    public function pipeTo(Writable<int> $output) : void
    {
        $this->output = $output;
    }

    public function isStdout() : bool
    {
        return $this->type === PipeType::Stdout;
    }

    public function isStderr() : bool
    {
        return $this->type === PipeType::Stderr;
    }

    public function close() : void
    {
        fclose($this->handle);
        $this->opened = false;
    }

}
<|endoftext|>


<commit_before>#include "qnitecircle.h"
#include "qniteaxes.h"
#include "qniteaxis.h"
#include "qnitecirclepainter.h"
#include "qniteclipper.h"
#include "qnitemapper.h"

#include <QLoggingCategory>
#include <QPolygon>

Q_LOGGING_CATEGORY(qnitecircle, "qnite.circle")

constexpr auto SELECTION_TOLERANCE = 20;

QniteCircle::QniteCircle(QQuickItem *parent)
    : QniteXYArtist(parent), m_highlightedId{-1}, m_highlightedIndex{-1} {
  setFlag(ItemHasContents, true);
  setClipper(new QniteClipper(this));
}

QniteCircle::~QniteCircle() {}

bool QniteCircle::select(const QList<QPoint> &path) {
  // nothing to select
  if (path.isEmpty()) {
    return false;
  }

  // when there are less than 3 point we use the point selection
  // algorithm which should select the nearest point
  if (path.size() < 3) {
    return select(path.first());
  }

  // create a polygon with the path so it is easier to check
  // if a point is in the path or not
  auto polygonPath = QPolygonF(QVector<QPoint>::fromList(path));

  // cycle through all the points and save those contained
  // in the polygon
  m_selectedIds.clear();
  auto ids = m_xMapped.keys();
  for (auto id : ids) {
    QPointF cp(m_xMapped.value(id), m_yMapped.value(id));

    if (polygonPath.containsPoint(cp, Qt::OddEvenFill)) {
      m_selectedIds << id;
    }
  }

  // no points have been selected
  if (m_selectedIds.isEmpty()) {
    return false;
  }

  emit selectedChanged();
  update();
  return true;
}

bool QniteCircle::select(const QPoint p) {
  // these variables are needed to keep
  // track of the nearest point during the search
  auto nearestId = -1;
  auto nearestIndex = -1;
  // we only evaluate points whose distance is below a
  // predefined tolerance
  qreal nearestDistance = SELECTION_TOLERANCE;

  auto ids = m_xMapped.keys();
  auto index = 0;
  for (auto id : ids) {
    QPointF cp(m_xMapped.value(id), m_yMapped.value(id));
    QPointF d = p - cp;
    auto distance = d.manhattanLength();
    if (distance < nearestDistance) {
      nearestId = id;
      nearestIndex = index;
      nearestDistance = distance;
      break;
    }
    index++;
  }

  // add the index to the selected points pool
  if (nearestId >= 0) {
    m_selectedIds.insert(nearestId);
    m_selectedIndexes.insert(nearestIndex);
    emit selectedChanged();
    update();
    return true;
  }

  return false;
}

void QniteCircle::clearSelection() {
  m_selectedIds.clear();
  m_selectedIndexes.clear();
  m_highlightedId = -1;
  m_highlightedIndex = -1;
  emit selectedChanged();
  update();
}

void QniteCircle::select(QList<int> indexes) {
  m_selectedIds.clear();
  m_selectedIndexes.clear();
  for (auto i : indexes) {
    if (i >= 0 && i < m_xValues.size()) {
      auto it = m_xValues.constBegin();
      it = it + i;
      m_selectedIds << it.key();
      m_selectedIndexes << i;
    }
  }
  // TODO: should emit selectedChanged???
  update();
}

void QniteCircle::highlight(int index) {
  m_selectedIds.clear();

  if (index >= 0 && index < m_xValues.size()) {
    auto it = m_xValues.constBegin();
    it = it + index;
    m_highlightedId = it.key();
    m_highlightedIndex = index;
  }

  update();
}

QNanoQuickItemPainter *QniteCircle::createItemPainter() const {
  return new QniteCirclePainter;
}
<commit_msg>Fixed issue with circle highlighting<commit_after>#include "qnitecircle.h"
#include "qniteaxes.h"
#include "qniteaxis.h"
#include "qnitecirclepainter.h"
#include "qniteclipper.h"
#include "qnitemapper.h"

#include <QLoggingCategory>
#include <QPolygon>

Q_LOGGING_CATEGORY(qnitecircle, "qnite.circle")

constexpr auto SELECTION_TOLERANCE = 20;

QniteCircle::QniteCircle(QQuickItem *parent)
    : QniteXYArtist(parent), m_highlightedId{-1}, m_highlightedIndex{-1} {
  setFlag(ItemHasContents, true);
  setClipper(new QniteClipper(this));
}

QniteCircle::~QniteCircle() {}

bool QniteCircle::select(const QList<QPoint> &path) {
  // nothing to select
  if (path.isEmpty()) {
    return false;
  }

  // when there are less than 3 point we use the point selection
  // algorithm which should select the nearest point
  if (path.size() < 3) {
    return select(path.first());
  }

  // create a polygon with the path so it is easier to check
  // if a point is in the path or not
  auto polygonPath = QPolygonF(QVector<QPoint>::fromList(path));

  // cycle through all the points and save those contained
  // in the polygon
  m_selectedIds.clear();
  auto ids = m_xMapped.keys();
  for (auto id : ids) {
    QPointF cp(m_xMapped.value(id), m_yMapped.value(id));

    if (polygonPath.containsPoint(cp, Qt::OddEvenFill)) {
      m_selectedIds << id;
    }
  }

  // no points have been selected
  if (m_selectedIds.isEmpty()) {
    return false;
  }

  emit selectedChanged();
  update();
  return true;
}

bool QniteCircle::select(const QPoint p) {
  // these variables are needed to keep
  // track of the nearest point during the search
  auto nearestId = -1;
  auto nearestIndex = -1;
  // we only evaluate points whose distance is below a
  // predefined tolerance
  qreal nearestDistance = SELECTION_TOLERANCE;

  auto ids = m_xMapped.keys();
  auto index = 0;
  for (auto id : ids) {
    QPointF cp(m_xMapped.value(id), m_yMapped.value(id));
    QPointF d = p - cp;
    auto distance = d.manhattanLength();
    if (distance < nearestDistance) {
      nearestId = id;
      nearestIndex = index;
      nearestDistance = distance;
      break;
    }
    index++;
  }

  // add the index to the selected points pool
  if (nearestId >= 0) {
    m_selectedIds.insert(nearestId);
    m_selectedIndexes.insert(nearestIndex);
    emit selectedChanged();
    update();
    return true;
  }

  return false;
}

void QniteCircle::clearSelection() {
  m_selectedIds.clear();
  m_selectedIndexes.clear();
  m_highlightedId = -1;
  m_highlightedIndex = -1;
  emit selectedChanged();
  update();
}

void QniteCircle::select(QList<int> indexes) {
  m_selectedIds.clear();
  m_selectedIndexes.clear();
  for (auto i : indexes) {
    if (i >= 0 && i < m_xValues.size()) {
      auto it = m_xValues.constBegin();
      it = it + i;
      m_selectedIds << it.key();
      m_selectedIndexes << i;
    }
  }
  // TODO: should emit selectedChanged???
  update();
}

void QniteCircle::highlight(int index) {
  if (index >= 0 && index < m_xValues.size()) {
    auto it = m_xValues.constBegin();
    it = it + index;
    m_highlightedId = it.key();
    m_highlightedIndex = index;
  }

  update();
}

QNanoQuickItemPainter *QniteCircle::createItemPainter() const {
  return new QniteCirclePainter;
}
<|endoftext|>


<commit_before>#include "FieldAccessor.h"
#include "JniLocalRef.h"
#include "ArgConverter.h"
#include "NativeScriptAssert.h"
#include "Util.h"
#include "V8GlobalHelpers.h"
#include <assert.h>

using namespace v8;
using namespace std;
using namespace tns;

void FieldAccessor::Init(JavaVM *jvm, ObjectManager *objectManager)
{
	this->jvm = jvm;
	this->objectManager = objectManager;
}

Local<Value> FieldAccessor::GetJavaField(const Local<Object>& target, FieldCallbackData *fieldData)
{
	JEnv env;

	auto isolate = Isolate::GetCurrent();
	EscapableHandleScope handleScope(isolate);

	Local<Value> fieldResult;

	jweak targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';

	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
								? fieldTypeName
								: (isFieldArray
									? fieldTypeName
									: ("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				jboolean result;
				if (isStatic)
				{
					result = env.GetStaticBooleanField(clazz, fieldId);
				}
				else
				{
					result = env.GetBooleanField(targetJavaObject, fieldId);
				}
				fieldResult = Boolean::New(isolate, (result == JNI_TRUE));
				break;
			}
			case 'B': //byte
			{
				jbyte result;
				if (isStatic)
				{
					result = env.GetStaticByteField(clazz, fieldId);
				}
				else
				{
					result = env.GetByteField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;
			}
			case 'C': //char
			{
				jchar result;
				if (isStatic)
				{
					result = env.GetStaticCharField(clazz, fieldId);
				}
				else
				{
					result = env.GetCharField(targetJavaObject, fieldId);
				}

				JniLocalRef str(env.NewString(&result, 1));
				jboolean bol = true;
				const char* resP = env.GetStringUTFChars(str, &bol);
				fieldResult = handleScope.Escape(ConvertToV8String(resP, 1));
				env.ReleaseStringUTFChars(str, resP);
				break;
			}
			case 'S': //short
			{
				jshort result;
				if (isStatic)
				{
					result = env.GetStaticShortField(clazz, fieldId);
				}
				else
				{
					result = env.GetShortField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;
			}
			case 'I': //int
			{
				jint result;
				if (isStatic)
				{
					result = env.GetStaticIntField(clazz, fieldId);
				}
				else
				{
					result = env.GetIntField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;

			}
			case 'J': //long
			{
				jlong result;
				if (isStatic)
				{
					result = env.GetStaticLongField(clazz, fieldId);
				}
				else
				{
					result = env.GetLongField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(ArgConverter::ConvertFromJavaLong(result));
				break;
			}
			case 'F': //float
			{
				jfloat result;
				if (isStatic)
				{
					result = env.GetStaticFloatField(clazz, fieldId);
				}
				else
				{
					result = env.GetFloatField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Number::New(isolate, (double) result));
				break;
			}
			case 'D': //double
			{
				jdouble result;
				if (isStatic)
				{
					result = env.GetStaticDoubleField(clazz, fieldId);
				}
				else
				{
					result = env.GetDoubleField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Number::New(isolate, result));
				break;
			}
			default:
			{
				// TODO:
				ASSERT_FAIL("Unknown field type");
				break;
			}
		}
	}
	else
	{
		bool isString = fieldTypeName == "java/lang/String";

		if (isString)
		{
			JniLocalRef result;
			if (isStatic)
			{
				result = env.GetStaticObjectField(clazz, fieldId);
			}
			else
			{
				result = env.GetObjectField(targetJavaObject, fieldId);
			}

			auto resultV8String = ArgConverter::jstringToV8String(result);
			fieldResult = handleScope.Escape(resultV8String);
		}
		else
		{
			jobject result;
			if (isStatic)
			{
				result = env.GetStaticObjectField(clazz, fieldId);
			}
			else
			{
				result = env.GetObjectField(targetJavaObject, fieldId);
			}

			if (result != nullptr)
			{
				int javaObjectID = objectManager->GetOrCreateObjectId(result);
				auto objectResult = objectManager->GetJsObjectByJavaObject(javaObjectID);

				if (objectResult.IsEmpty())
				{
					objectResult = objectManager->CreateJSWrapper(javaObjectID, fieldTypeName, result);
				}

				env.DeleteLocalRef(result);

				fieldResult = handleScope.Escape(objectResult);
			}
			else
			{
				fieldResult = Null(isolate);
			}
		}
	}
	return fieldResult;
}

void FieldAccessor::SetJavaField(const Local<Object>& target, const Local<Value>& value, FieldCallbackData *fieldData)
{
	JEnv env;

	auto isolate = Isolate::GetCurrent();
	HandleScope handleScope(isolate);

	jweak targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';

	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
								? fieldTypeName
								: (isFieldArray
									? fieldTypeName
									: ("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				//TODO: validate value is a boolean before calling
				if (isStatic)
				{
					env.SetStaticBooleanField(clazz, fieldId, value->BooleanValue());
				}
				else
				{
					env.SetBooleanField(targetJavaObject, fieldId, value->BooleanValue());
				}
				break;
			}
			case 'B': //byte
			{
				//TODO: validate value is a byte before calling
				if (isStatic)
				{
					env.SetStaticByteField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetByteField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'C': //char
			{
				//TODO: validate value is a single char
				String::Utf8Value stringValue(value->ToString());
				JniLocalRef value(env.NewStringUTF(*stringValue));
				const char* chars = env.GetStringUTFChars(value, 0);

				if (isStatic)
				{
					env.SetStaticCharField(clazz, fieldId, chars[0]);
				}
				else
				{
					env.SetCharField(targetJavaObject, fieldId, chars[0]);
				}
				env.ReleaseStringUTFChars(value, chars);
				break;
			}
			case 'S': //short
			{
				//TODO: validate value is a short before calling
				if (isStatic)
				{
					env.SetStaticShortField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetShortField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'I': //int
			{
				//TODO: validate value is a int before calling
				if (isStatic)
				{
					env.SetStaticIntField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetIntField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;

			}
			case 'J': //long
			{
				jlong longValue = static_cast<jlong>(ArgConverter::ConvertToJavaLong(value));
				if (isStatic)
				{
					env.SetStaticLongField(clazz, fieldId, longValue);
				}
				else
				{
					env.SetLongField(targetJavaObject, fieldId, longValue);
				}
				break;
			}
			case 'F': //float
			{
				if (isStatic)
				{
					env.SetStaticFloatField(clazz, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				else
				{
					env.SetFloatField(targetJavaObject, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				break;
			}
			case 'D': //double
			{
				if (isStatic)
				{
					env.SetStaticDoubleField(clazz, fieldId, value->NumberValue());
				}
				else
				{
					env.SetDoubleField(targetJavaObject, fieldId, value->NumberValue());
				}
				break;
			}
			default:
			{
				// TODO:
				ASSERT_FAIL("Unknown field type");
				break;
			}
		}
	}
	else
	{
		bool isString = fieldTypeName == "java/lang/String";
		if (isString)
		{
			//TODO: validate valie is a string;
			jstring result = nullptr;
			if(!value->IsNull()) {
				String::Utf8Value stringValue(value);
				result = env.NewStringUTF(*stringValue);
			}
			JniLocalRef value(result);

			if (isStatic)
			{
				env.SetStaticObjectField(clazz, fieldId, value);
			}
			else
			{
				env.SetObjectField(targetJavaObject, fieldId, value);
			}
		}
		else
		{
			auto objectWithHiddenID = value->ToObject();
			jweak javaObject = objectManager->GetJavaObjectByJsObject(objectWithHiddenID);

			if (isStatic)
			{
				env.SetStaticObjectField(clazz, fieldId, javaObject);
			}
			else
			{
				env.SetObjectField(targetJavaObject, fieldId, javaObject);
			}
		}
	}
}
<commit_msg>refactored field acessor get set logic for ref types<commit_after>#include "FieldAccessor.h"
#include "JniLocalRef.h"
#include "ArgConverter.h"
#include "NativeScriptAssert.h"
#include "Util.h"
#include "V8GlobalHelpers.h"
#include <assert.h>

using namespace v8;
using namespace std;
using namespace tns;

void FieldAccessor::Init(JavaVM *jvm, ObjectManager *objectManager)
{
	this->jvm = jvm;
	this->objectManager = objectManager;
}

Local<Value> FieldAccessor::GetJavaField(const Local<Object>& target, FieldCallbackData *fieldData)
{
	JEnv env;

	auto isolate = Isolate::GetCurrent();
	EscapableHandleScope handleScope(isolate);

	Local<Value> fieldResult;

	jweak targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';

	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
								? fieldTypeName
								: (isFieldArray
									? fieldTypeName
									: ("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				jboolean result;
				if (isStatic)
				{
					result = env.GetStaticBooleanField(clazz, fieldId);
				}
				else
				{
					result = env.GetBooleanField(targetJavaObject, fieldId);
				}
				fieldResult = Boolean::New(isolate, (result == JNI_TRUE));
				break;
			}
			case 'B': //byte
			{
				jbyte result;
				if (isStatic)
				{
					result = env.GetStaticByteField(clazz, fieldId);
				}
				else
				{
					result = env.GetByteField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;
			}
			case 'C': //char
			{
				jchar result;
				if (isStatic)
				{
					result = env.GetStaticCharField(clazz, fieldId);
				}
				else
				{
					result = env.GetCharField(targetJavaObject, fieldId);
				}

				JniLocalRef str(env.NewString(&result, 1));
				jboolean bol = true;
				const char* resP = env.GetStringUTFChars(str, &bol);
				fieldResult = handleScope.Escape(ConvertToV8String(resP, 1));
				env.ReleaseStringUTFChars(str, resP);
				break;
			}
			case 'S': //short
			{
				jshort result;
				if (isStatic)
				{
					result = env.GetStaticShortField(clazz, fieldId);
				}
				else
				{
					result = env.GetShortField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;
			}
			case 'I': //int
			{
				jint result;
				if (isStatic)
				{
					result = env.GetStaticIntField(clazz, fieldId);
				}
				else
				{
					result = env.GetIntField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Int32::New(isolate, result));
				break;

			}
			case 'J': //long
			{
				jlong result;
				if (isStatic)
				{
					result = env.GetStaticLongField(clazz, fieldId);
				}
				else
				{
					result = env.GetLongField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(ArgConverter::ConvertFromJavaLong(result));
				break;
			}
			case 'F': //float
			{
				jfloat result;
				if (isStatic)
				{
					result = env.GetStaticFloatField(clazz, fieldId);
				}
				else
				{
					result = env.GetFloatField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Number::New(isolate, (double) result));
				break;
			}
			case 'D': //double
			{
				jdouble result;
				if (isStatic)
				{
					result = env.GetStaticDoubleField(clazz, fieldId);
				}
				else
				{
					result = env.GetDoubleField(targetJavaObject, fieldId);
				}
				fieldResult = handleScope.Escape(Number::New(isolate, result));
				break;
			}
			default:
			{
				// TODO:
				ASSERT_FAIL("Unknown field type");
				break;
			}
		}
	}
	else
	{
		jobject result;

		if (isStatic)
		{
			result = env.GetStaticObjectField(clazz, fieldId);
		}
		else
		{
			result = env.GetObjectField(targetJavaObject, fieldId);
		}

		if(result != nullptr) {

			bool isString = fieldTypeName == "java/lang/String";
			if (isString)
			{
				auto resultV8Value = ArgConverter::jstringToV8String((jstring)result);
				fieldResult = handleScope.Escape(resultV8Value);
			}
			else
			{
				int javaObjectID = objectManager->GetOrCreateObjectId(result);
				auto objectResult = objectManager->GetJsObjectByJavaObject(javaObjectID);

				if (objectResult.IsEmpty())
				{
					objectResult = objectManager->CreateJSWrapper(javaObjectID, fieldTypeName, result);
				}

				fieldResult = handleScope.Escape(objectResult);
			}
			env.DeleteLocalRef(result);
		}
		else
		{
			fieldResult = handleScope.Escape(Null(isolate));
		}
	}
	return fieldResult;
}

void FieldAccessor::SetJavaField(const Local<Object>& target, const Local<Value>& value, FieldCallbackData *fieldData)
{
	JEnv env;

	auto isolate = Isolate::GetCurrent();
	HandleScope handleScope(isolate);

	jweak targetJavaObject;

	const auto& fieldTypeName = fieldData->signature;
	auto isStatic = fieldData->isStatic;

	auto isPrimitiveType = fieldTypeName.size() == 1;
	auto isFieldArray = fieldTypeName[0] == '[';

	if (fieldData->fid == nullptr)
	{
		auto fieldJniSig = isPrimitiveType
								? fieldTypeName
								: (isFieldArray
									? fieldTypeName
									: ("L" + fieldTypeName + ";"));

		if (isStatic)
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetStaticFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
		else
		{
			fieldData->clazz = env.FindClass(fieldData->declaringType);
			assert(fieldData->clazz != nullptr);
			fieldData->fid = env.GetFieldID(fieldData->clazz, fieldData->name, fieldJniSig);
			assert(fieldData->fid != nullptr);
		}
	}

	if (!isStatic)
	{
		targetJavaObject = objectManager->GetJavaObjectByJsObject(target);
	}

	auto fieldId = fieldData->fid;
	auto clazz = fieldData->clazz;

	if (isPrimitiveType)
	{
		switch (fieldTypeName[0])
		{
			case 'Z': //bool
			{
				//TODO: validate value is a boolean before calling
				if (isStatic)
				{
					env.SetStaticBooleanField(clazz, fieldId, value->BooleanValue());
				}
				else
				{
					env.SetBooleanField(targetJavaObject, fieldId, value->BooleanValue());
				}
				break;
			}
			case 'B': //byte
			{
				//TODO: validate value is a byte before calling
				if (isStatic)
				{
					env.SetStaticByteField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetByteField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'C': //char
			{
				//TODO: validate value is a single char
				String::Utf8Value stringValue(value->ToString());
				JniLocalRef value(env.NewStringUTF(*stringValue));
				const char* chars = env.GetStringUTFChars(value, 0);

				if (isStatic)
				{
					env.SetStaticCharField(clazz, fieldId, chars[0]);
				}
				else
				{
					env.SetCharField(targetJavaObject, fieldId, chars[0]);
				}
				env.ReleaseStringUTFChars(value, chars);
				break;
			}
			case 'S': //short
			{
				//TODO: validate value is a short before calling
				if (isStatic)
				{
					env.SetStaticShortField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetShortField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;
			}
			case 'I': //int
			{
				//TODO: validate value is a int before calling
				if (isStatic)
				{
					env.SetStaticIntField(clazz, fieldId, value->Int32Value());
				}
				else
				{
					env.SetIntField(targetJavaObject, fieldId, value->Int32Value());
				}
				break;

			}
			case 'J': //long
			{
				jlong longValue = static_cast<jlong>(ArgConverter::ConvertToJavaLong(value));
				if (isStatic)
				{
					env.SetStaticLongField(clazz, fieldId, longValue);
				}
				else
				{
					env.SetLongField(targetJavaObject, fieldId, longValue);
				}
				break;
			}
			case 'F': //float
			{
				if (isStatic)
				{
					env.SetStaticFloatField(clazz, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				else
				{
					env.SetFloatField(targetJavaObject, fieldId, static_cast<jfloat>(value->NumberValue()));
				}
				break;
			}
			case 'D': //double
			{
				if (isStatic)
				{
					env.SetStaticDoubleField(clazz, fieldId, value->NumberValue());
				}
				else
				{
					env.SetDoubleField(targetJavaObject, fieldId, value->NumberValue());
				}
				break;
			}
			default:
			{
				// TODO:
				ASSERT_FAIL("Unknown field type");
				break;
			}
		}
	}
	else
	{
		bool isString = fieldTypeName == "java/lang/String";
		jobject result = nullptr;

		if(!value->IsNull()) {
			if (isString)
			{
				//TODO: validate valie is a string;
				String::Utf8Value stringValue(value);
				result = env.NewStringUTF(*stringValue);
			}
			else
			{
				auto objectWithHiddenID = value->ToObject();
				result =objectManager->GetJavaObjectByJsObject(objectWithHiddenID);
			}
		}

		if (isStatic)
		{
			env.SetStaticObjectField(clazz, fieldId, result);
		}
		else
		{
			env.SetObjectField(targetJavaObject, fieldId, result);
		}

		if (isString)
		{
			env.DeleteLocalRef(result);
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "HttpConnection.hxx"
#include "ClusterConfig.hxx"
#include "ListenerConfig.hxx"
#include "Goto.txx"
#include "ForwardHttpRequest.hxx"
#include "TranslationHandler.hxx"
#include "Instance.hxx"
#include "Cookie.hxx"
#include "http_server/http_server.hxx"
#include "http_server/Request.hxx"
#include "http_server/Handler.hxx"
#include "http_server/Error.hxx"
#include "SocketProtocolError.hxx"
#include "access_log/Glue.hxx"
#include "pool.hxx"
#include "address_string.hxx"
#include "thread_socket_filter.hxx"
#include "thread_pool.hxx"
#include "uri/uri_verify.hxx"
#include "ssl/ssl_filter.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "system/Error.hxx"
#include "util/Exception.hxx"

#include <assert.h>

LbHttpConnection::LbHttpConnection(struct pool &_pool, LbInstance &_instance,
                                   const LbListenerConfig &_listener,
                                   const LbGoto &_destination,
                                   SocketAddress _client_address)
    :pool(_pool), instance(_instance), listener(_listener),
     initial_destination(_destination),
     client_address(address_to_string(pool, _client_address)),
     logger(*this)
{
    if (client_address == nullptr)
        client_address = "unknown";
}

gcc_pure
static int
HttpServerLogLevel(std::exception_ptr e)
{
    try {
        FindRetrowNested<HttpServerSocketError>(e);
    } catch (const HttpServerSocketError &) {
        e = std::current_exception();

        /* some socket errors caused by our client are less
           important */

        try {
            FindRetrowNested<std::system_error>(e);
        } catch (const std::system_error &se) {
            if (se.code().category() == ErrnoCategory() &&
                se.code().value() == ECONNRESET)
                return 4;
            return 4;
        }

        try {
            FindRetrowNested<SocketProtocolError>(e);
        } catch (...) {
            return 4;
        }
    }

    return 2;
}

/*
 * public
 *
 */

LbHttpConnection *
NewLbHttpConnection(LbInstance &instance,
                    const LbListenerConfig &listener,
                    const LbGoto &destination,
                    SslFactory *ssl_factory,
                    UniqueSocketDescriptor &&fd, SocketAddress address)
{
    assert(listener.destination.GetProtocol() == LbProtocol::HTTP);

    /* determine the local socket address */
    StaticSocketAddress local_address = fd.GetLocalAddress();

    auto fd_type = FdType::FD_TCP;

    SslFilter *ssl_filter = nullptr;
    const SocketFilter *filter = nullptr;
    void *filter_ctx = nullptr;

    if (ssl_factory != nullptr) {
        ssl_filter = ssl_filter_new(*ssl_factory);
        filter = &thread_socket_filter;
        filter_ctx =
            new ThreadSocketFilter(instance.event_loop,
                                   thread_pool_get_queue(instance.event_loop),
                                   &ssl_filter_get_handler(*ssl_filter));
    }

    struct pool *pool = pool_new_linear(instance.root_pool,
                                        "http_connection",
                                        2048);
    pool_set_major(pool);

    auto *connection = NewFromPool<LbHttpConnection>(*pool, *pool, instance,
                                                     listener, destination,
                                                     address);
    connection->ssl_filter = ssl_filter;

    instance.http_connections.push_back(*connection);

    connection->http = http_server_connection_new(pool, instance.event_loop,
                                                  fd.Release(), fd_type,
                                                  filter, filter_ctx,
                                                  local_address.IsDefined()
                                                  ? (SocketAddress)local_address
                                                  : nullptr,
                                                  address,
                                                  false,
                                                  *connection);
    return connection;
}

void
LbHttpConnection::Destroy()
{
    assert(!instance.http_connections.empty());

    auto &connections = instance.http_connections;
    connections.erase(connections.iterator_to(*this));

    DeleteUnrefTrashPool(pool, this);
}

void
LbHttpConnection::CloseAndDestroy()
{
    assert(listener.destination.GetProtocol() == LbProtocol::HTTP);
    assert(http != nullptr);

    http_server_connection_close(http);

    Destroy();
}

void
LbHttpConnection::SendError(HttpServerRequest &request, std::exception_ptr ep)
{
    const char *msg = listener.verbose_response
        ? p_strdup(request.pool, GetFullMessage(ep).c_str())
        : "Bad gateway";

    http_server_send_message(&request, HTTP_STATUS_BAD_GATEWAY, msg);
}

void
LbHttpConnection::LogSendError(HttpServerRequest &request,
                               std::exception_ptr ep)
{
    logger(2, ep);
    SendError(request, ep);
}

static void
SendResponse(HttpServerRequest &request,
             const LbSimpleHttpResponse &response)
{
    assert(response.IsDefined());

    http_server_simple_response(request, response.status,
                                response.location.empty() ? nullptr : response.location.c_str(),
                                response.message.empty() ? nullptr : response.message.c_str());
}

/*
 * http connection handler
 *
 */

void
LbHttpConnection::HandleHttpRequest(HttpServerRequest &request,
                                    CancellablePointer &cancel_ptr)
{
    ++instance.http_request_counter;

    request_start_time = std::chrono::steady_clock::now();
    canonical_host = nullptr;

    if (!uri_path_verify_quick(request.uri)) {
        http_server_send_message(&request, HTTP_STATUS_BAD_REQUEST,
                                 "Malformed request URI");
        return;
    }

    HandleHttpRequest(initial_destination, request, cancel_ptr);
}

void
LbHttpConnection::HandleHttpRequest(const LbGoto &destination,
                                    HttpServerRequest &request,
                                    CancellablePointer &cancel_ptr)
{
    const auto &goto_ = destination.FindRequestLeaf(request);
    if (goto_.response != nullptr) {
        SendResponse(request, *goto_.response);
        return;
    }

    if (goto_.lua != nullptr) {
        InvokeLua(*goto_.lua, request, cancel_ptr);
        return;
    }

    if (goto_.translation != nullptr) {
        AskTranslationServer(*goto_.translation, request, cancel_ptr);
        return;
    }

    assert(goto_.cluster != nullptr);
    ForwardHttpRequest(*goto_.cluster, request, cancel_ptr);
}

void
LbHttpConnection::ForwardHttpRequest(LbCluster &cluster,
                                     HttpServerRequest &request,
                                     CancellablePointer &cancel_ptr)
{
    ::ForwardHttpRequest(*this, request, cluster, cancel_ptr);
}

void
LbHttpConnection::LogHttpRequest(HttpServerRequest &request,
                                 http_status_t status, int64_t length,
                                 uint64_t bytes_received, uint64_t bytes_sent)
{
    if (instance.access_log != nullptr)
        instance.access_log->Log(request, nullptr,
                                 request.headers.Get("referer"),
                                 request.headers.Get("user-agent"),
                                 status, length,
                                 bytes_received, bytes_sent,
                                 std::chrono::steady_clock::now() - request_start_time);
}

void
LbHttpConnection::HttpConnectionError(std::exception_ptr e)
{
    logger(HttpServerLogLevel(e), e);

    assert(http != nullptr);
    http = nullptr;

    Destroy();
}

void
LbHttpConnection::HttpConnectionClosed()
{
    assert(http != nullptr);
    http = nullptr;

    Destroy();
}

std::string
LbHttpConnection::MakeLoggerDomain() const noexcept
{
    return "listener='" + listener.name
        + "' cluster='" + listener.destination.GetName()
        + "' client='" + client_address
        + "'";
}
<commit_msg>lb/HttpConnection: remove redundant "return"<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "HttpConnection.hxx"
#include "ClusterConfig.hxx"
#include "ListenerConfig.hxx"
#include "Goto.txx"
#include "ForwardHttpRequest.hxx"
#include "TranslationHandler.hxx"
#include "Instance.hxx"
#include "Cookie.hxx"
#include "http_server/http_server.hxx"
#include "http_server/Request.hxx"
#include "http_server/Handler.hxx"
#include "http_server/Error.hxx"
#include "SocketProtocolError.hxx"
#include "access_log/Glue.hxx"
#include "pool.hxx"
#include "address_string.hxx"
#include "thread_socket_filter.hxx"
#include "thread_pool.hxx"
#include "uri/uri_verify.hxx"
#include "ssl/ssl_filter.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "system/Error.hxx"
#include "util/Exception.hxx"

#include <assert.h>

LbHttpConnection::LbHttpConnection(struct pool &_pool, LbInstance &_instance,
                                   const LbListenerConfig &_listener,
                                   const LbGoto &_destination,
                                   SocketAddress _client_address)
    :pool(_pool), instance(_instance), listener(_listener),
     initial_destination(_destination),
     client_address(address_to_string(pool, _client_address)),
     logger(*this)
{
    if (client_address == nullptr)
        client_address = "unknown";
}

gcc_pure
static int
HttpServerLogLevel(std::exception_ptr e)
{
    try {
        FindRetrowNested<HttpServerSocketError>(e);
    } catch (const HttpServerSocketError &) {
        e = std::current_exception();

        /* some socket errors caused by our client are less
           important */

        try {
            FindRetrowNested<std::system_error>(e);
        } catch (const std::system_error &se) {
            if (se.code().category() == ErrnoCategory() &&
                se.code().value() == ECONNRESET)
                return 4;
        }

        try {
            FindRetrowNested<SocketProtocolError>(e);
        } catch (...) {
            return 4;
        }
    }

    return 2;
}

/*
 * public
 *
 */

LbHttpConnection *
NewLbHttpConnection(LbInstance &instance,
                    const LbListenerConfig &listener,
                    const LbGoto &destination,
                    SslFactory *ssl_factory,
                    UniqueSocketDescriptor &&fd, SocketAddress address)
{
    assert(listener.destination.GetProtocol() == LbProtocol::HTTP);

    /* determine the local socket address */
    StaticSocketAddress local_address = fd.GetLocalAddress();

    auto fd_type = FdType::FD_TCP;

    SslFilter *ssl_filter = nullptr;
    const SocketFilter *filter = nullptr;
    void *filter_ctx = nullptr;

    if (ssl_factory != nullptr) {
        ssl_filter = ssl_filter_new(*ssl_factory);
        filter = &thread_socket_filter;
        filter_ctx =
            new ThreadSocketFilter(instance.event_loop,
                                   thread_pool_get_queue(instance.event_loop),
                                   &ssl_filter_get_handler(*ssl_filter));
    }

    struct pool *pool = pool_new_linear(instance.root_pool,
                                        "http_connection",
                                        2048);
    pool_set_major(pool);

    auto *connection = NewFromPool<LbHttpConnection>(*pool, *pool, instance,
                                                     listener, destination,
                                                     address);
    connection->ssl_filter = ssl_filter;

    instance.http_connections.push_back(*connection);

    connection->http = http_server_connection_new(pool, instance.event_loop,
                                                  fd.Release(), fd_type,
                                                  filter, filter_ctx,
                                                  local_address.IsDefined()
                                                  ? (SocketAddress)local_address
                                                  : nullptr,
                                                  address,
                                                  false,
                                                  *connection);
    return connection;
}

void
LbHttpConnection::Destroy()
{
    assert(!instance.http_connections.empty());

    auto &connections = instance.http_connections;
    connections.erase(connections.iterator_to(*this));

    DeleteUnrefTrashPool(pool, this);
}

void
LbHttpConnection::CloseAndDestroy()
{
    assert(listener.destination.GetProtocol() == LbProtocol::HTTP);
    assert(http != nullptr);

    http_server_connection_close(http);

    Destroy();
}

void
LbHttpConnection::SendError(HttpServerRequest &request, std::exception_ptr ep)
{
    const char *msg = listener.verbose_response
        ? p_strdup(request.pool, GetFullMessage(ep).c_str())
        : "Bad gateway";

    http_server_send_message(&request, HTTP_STATUS_BAD_GATEWAY, msg);
}

void
LbHttpConnection::LogSendError(HttpServerRequest &request,
                               std::exception_ptr ep)
{
    logger(2, ep);
    SendError(request, ep);
}

static void
SendResponse(HttpServerRequest &request,
             const LbSimpleHttpResponse &response)
{
    assert(response.IsDefined());

    http_server_simple_response(request, response.status,
                                response.location.empty() ? nullptr : response.location.c_str(),
                                response.message.empty() ? nullptr : response.message.c_str());
}

/*
 * http connection handler
 *
 */

void
LbHttpConnection::HandleHttpRequest(HttpServerRequest &request,
                                    CancellablePointer &cancel_ptr)
{
    ++instance.http_request_counter;

    request_start_time = std::chrono::steady_clock::now();
    canonical_host = nullptr;

    if (!uri_path_verify_quick(request.uri)) {
        http_server_send_message(&request, HTTP_STATUS_BAD_REQUEST,
                                 "Malformed request URI");
        return;
    }

    HandleHttpRequest(initial_destination, request, cancel_ptr);
}

void
LbHttpConnection::HandleHttpRequest(const LbGoto &destination,
                                    HttpServerRequest &request,
                                    CancellablePointer &cancel_ptr)
{
    const auto &goto_ = destination.FindRequestLeaf(request);
    if (goto_.response != nullptr) {
        SendResponse(request, *goto_.response);
        return;
    }

    if (goto_.lua != nullptr) {
        InvokeLua(*goto_.lua, request, cancel_ptr);
        return;
    }

    if (goto_.translation != nullptr) {
        AskTranslationServer(*goto_.translation, request, cancel_ptr);
        return;
    }

    assert(goto_.cluster != nullptr);
    ForwardHttpRequest(*goto_.cluster, request, cancel_ptr);
}

void
LbHttpConnection::ForwardHttpRequest(LbCluster &cluster,
                                     HttpServerRequest &request,
                                     CancellablePointer &cancel_ptr)
{
    ::ForwardHttpRequest(*this, request, cluster, cancel_ptr);
}

void
LbHttpConnection::LogHttpRequest(HttpServerRequest &request,
                                 http_status_t status, int64_t length,
                                 uint64_t bytes_received, uint64_t bytes_sent)
{
    if (instance.access_log != nullptr)
        instance.access_log->Log(request, nullptr,
                                 request.headers.Get("referer"),
                                 request.headers.Get("user-agent"),
                                 status, length,
                                 bytes_received, bytes_sent,
                                 std::chrono::steady_clock::now() - request_start_time);
}

void
LbHttpConnection::HttpConnectionError(std::exception_ptr e)
{
    logger(HttpServerLogLevel(e), e);

    assert(http != nullptr);
    http = nullptr;

    Destroy();
}

void
LbHttpConnection::HttpConnectionClosed()
{
    assert(http != nullptr);
    http = nullptr;

    Destroy();
}

std::string
LbHttpConnection::MakeLoggerDomain() const noexcept
{
    return "listener='" + listener.name
        + "' cluster='" + listener.destination.GetName()
        + "' client='" + client_address
        + "'";
}
<|endoftext|>


<commit_before>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: Ken Zangelin
*/
#include <stdio.h>

#include "logMsg/traceLevels.h"

#include "common/globals.h"
#include "common/tag.h"
#include "ngsi/Metadata.h"

/* ****************************************************************************
*
* Metadata::Metadata -
*/
Metadata::Metadata()
{
  name  = "";
  type  = "";
  value = "";
}

/* ****************************************************************************
*
* Metadata::Metadata -
*
* FIXME 8: Copy also the Association!
*
*/
Metadata::Metadata(Metadata* mP)
{
  LM_T(LmtClone, ("'cloning' a Metadata"));

  name  = mP->name;
  type  = mP->type;
  value = mP->value;
}

/* ****************************************************************************
*
* Metadata::Metadata -
*/
Metadata::Metadata(std::string _name, std::string _type, std::string _value)
{
  name  = _name;
  type  = _type;
  value = _value;
}

/* ****************************************************************************
*
* Metadata::render -
*/
std::string Metadata::render(Format format, std::string indent, bool comma)
{
  std::string out     = "";
  std::string xmlTag  = "contextMetadata";
  std::string jsonTag = "metadatas";
  std::string xValue  = value;

  out += startTag(indent, xmlTag, jsonTag, format, false, false);
  out += valueTag(indent + "  ", "name", name, format, true);
  out += valueTag(indent + "  ", "type", type, format, true);

  if (type == "Association")
     xValue = std::string("\n") + association.render(format, indent + "  ");

  out += valueTag(indent + "  ", "value", xValue, format, false, (type == "Association"));
  out += endTag(indent, xmlTag, format, comma);

  return out;
}

/* ****************************************************************************
*
* Metadata::check -
*/
std::string Metadata::check(RequestType requestType, Format format, std::string indent, std::string predetectedError, int counter)
{
  if (name == "")
    return "missing metadata name";

  if ((value == "") && (type != "Association"))
    return "missing metadata value";

  if (type == "Association")
     return association.check(requestType, format, indent, predetectedError, counter);

  return "OK";
}

/* ****************************************************************************
*
* Metadata::present -
*/
void Metadata::present(std::string metadataType, int ix, std::string indent)
{
  PRINTF("%s%s Metadata %d:\n",   indent.c_str(), metadataType.c_str(), ix);
  PRINTF("%s  Name:     %s\n", indent.c_str(), name.c_str());
  PRINTF("%s  Type:     %s\n", indent.c_str(), type.c_str());
  PRINTF("%s  Value:    %s\n", indent.c_str(), value.c_str());
}

/* ****************************************************************************
*
* release -
*/
void Metadata::release(void)
{
   association.release();
}
<commit_msg>FIX Metadata doesn't need a vector name to render<commit_after>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: Ken Zangelin
*/
#include <stdio.h>

#include "logMsg/traceLevels.h"

#include "common/globals.h"
#include "common/tag.h"
#include "ngsi/Metadata.h"

/* ****************************************************************************
*
* Metadata::Metadata -
*/
Metadata::Metadata()
{
  name  = "";
  type  = "";
  value = "";
}

/* ****************************************************************************
*
* Metadata::Metadata -
*
* FIXME 8: Copy also the Association!
*
*/
Metadata::Metadata(Metadata* mP)
{
  LM_T(LmtClone, ("'cloning' a Metadata"));

  name  = mP->name;
  type  = mP->type;
  value = mP->value;
}

/* ****************************************************************************
*
* Metadata::Metadata -
*/
Metadata::Metadata(std::string _name, std::string _type, std::string _value)
{
  name  = _name;
  type  = _type;
  value = _value;
}

/* ****************************************************************************
*
* Metadata::render -
*/
std::string Metadata::render(Format format, std::string indent, bool comma)
{
  std::string out     = "";
  std::string tag  = "contextMetadata";
  std::string xValue  = value;

  out += startTag(indent, tag, tag, format, false, false);
  out += valueTag(indent + "  ", "name", name, format, true);
  out += valueTag(indent + "  ", "type", type, format, true);

  if (type == "Association")
     xValue = std::string("\n") + association.render(format, indent + "  ");

  out += valueTag(indent + "  ", "value", xValue, format, false, (type == "Association"));
  out += endTag(indent, tag, format, comma);

  return out;
}

/* ****************************************************************************
*
* Metadata::check -
*/
std::string Metadata::check(RequestType requestType, Format format, std::string indent, std::string predetectedError, int counter)
{
  if (name == "")
    return "missing metadata name";

  if ((value == "") && (type != "Association"))
    return "missing metadata value";

  if (type == "Association")
     return association.check(requestType, format, indent, predetectedError, counter);

  return "OK";
}

/* ****************************************************************************
*
* Metadata::present -
*/
void Metadata::present(std::string metadataType, int ix, std::string indent)
{
  PRINTF("%s%s Metadata %d:\n",   indent.c_str(), metadataType.c_str(), ix);
  PRINTF("%s  Name:     %s\n", indent.c_str(), name.c_str());
  PRINTF("%s  Type:     %s\n", indent.c_str(), type.c_str());
  PRINTF("%s  Value:    %s\n", indent.c_str(), value.c_str());
}

/* ****************************************************************************
*
* release -
*/
void Metadata::release(void)
{
   association.release();
}
<|endoftext|>