<commit_before>// Copyright CERN. This software is distributed under the terms of the GNU
// General Public License v3 (GPL Version 3).
//
// See http://www.gnu.org/licenses/ for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file AliMLResponse.cxx
/// \author pietro.fecchio@cern.ch, maximiliano.puccio@cern.ch

#include "AliMLResponse.h"

#include "yaml-cpp/yaml.h"

#include "AliLog.h"
#include "AliExternalBDT.h"

using std::map;
using std::pair;
using std::string;
using std::vector;

/// \cond CLASSIMP
ClassImp(AliMLResponse);
/// \endcond

//_______________________________________________________________________________
AliMLResponse::AliMLResponse()
    : TNamed(), fConfigFilePath{}, fModels{}, fCentClasses{}, fBins{}, fVariableNames{}, fNBins{}, fNVariables{},
      fBinsBegin{}, fRaw{} {
  //
  // Default constructor
  //
}

//_______________________________________________________________________________
AliMLResponse::AliMLResponse(const Char_t *name, const Char_t *title)
    : TNamed(name, title), fConfigFilePath{""}, fModels{}, fCentClasses{}, fBins{}, fVariableNames{}, fNBins{},
      fNVariables{}, fBinsBegin{}, fRaw{} {
  //
  // Standard constructor
  //
}

//_______________________________________________________________________________
AliMLResponse::~AliMLResponse() {
  //
  // Destructor
  //
}

//_______________________________________________________________________________
AliMLResponse::AliMLResponse(const AliMLResponse &source)
    : TNamed(source.GetName(), source.GetTitle()), fConfigFilePath{source.fConfigFilePath}, fModels{source.fModels},
      fCentClasses{source.fCentClasses}, fBins{source.fBins}, fVariableNames{source.fVariableNames},
      fNBins{source.fNBins}, fNVariables{source.fNVariables}, fBinsBegin{source.fBinsBegin}, fRaw{source.fRaw} {
  //
  // Copy constructor
  //
}

AliMLResponse &AliMLResponse::operator=(const AliMLResponse &source) {
  //
  // assignment operator
  //
  if (&source == this) return *this;

  TNamed::operator=(source);

  fConfigFilePath = source.fConfigFilePath;
  fModels         = source.fModels;
  fCentClasses    = source.fCentClasses;
  fBins           = source.fBins;
  fVariableNames  = source.fVariableNames;
  fNBins          = source.fNBins;
  fNVariables     = source.fNVariables;
  fBinsBegin      = source.fBinsBegin;
  fRaw            = source.fRaw;

  return *this;
}

//_______________________________________________________________________________
void AliMLResponse::CheckConfigFile(YAML::Node nodelist) {
  /// error for empty config file
  if (nodelist.IsNull()) {
    AliFatal("Empty .yaml config file, please check it! Exit");
  }
  /// error for bin/model number inconsistencies
  if ((nodelist["BINS"].as<vector<float>>().size() - 1) != nodelist["N_MODELS"].as<unsigned int>() ||
      (nodelist["N_MODELS"].as<unsigned int>() != nodelist["MODELS"].size())) {
    AliFatal("Inconsistency found in the number of bins/models, please check it! Exit");
  }
  /// error for variables/numberofvariable inconsistency
  if (nodelist["NUM_VAR"].as<unsigned int>() != nodelist["VAR_NAMES"].size()) {
    AliFatal("Inconsistency found in the number of varibles, please check it! Exit");
  }
  return;
}

//_______________________________________________________________________________
void AliMLResponse::MLResponseInit() {
  /// import config file from alien path
  string configPath = AliMLModelHandler::ImportFile(fConfigFilePath);
  YAML::Node nodeList;
  /// manage wrong config file path
  try {
    nodeList = YAML::LoadFile(configPath);
  } catch (std::exception &e) {
    AliFatal(Form("Yaml-ccp error: %s! Exit", e.what()));
  }
  /// manage inconsistencies in config file
  CheckConfigFile(nodeList);

  fVariableNames = nodeList["VAR_NAMES"].as<vector<string>>();
  fBins          = nodeList["BINS"].as<vector<float>>();
  fNBins         = nodeList["N_MODELS"].as<int>();
  fNVariables    = nodeList["NUM_VAR"].as<int>();
  fRaw           = nodeList["RAW_SCORE"].as<bool>();

  fBinsBegin = fBins.begin();

  for (const auto &model : nodeList["MODELS"]) {
    fModels.push_back(AliMLModelHandler{model});
  }

  for (auto &model : fModels) {
    bool comp = model.CompileModel();
    if (!comp) {
      AliFatal("Error in model compilation! Exit");
    }
  }
}

//_______________________________________________________________________________
int AliMLResponse::FindBin(double binvar) {
  vector<float>::iterator low;
  low = std::lower_bound(fBins.begin(), fBins.end(), binvar);
  return low - fBinsBegin;
}

//_______________________________________________________________________________
double AliMLResponse::Predict(double binvar, map<string, double> varmap) {
  if ((int)varmap.size() < fNVariables) {
    AliFatal("The variable map you provided to the predictor has a size smaller than the variable list size! Exit");
  }

  vector<double> features;
  for (const auto &varname : fVariableNames) {
    if (varmap.find(varname) == varmap.end()) {
      AliFatal(Form("Variable |%s| not found in variable list provided in config! Exit", varname.data()));
    }
    features.push_back(varmap[varname]);
  }

  int bin = FindBin(binvar);
  if (bin == 0 || bin == fNBins) {
    AliWarning("Binned variable outside range, no model available!");
    return -999.;
  }

  return fModels[bin - 1].GetModel()->Predict(&features[0], fNVariables, fRaw);
}

//________________________________________________________________
double AliMLResponse::Predict(double binvar, vector<double> variables) {
  if ((int)variables.size() != fNVariables) {
    AliFatal(Form("Number of variables passed (%d) different from the one used in the model (%d)! Exit", (int)variables.size(), fNVariables));
  }

  int bin = FindBin(binvar);
  if (bin == 0 || bin == fNBins) {
    AliWarning("Binned variable outside range, no model available!");
    return -999.;
  }

  return fModels[bin - 1].GetModel()->Predict(&variables[0], fNVariables, fRaw);
}

//________________________________________________________________
bool AliMLResponse::IsSelected(double binvar, std::map<std::string, double> varmap) {
  double score{0.};
  return IsSelected(binvar, varmap, score);
}

//________________________________________________________________
bool AliMLResponse::IsSelected(double binvar, std::vector<double> variables) {
  double score{0.};
  return IsSelected(binvar, variables, score);
}<commit_msg>Fix typo<commit_after>// Copyright CERN. This software is distributed under the terms of the GNU
// General Public License v3 (GPL Version 3).
//
// See http://www.gnu.org/licenses/ for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file AliMLResponse.cxx
/// \author pietro.fecchio@cern.ch, maximiliano.puccio@cern.ch

#include "AliMLResponse.h"

#include "yaml-cpp/yaml.h"

#include "AliLog.h"
#include "AliExternalBDT.h"

using std::map;
using std::pair;
using std::string;
using std::vector;

/// \cond CLASSIMP
ClassImp(AliMLResponse);
/// \endcond

//_______________________________________________________________________________
AliMLResponse::AliMLResponse()
    : TNamed(), fConfigFilePath{}, fModels{}, fCentClasses{}, fBins{}, fVariableNames{}, fNBins{}, fNVariables{},
      fBinsBegin{}, fRaw{} {
  //
  // Default constructor
  //
}

//_______________________________________________________________________________
AliMLResponse::AliMLResponse(const Char_t *name, const Char_t *title)
    : TNamed(name, title), fConfigFilePath{""}, fModels{}, fCentClasses{}, fBins{}, fVariableNames{}, fNBins{},
      fNVariables{}, fBinsBegin{}, fRaw{} {
  //
  // Standard constructor
  //
}

//_______________________________________________________________________________
AliMLResponse::~AliMLResponse() {
  //
  // Destructor
  //
}

//_______________________________________________________________________________
AliMLResponse::AliMLResponse(const AliMLResponse &source)
    : TNamed(source.GetName(), source.GetTitle()), fConfigFilePath{source.fConfigFilePath}, fModels{source.fModels},
      fCentClasses{source.fCentClasses}, fBins{source.fBins}, fVariableNames{source.fVariableNames},
      fNBins{source.fNBins}, fNVariables{source.fNVariables}, fBinsBegin{source.fBinsBegin}, fRaw{source.fRaw} {
  //
  // Copy constructor
  //
}

AliMLResponse &AliMLResponse::operator=(const AliMLResponse &source) {
  //
  // assignment operator
  //
  if (&source == this) return *this;

  TNamed::operator=(source);

  fConfigFilePath = source.fConfigFilePath;
  fModels         = source.fModels;
  fCentClasses    = source.fCentClasses;
  fBins           = source.fBins;
  fVariableNames  = source.fVariableNames;
  fNBins          = source.fNBins;
  fNVariables     = source.fNVariables;
  fBinsBegin      = source.fBinsBegin;
  fRaw            = source.fRaw;

  return *this;
}

//_______________________________________________________________________________
void AliMLResponse::CheckConfigFile(YAML::Node nodelist) {
  /// error for empty config file
  if (nodelist.IsNull()) {
    AliFatal("Empty .yaml config file, please check it! Exit");
  }
  /// error for bin/model number inconsistencies
  if ((nodelist["BINS"].as<vector<float>>().size() - 1) != nodelist["N_MODELS"].as<unsigned int>() ||
      (nodelist["N_MODELS"].as<unsigned int>() != nodelist["MODELS"].size())) {
    AliFatal("Inconsistency found in the number of bins/models, please check it! Exit");
  }
  /// error for variables/numberofvariable inconsistency
  if (nodelist["NUM_VAR"].as<unsigned int>() != nodelist["VAR_NAMES"].size()) {
    AliFatal("Inconsistency found in the number of variables, please check it! Exit");
  }
  return;
}

//_______________________________________________________________________________
void AliMLResponse::MLResponseInit() {
  /// import config file from alien path
  string configPath = AliMLModelHandler::ImportFile(fConfigFilePath);
  YAML::Node nodeList;
  /// manage wrong config file path
  try {
    nodeList = YAML::LoadFile(configPath);
  } catch (std::exception &e) {
    AliFatal(Form("Yaml-ccp error: %s! Exit", e.what()));
  }
  /// manage inconsistencies in config file
  CheckConfigFile(nodeList);

  fVariableNames = nodeList["VAR_NAMES"].as<vector<string>>();
  fBins          = nodeList["BINS"].as<vector<float>>();
  fNBins         = nodeList["N_MODELS"].as<int>();
  fNVariables    = nodeList["NUM_VAR"].as<int>();
  fRaw           = nodeList["RAW_SCORE"].as<bool>();

  fBinsBegin = fBins.begin();

  for (const auto &model : nodeList["MODELS"]) {
    fModels.push_back(AliMLModelHandler{model});
  }

  for (auto &model : fModels) {
    bool comp = model.CompileModel();
    if (!comp) {
      AliFatal("Error in model compilation! Exit");
    }
  }
}

//_______________________________________________________________________________
int AliMLResponse::FindBin(double binvar) {
  vector<float>::iterator low;
  low = std::lower_bound(fBins.begin(), fBins.end(), binvar);
  return low - fBinsBegin;
}

//_______________________________________________________________________________
double AliMLResponse::Predict(double binvar, map<string, double> varmap) {
  if ((int)varmap.size() < fNVariables) {
    AliFatal("The variable map you provided to the predictor has a size smaller than the variable list size! Exit");
  }

  vector<double> features;
  for (const auto &varname : fVariableNames) {
    if (varmap.find(varname) == varmap.end()) {
      AliFatal(Form("Variable |%s| not found in variable list provided in config! Exit", varname.data()));
    }
    features.push_back(varmap[varname]);
  }

  int bin = FindBin(binvar);
  if (bin == 0 || bin == fNBins) {
    AliWarning("Binned variable outside range, no model available!");
    return -999.;
  }

  return fModels[bin - 1].GetModel()->Predict(&features[0], fNVariables, fRaw);
}

//________________________________________________________________
double AliMLResponse::Predict(double binvar, vector<double> variables) {
  if ((int)variables.size() != fNVariables) {
    AliFatal(Form("Number of variables passed (%d) different from the one used in the model (%d)! Exit", (int)variables.size(), fNVariables));
  }

  int bin = FindBin(binvar);
  if (bin == 0 || bin == fNBins) {
    AliWarning("Binned variable outside range, no model available!");
    return -999.;
  }

  return fModels[bin - 1].GetModel()->Predict(&variables[0], fNVariables, fRaw);
}

//________________________________________________________________
bool AliMLResponse::IsSelected(double binvar, std::map<std::string, double> varmap) {
  double score{0.};
  return IsSelected(binvar, varmap, score);
}

//________________________________________________________________
bool AliMLResponse::IsSelected(double binvar, std::vector<double> variables) {
  double score{0.};
  return IsSelected(binvar, variables, score);
}<|endoftext|>


<commit_before>#include "BooleanCircuit.h"

extern "C" {
#include "provsql_utils.h"
#include <unistd.h>
#include <math.h>
}

#include <cassert>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <iostream>

using namespace std;

// Has to be redefined because of name hiding
unsigned BooleanCircuit::setGate(const uuid &u, BooleanGate type)
{
 unsigned id = Circuit::setGate(u, type);
  if(type == BooleanGate::IN)
    inputs.insert(id);
  return id;
}

unsigned BooleanCircuit::setGate(const uuid &u, BooleanGate type, double p)
{
  unsigned id = setGate(u, type);
  prob[id] = p;
  return id;
}

unsigned BooleanCircuit::addGate()
{
  unsigned id=Circuit::addGate();
  prob.push_back(1);
  return id;
}

std::string BooleanCircuit::toString(unsigned g) const
{
  std::string op;
  string result;

  switch(gates[g]) {
    case BooleanGate::IN:
      if(prob[g]==0.) {
        return "⊥";
      } else if(prob[g]==1.) {
        return "⊤";
      } else {
        return to_string(g)+"["+to_string(prob[g])+"]";
      }
    case BooleanGate::NOT:
      op="¬";
      break;
    case BooleanGate::UNDETERMINED:
      op="?";
      break;
    case BooleanGate::AND:
      op="∧";
      break;
    case BooleanGate::OR:
      op="∨";
      break;
  }

  if(wires[g].empty()) {
    if(gates[g]==BooleanGate::AND)
      return "⊤";
    else if(gates[g]==BooleanGate::OR)
      return "⊥";
    else return op;
  }

  for(auto s: wires[g]) {
    if(gates[g]==BooleanGate::NOT)
      result = op;
    else if(!result.empty())
      result+=" "+op+" ";
    result+=toString(s);
  }

  return "("+result+")";
}

double BooleanCircuit::dDNNFEvaluation(unsigned g) const
{
  switch(gates[g]) {
    case BooleanGate::IN:
      return prob[g];
    case BooleanGate::NOT:
      return 1-prob[g];
    case BooleanGate::AND:
      break;
    case BooleanGate::OR:
      break;
    case BooleanGate::UNDETERMINED:
      throw CircuitException("Incorrect gate type");
  }

  double result=(gates[g]==BooleanGate::AND?1:0);
  for(auto s: wires[g]) {
    double d = dDNNFEvaluation(s);
    if(gates[g]==BooleanGate::AND)
      result*=d;
    else
      result+=d;
  }

  return result;
}

bool BooleanCircuit::evaluate(unsigned g, const unordered_set<unsigned> &sampled) const
{
  bool disjunction=false;

  switch(gates[g]) {
    case BooleanGate::IN:
      return sampled.find(g)!=sampled.end();
    case BooleanGate::NOT:
      return !evaluate(*(wires[g].begin()), sampled);
    case BooleanGate::AND:
      disjunction = false;
      break;
    case BooleanGate::OR:
      disjunction = true;
      break;
    case BooleanGate::UNDETERMINED:
      throw CircuitException("Incorrect gate type");
  }

  for(auto s: wires[g]) {
    bool e = evaluate(s, sampled);
    if(disjunction && e)
      return true;
    if(!disjunction && !e)
      return false;
  }

  if(disjunction)
    return false;
  else
    return true;
}

double BooleanCircuit::monteCarlo(unsigned g, unsigned samples) const
{
  unsigned success=0;

  for(unsigned i=0; i<samples; ++i) {
    unordered_set<unsigned> sampled;
    for(unsigned in : inputs) {
      if(rand() *1. / RAND_MAX < prob[in]) {
        sampled.insert(in);
      }
    }

    if(evaluate(g, sampled))
      ++success;

    if(provsql_interrupted)
      throw CircuitException("Interrupted after "+to_string(i+1)+" samples");
  }

  return success*1./samples;
}

double BooleanCircuit::possibleWorlds(unsigned g) const
{
  if(inputs.size()>=8*sizeof(unsigned long long))
    throw CircuitException("Too many possible worlds to iterate over");

  unsigned long long nb=(1<<inputs.size());
  double totalp=0.;

  for(unsigned long long i=0; i < nb; ++i) {
    unordered_set<unsigned> s;
    double p = 1;

    unsigned j=0;
    for(unsigned in : inputs) {
      if(i & (1 << j)) {
        s.insert(in);
        p*=prob[in];
      } else {
        p*=1-prob[in];
      }
      ++j;
    }

    if(evaluate(g, s))
      totalp+=p;

    if(provsql_interrupted)
      throw CircuitException("Interrupted");
  }

  return totalp;
}

std::string BooleanCircuit::Tseytin(unsigned g, bool display_prob=false) const {
  vector<vector<int>> clauses;

  // Tseytin transformation
  for(unsigned i=0; i<gates.size(); ++i) {
    switch(gates[i]) {
      case BooleanGate::AND:
        {
          int id=i+1;
          vector<int> c = {id};
          for(int s: wires[i]) {
            clauses.push_back({-id, s+1});
            c.push_back(-s-1);
          }
          clauses.push_back(c);
          break;
        }

      case BooleanGate::OR:
        {
          int id=i+1;
          vector<int> c = {-id};
          for(int s: wires[i]) {
            clauses.push_back({id, -s-1});
            c.push_back(s+1);
          }
          clauses.push_back(c);
        }
        break;

      case BooleanGate::NOT:
        {
          int id=i+1;
          int s=*wires[i].begin();
          clauses.push_back({-id,-s-1});
          clauses.push_back({id,s+1});
          break;
        }

      case BooleanGate::IN:
      case BooleanGate::UNDETERMINED:
        ;
    }
  }
  clauses.push_back({(int)g+1});

  int fd;
  char cfilename[] = "/tmp/provsqlXXXXXX";
  fd = mkstemp(cfilename);
  close(fd);

  string filename=cfilename;
  ofstream ofs(filename.c_str());

  ofs << "p cnf " << gates.size() << " " << clauses.size() << "\n";

  for(unsigned i=0;i<clauses.size();++i) {
    for(int x : clauses[i]) {
      ofs << x << " ";
    }
    ofs << "0\n";
  }
  if(display_prob) {
    for(unsigned in : inputs) {
      ofs << "w " << (in+1) << " " << to_string(prob[in]) << "\n";
      ofs << "w -" << (in+1) << " " << to_string(1. - prob[in]) << "\n";
    }
  }

  ofs.close();

  return filename;
}

double BooleanCircuit::compilation(unsigned g, string compiler) const {
  string filename=BooleanCircuit::Tseytin(g);
  string outfilename=filename+".nnf";

//  throw CircuitException("filename: "+filename);

    string cmdline=compiler+" ";
  if(compiler=="d4") {
    cmdline+=filename+" -out="+outfilename;
  } else if(compiler=="c2d") {
    cmdline+="-in "+filename+" -silent";
  } else if(compiler=="dsharp") {
    cmdline+="-q -Fnnf "+outfilename+" "+filename;
  } else {
    throw CircuitException("Unknown compiler '"+compiler+"'");
  }

  int retvalue=system(cmdline.c_str());

  if(unlink(filename.c_str())) {
    throw CircuitException("Error removing "+filename);
  }

  if(retvalue)
    throw CircuitException("Error executing "+compiler);

  ifstream ifs(outfilename.c_str());

  string nnf;
  getline(ifs, nnf, ' ');

  if(nnf!="nnf") // unsatisfiable formula
    return 0.;

  unsigned nb_nodes, foobar, nb_variables;
  ifs >> nb_nodes >> foobar >> nb_variables;

  BooleanCircuit dnnf;

  if(nb_variables!=gates.size())
    throw CircuitException("Unreadable d-DNNF (wrong number of variables: " + to_string(nb_variables) +" vs " + to_string(gates.size()) + ")");

  std::string line;
  getline(ifs,line);
  unsigned i=0;
  while(getline(ifs,line)) {
    stringstream ss(line);

    char c;
    ss >> c;

    if(c=='O') {
      int var, args;
      ss >> var >> args;
      unsigned id=dnnf.getGate(to_string(i));
      dnnf.setGate(to_string(i), BooleanGate::OR);
      int g;
      while(ss >> g) {
        unsigned id2=dnnf.getGate(to_string(g));
        dnnf.addWire(id,id2);
      }
    } else if(c=='A') {
      int args;
      ss >> args;
      unsigned id=dnnf.getGate(to_string(i));
      dnnf.setGate(to_string(i), BooleanGate::AND);
      int g;
      while(ss >> g) {
        unsigned id2=dnnf.getGate(to_string(g));
        dnnf.addWire(id,id2);
      }
    } else if(c=='L') {
      int leaf;
      ss >> leaf;
      if(gates[abs(leaf)-1]==BooleanGate::IN) {
        if(leaf<0) {
          dnnf.setGate(to_string(i), BooleanGate::IN, 1-prob[-leaf-1]);
        } else {
          dnnf.setGate(to_string(i), BooleanGate::IN, prob[leaf-1]);
        }
      } else
        dnnf.setGate(to_string(i), BooleanGate::IN, 1.);
    } else
      throw CircuitException(string("Unreadable d-DNNF (unknown node type: ")+c+")");

    ++i;
  }

  ifs.close();
  if(unlink(outfilename.c_str())) {
    throw CircuitException("Error removing "+outfilename);
  }

//  throw CircuitException(toString(g) + "\n" + dnnf.toString(dnnf.getGate(to_string(i-1))));

  return dnnf.dDNNFEvaluation(dnnf.getGate(to_string(i-1)));
}

double BooleanCircuit::WeightMC(unsigned g, string opt) const {
  string filename=BooleanCircuit::Tseytin(g, true);

  //opt of the form 'delta;epsilon'
  stringstream ssopt(opt);
  string delta_s, epsilon_s;
  getline(ssopt, delta_s, ';');
  getline(ssopt, epsilon_s, ';');

  double delta = 0;
  try {
    delta=stod(delta_s);
  } catch (invalid_argument &e) {
    delta=0;
  }
  double epsilon = 0;
  try {
    epsilon=stod(epsilon_s);
  } catch (invalid_argument &e) {
    epsilon=0;
  }
  if(delta == 0) delta=0.2;
  if(epsilon == 0) epsilon=0.8;

  //TODO calcul numIterations

  //calcul pivotAC
  final double pivotAC=2*ceil(exp(3./2)*(1+1/epsilon)*(1+1/epsilon));

  string cmdline="weightmc --startIteration=0 --gaussuntil=400 --verbosity=0 --pivotAC="+to_string(pivotAC)+ " "+filename+" > "+filename+".out";

  int retvalue=system(cmdline.c_str());
  if(retvalue) {
    throw CircuitException("Error executing weightmc");
  }

  //parsing
  ifstream ifs((filename+".out").c_str());
  string line, prev_line;
  while(getline(ifs,line))
    prev_line=line;

  stringstream ss(prev_line);
  string result;
  ss >> result >> result >> result >> result >> result;

  istringstream iss(result);
  string val, exp;
  getline(iss, val, 'x');
  getline(iss, exp);
  double value=stod(val);
  exp=exp.substr(2);
  double exponent=stod(exp);
  double ret=value*(pow(2.0,exponent));
//  throw CircuitException(to_string(ret));

  if(unlink(filename.c_str())) {
    throw CircuitException("Error removing "+filename);
  }

  if(unlink((filename+".out").c_str())) {
    throw CircuitException("Error removing "+filename+".out");
  }

  return ret;
}
<commit_msg>Fix compilation<commit_after>#include "BooleanCircuit.h"

extern "C" {
#include "provsql_utils.h"
#include <unistd.h>
#include <math.h>
}

#include <cassert>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <iostream>

using namespace std;

// Has to be redefined because of name hiding
unsigned BooleanCircuit::setGate(const uuid &u, BooleanGate type)
{
 unsigned id = Circuit::setGate(u, type);
  if(type == BooleanGate::IN)
    inputs.insert(id);
  return id;
}

unsigned BooleanCircuit::setGate(const uuid &u, BooleanGate type, double p)
{
  unsigned id = setGate(u, type);
  prob[id] = p;
  return id;
}

unsigned BooleanCircuit::addGate()
{
  unsigned id=Circuit::addGate();
  prob.push_back(1);
  return id;
}

std::string BooleanCircuit::toString(unsigned g) const
{
  std::string op;
  string result;

  switch(gates[g]) {
    case BooleanGate::IN:
      if(prob[g]==0.) {
        return "⊥";
      } else if(prob[g]==1.) {
        return "⊤";
      } else {
        return to_string(g)+"["+to_string(prob[g])+"]";
      }
    case BooleanGate::NOT:
      op="¬";
      break;
    case BooleanGate::UNDETERMINED:
      op="?";
      break;
    case BooleanGate::AND:
      op="∧";
      break;
    case BooleanGate::OR:
      op="∨";
      break;
  }

  if(wires[g].empty()) {
    if(gates[g]==BooleanGate::AND)
      return "⊤";
    else if(gates[g]==BooleanGate::OR)
      return "⊥";
    else return op;
  }

  for(auto s: wires[g]) {
    if(gates[g]==BooleanGate::NOT)
      result = op;
    else if(!result.empty())
      result+=" "+op+" ";
    result+=toString(s);
  }

  return "("+result+")";
}

double BooleanCircuit::dDNNFEvaluation(unsigned g) const
{
  switch(gates[g]) {
    case BooleanGate::IN:
      return prob[g];
    case BooleanGate::NOT:
      return 1-prob[g];
    case BooleanGate::AND:
      break;
    case BooleanGate::OR:
      break;
    case BooleanGate::UNDETERMINED:
      throw CircuitException("Incorrect gate type");
  }

  double result=(gates[g]==BooleanGate::AND?1:0);
  for(auto s: wires[g]) {
    double d = dDNNFEvaluation(s);
    if(gates[g]==BooleanGate::AND)
      result*=d;
    else
      result+=d;
  }

  return result;
}

bool BooleanCircuit::evaluate(unsigned g, const unordered_set<unsigned> &sampled) const
{
  bool disjunction=false;

  switch(gates[g]) {
    case BooleanGate::IN:
      return sampled.find(g)!=sampled.end();
    case BooleanGate::NOT:
      return !evaluate(*(wires[g].begin()), sampled);
    case BooleanGate::AND:
      disjunction = false;
      break;
    case BooleanGate::OR:
      disjunction = true;
      break;
    case BooleanGate::UNDETERMINED:
      throw CircuitException("Incorrect gate type");
  }

  for(auto s: wires[g]) {
    bool e = evaluate(s, sampled);
    if(disjunction && e)
      return true;
    if(!disjunction && !e)
      return false;
  }

  if(disjunction)
    return false;
  else
    return true;
}

double BooleanCircuit::monteCarlo(unsigned g, unsigned samples) const
{
  unsigned success=0;

  for(unsigned i=0; i<samples; ++i) {
    unordered_set<unsigned> sampled;
    for(unsigned in : inputs) {
      if(rand() *1. / RAND_MAX < prob[in]) {
        sampled.insert(in);
      }
    }

    if(evaluate(g, sampled))
      ++success;

    if(provsql_interrupted)
      throw CircuitException("Interrupted after "+to_string(i+1)+" samples");
  }

  return success*1./samples;
}

double BooleanCircuit::possibleWorlds(unsigned g) const
{
  if(inputs.size()>=8*sizeof(unsigned long long))
    throw CircuitException("Too many possible worlds to iterate over");

  unsigned long long nb=(1<<inputs.size());
  double totalp=0.;

  for(unsigned long long i=0; i < nb; ++i) {
    unordered_set<unsigned> s;
    double p = 1;

    unsigned j=0;
    for(unsigned in : inputs) {
      if(i & (1 << j)) {
        s.insert(in);
        p*=prob[in];
      } else {
        p*=1-prob[in];
      }
      ++j;
    }

    if(evaluate(g, s))
      totalp+=p;

    if(provsql_interrupted)
      throw CircuitException("Interrupted");
  }

  return totalp;
}

std::string BooleanCircuit::Tseytin(unsigned g, bool display_prob=false) const {
  vector<vector<int>> clauses;

  // Tseytin transformation
  for(unsigned i=0; i<gates.size(); ++i) {
    switch(gates[i]) {
      case BooleanGate::AND:
        {
          int id=i+1;
          vector<int> c = {id};
          for(int s: wires[i]) {
            clauses.push_back({-id, s+1});
            c.push_back(-s-1);
          }
          clauses.push_back(c);
          break;
        }

      case BooleanGate::OR:
        {
          int id=i+1;
          vector<int> c = {-id};
          for(int s: wires[i]) {
            clauses.push_back({id, -s-1});
            c.push_back(s+1);
          }
          clauses.push_back(c);
        }
        break;

      case BooleanGate::NOT:
        {
          int id=i+1;
          int s=*wires[i].begin();
          clauses.push_back({-id,-s-1});
          clauses.push_back({id,s+1});
          break;
        }

      case BooleanGate::IN:
      case BooleanGate::UNDETERMINED:
        ;
    }
  }
  clauses.push_back({(int)g+1});

  int fd;
  char cfilename[] = "/tmp/provsqlXXXXXX";
  fd = mkstemp(cfilename);
  close(fd);

  string filename=cfilename;
  ofstream ofs(filename.c_str());

  ofs << "p cnf " << gates.size() << " " << clauses.size() << "\n";

  for(unsigned i=0;i<clauses.size();++i) {
    for(int x : clauses[i]) {
      ofs << x << " ";
    }
    ofs << "0\n";
  }
  if(display_prob) {
    for(unsigned in : inputs) {
      ofs << "w " << (in+1) << " " << to_string(prob[in]) << "\n";
      ofs << "w -" << (in+1) << " " << to_string(1. - prob[in]) << "\n";
    }
  }

  ofs.close();

  return filename;
}

double BooleanCircuit::compilation(unsigned g, string compiler) const {
  string filename=BooleanCircuit::Tseytin(g);
  string outfilename=filename+".nnf";

//  throw CircuitException("filename: "+filename);

    string cmdline=compiler+" ";
  if(compiler=="d4") {
    cmdline+=filename+" -out="+outfilename;
  } else if(compiler=="c2d") {
    cmdline+="-in "+filename+" -silent";
  } else if(compiler=="dsharp") {
    cmdline+="-q -Fnnf "+outfilename+" "+filename;
  } else {
    throw CircuitException("Unknown compiler '"+compiler+"'");
  }

  int retvalue=system(cmdline.c_str());

  if(unlink(filename.c_str())) {
    throw CircuitException("Error removing "+filename);
  }

  if(retvalue)
    throw CircuitException("Error executing "+compiler);

  ifstream ifs(outfilename.c_str());

  string nnf;
  getline(ifs, nnf, ' ');

  if(nnf!="nnf") // unsatisfiable formula
    return 0.;

  unsigned nb_nodes, foobar, nb_variables;
  ifs >> nb_nodes >> foobar >> nb_variables;

  BooleanCircuit dnnf;

  if(nb_variables!=gates.size())
    throw CircuitException("Unreadable d-DNNF (wrong number of variables: " + to_string(nb_variables) +" vs " + to_string(gates.size()) + ")");

  std::string line;
  getline(ifs,line);
  unsigned i=0;
  while(getline(ifs,line)) {
    stringstream ss(line);

    char c;
    ss >> c;

    if(c=='O') {
      int var, args;
      ss >> var >> args;
      unsigned id=dnnf.getGate(to_string(i));
      dnnf.setGate(to_string(i), BooleanGate::OR);
      int g;
      while(ss >> g) {
        unsigned id2=dnnf.getGate(to_string(g));
        dnnf.addWire(id,id2);
      }
    } else if(c=='A') {
      int args;
      ss >> args;
      unsigned id=dnnf.getGate(to_string(i));
      dnnf.setGate(to_string(i), BooleanGate::AND);
      int g;
      while(ss >> g) {
        unsigned id2=dnnf.getGate(to_string(g));
        dnnf.addWire(id,id2);
      }
    } else if(c=='L') {
      int leaf;
      ss >> leaf;
      if(gates[abs(leaf)-1]==BooleanGate::IN) {
        if(leaf<0) {
          dnnf.setGate(to_string(i), BooleanGate::IN, 1-prob[-leaf-1]);
        } else {
          dnnf.setGate(to_string(i), BooleanGate::IN, prob[leaf-1]);
        }
      } else
        dnnf.setGate(to_string(i), BooleanGate::IN, 1.);
    } else
      throw CircuitException(string("Unreadable d-DNNF (unknown node type: ")+c+")");

    ++i;
  }

  ifs.close();
  if(unlink(outfilename.c_str())) {
    throw CircuitException("Error removing "+outfilename);
  }

//  throw CircuitException(toString(g) + "\n" + dnnf.toString(dnnf.getGate(to_string(i-1))));

  return dnnf.dDNNFEvaluation(dnnf.getGate(to_string(i-1)));
}

double BooleanCircuit::WeightMC(unsigned g, string opt) const {
  string filename=BooleanCircuit::Tseytin(g, true);

  //opt of the form 'delta;epsilon'
  stringstream ssopt(opt);
  string delta_s, epsilon_s;
  getline(ssopt, delta_s, ';');
  getline(ssopt, epsilon_s, ';');

  double delta = 0;
  try {
    delta=stod(delta_s);
  } catch (invalid_argument &e) {
    delta=0;
  }
  double epsilon = 0;
  try {
    epsilon=stod(epsilon_s);
  } catch (invalid_argument &e) {
    epsilon=0;
  }
  if(delta == 0) delta=0.2;
  if(epsilon == 0) epsilon=0.8;

  //TODO calcul numIterations

  //calcul pivotAC
  const double pivotAC=2*ceil(exp(3./2)*(1+1/epsilon)*(1+1/epsilon));

  string cmdline="weightmc --startIteration=0 --gaussuntil=400 --verbosity=0 --pivotAC="+to_string(pivotAC)+ " "+filename+" > "+filename+".out";

  int retvalue=system(cmdline.c_str());
  if(retvalue) {
    throw CircuitException("Error executing weightmc");
  }

  //parsing
  ifstream ifs((filename+".out").c_str());
  string line, prev_line;
  while(getline(ifs,line))
    prev_line=line;

  stringstream ss(prev_line);
  string result;
  ss >> result >> result >> result >> result >> result;

  istringstream iss(result);
  string val, exp;
  getline(iss, val, 'x');
  getline(iss, exp);
  double value=stod(val);
  exp=exp.substr(2);
  double exponent=stod(exp);
  double ret=value*(pow(2.0,exponent));
//  throw CircuitException(to_string(ret));

  if(unlink(filename.c_str())) {
    throw CircuitException("Error removing "+filename);
  }

  if(unlink((filename+".out").c_str())) {
    throw CircuitException("Error removing "+filename+".out");
  }

  return ret;
}
<|endoftext|>


<commit_before><commit_msg>Fixes to the ForceDistanceConstraint tag checking scheme<commit_after><|endoftext|>


<commit_before>/*
 *
 * $Id$
 *
 * History:
 *
 * Bernd Wuebben, wuebben@math.cornell.edu:
 *
 * Much of this  is taken from the pppd sources in particular
 * /pppstat/pppstat.c, and modified to suit the needs of kppp.
 *
 *
 * Here the original history of pppstat.c:
 *
 * perkins@cps.msu.edu: Added compression statistics and alternate
 *                display. 11/94
 *
 * Brad Parker (brad@cayman.com) 6/92
 *
 * from the original "slstats" by Van Jaconson
 *
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
 *	- Initial distribution.
 */

#include "pppstats.h"

#include <ctype.h>
#include <errno.h>

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/ppp_defs.h>

#ifndef STREAMS
#if defined(__linux__) && defined(__powerpc__) \
    && (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
/* kludge alert! */
#undef __GLIBC__
#endif
#include <sys/socket.h>		/* *BSD, Linux, NeXT, Ultrix etc. */
#ifndef HAVE_NET_IF_PPP_H
#ifdef HAVE_LINUX_IF_PPP_H
#include <linux/if.h>
#include <linux/if_ppp.h>
#endif
#else
#include <net/if.h>
#include <net/if_ppp.h>
#endif

#else	/* STREAMS */
#include <sys/socket.h>
#include <sys/stropts.h>	/* SVR4, Solaris 2, SunOS 4, OSF/1, etc. */
#include <net/ppp_defs.h>
#include <net/pppio.h>
#include <net/if.h>
#include <sys/sockio.h>

#endif	/* STREAMS */

#include <qtimer.h>
#include <kdebug.h>
#include "pppstats.h"

PPPStats::PPPStats() {
  timer = new QTimer;
  connect(timer, SIGNAL(timeout()), SLOT(timerClick()));
}

PPPStats::~PPPStats() {
  stop();
  delete timer;
}

void PPPStats::timerClick() {
  enum IOStatus newStatus;

  doStats();

  if((ibytes != ibytes_last) && (obytes != obytes_last))
    newStatus = BytesBoth;
  else if(ibytes != ibytes_last)
    newStatus = BytesIn;
  else if(obytes != obytes_last)
    newStatus = BytesOut;
  else
    newStatus = BytesNone;

  if(newStatus != ioStatus)
    emit statsChanged(ioStatus = newStatus);

  ibytes_last = ibytes;
  obytes_last = obytes;
}

void PPPStats::setUnit(int u) {
  unit = u;
  sprintf(unitName, "ppp%d", unit);
}

void PPPStats::start() {
  timer->start(PPP_STATS_INTERVAL);
}

void PPPStats::stop() {
  emit statsChanged(BytesNone);
  timer->stop();
}

bool PPPStats::ifIsUp() {
  bool is_up;
  struct ifreq ifr;

#if defined(__svr4__ )
  usleep(1000000); // Needed for Solaris ?!
#endif

#ifdef STREAMS
    if ((t = open("/dev/ppp", O_RDONLY)) < 0) {
	perror("pppstats: Couldn't open /dev/ppp: ");
	return false;
    }
    if (!strioctl(t, PPPIO_ATTACH, (char*)&unit, sizeof(int), 0)) {
	fprintf(stderr, "pppstats: ppp%d is not available\n", unit);
	::close(t);
	return false;
    }
    // TODO: close t somewhere again
#endif
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("Couldn't create IP socket");
	return false;
    }

    strncpy(ifr.ifr_name, unitName, sizeof(ifr.ifr_name));

    if(ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
        if (errno)
          fprintf(stderr, "Couldn't find interface %s: %s\n",
                  unitName, strerror(errno));
	::close(s);
	s = 0;
	return 0;
    }

    if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != 0) {
	is_up = true;
	kdDebug(5002) << "Interface is up" << endl;
    }
    else{
      is_up = false;
      ::close(s);
      s = 0;
      kdDebug(5002) << "Interface is down" << endl;
    }

    return is_up;
}

bool PPPStats::initStats() {

  struct sockaddr_in *sinp;
  struct ifreq ifr;

  ibytes = 0;
  ipackets = 0;
  ibytes_last = 0;
  obytes_last = 0;
  compressedin = 0;
  uncompressedin = 0;
  errorin = 0;
  obytes = 0;
  opackets = 0;
  compressed = 0;
  packetsunc = 0;
  packetsoutunc = 0;
  ioStatus = BytesNone;

  strcpy(ifr.ifr_name, unitName);

  if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
  }

  sinp = (struct sockaddr_in*)&ifr.ifr_addr;

  if(sinp->sin_addr.s_addr)
    local_ip_address = inet_ntoa(sinp->sin_addr);
  else
    local_ip_address = "";
  kdDebug(5002) << "Local IP: " << local_ip_address << endl;

  if (ioctl(s, SIOCGIFDSTADDR, &ifr) < 0)
    ;

  sinp = (struct sockaddr_in*)&ifr.ifr_dstaddr;

  if(sinp->sin_addr.s_addr)
    remote_ip_address = inet_ntoa(sinp->sin_addr);
  else
    remote_ip_address = "";
  kdDebug(5002) << "Remote IP: " << remote_ip_address << endl;

  return true;

}

bool PPPStats::doStats() {
  struct ppp_stats cur;

  if(! get_ppp_stats(&cur)){
    return false;
  }

  // "in"  "pack"  "comp"  "uncomp"  "err"
  // IN    PACK    VJCOMP  VJUNC     VJERR

  ibytes =   cur.p.ppp_ibytes; 			// bytes received
  ipackets =   cur.p.ppp_ipackets; 		// packets recieved
  compressedin =  cur.vj.vjs_compressedin; 	// inbound compressed packets
  uncompressedin =   cur.vj.vjs_uncompressedin; // inbound uncompressed packets
  errorin =  cur.vj.vjs_errorin; 		//receive errors

  //  "out"  "pack"  "comp"  "uncomp"  "ip"
  // OUT       PACK   JCOMP   VJUNC    NON-VJ

  obytes =  cur.p.ppp_obytes; 		       	// raw bytes sent
  opackets =  cur.p.ppp_opackets; 		// packets sent
  compressed =  cur.vj.vjs_compressed; 		//outbound compressed packets

  // outbound packets - outbound compressed packets
  packetsunc =  cur.vj.vjs_packets - cur.vj.vjs_compressed;

  // packets sent - oubount compressed
  packetsoutunc = cur.p.ppp_opackets - cur.vj.vjs_packets;

  return true;
}

#ifndef STREAMS
bool PPPStats::get_ppp_stats(struct ppp_stats *curp){

  struct ifpppstatsreq req;

    if(s==0)
      return false;

#ifdef __linux__
    req.stats_ptr = (caddr_t) &req.stats;
    sprintf(req.ifr__name, "ppp%d", unit);
#else
    sprintf(req.ifr_name, "ppp%d", unit);
#endif
    if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
	if (errno == ENOTTY)
	    fprintf(stderr, "pppstats: kernel support missing\n");
	else
	    perror("ioctl(SIOCGPPPSTATS)");
	return false;
    }
    *curp = req.stats;
    return true;
}

#else	/* STREAMS */
bool PPPStats::get_ppp_stats( struct ppp_stats *curp){

    if (!strioctl(t, PPPIO_GETSTAT, (char*)curp, 0, sizeof(*curp))) {
	if (errno == EINVAL)
	    fprintf(stderr, "pppstats: kernel support missing\n");
	else
	    perror("pppstats: Couldn't get statistics");
	return false;
    }
    return true;
}

bool PPPStats::strioctl(int fd, int cmd, char* ptr, int ilen, int olen){

    struct strioctl str;

    str.ic_cmd = cmd;
    str.ic_timout = 0;
    str.ic_len = ilen;
    str.ic_dp = ptr;
    if (ioctl(fd, I_STR, &str) == -1)
	return false;
    if (str.ic_len != olen)
	fprintf(stderr, "strioctl: expected %d bytes, got %d for cmd %x\n",
	       olen, str.ic_len, cmd);
    return true;
}
#endif /* STREAMS */

#include "pppstats.moc"

<commit_msg>ignore<commit_after>/*
 *
 * $Id$
 *
 * History:
 *
 * Bernd Wuebben, wuebben@math.cornell.edu:
 *
 * Much of this  is taken from the pppd sources in particular
 * /pppstat/pppstat.c, and modified to suit the needs of kppp.
 *
 *
 * Here the original history of pppstat.c:
 *
 * perkins@cps.msu.edu: Added compression statistics and alternate
 *                display. 11/94
 *
 * Brad Parker (brad@cayman.com) 6/92
 *
 * from the original "slstats" by Van Jaconson
 *
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
 *	- Initial distribution.
 */

#include <ctype.h>
#include <errno.h>

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/ppp_defs.h>

#ifndef STREAMS
#if defined(__linux__) && defined(__powerpc__) \
    && (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
/* kludge alert! */
#undef __GLIBC__
#endif
#include <sys/socket.h>		/* *BSD, Linux, NeXT, Ultrix etc. */
#ifndef HAVE_NET_IF_PPP_H
#ifdef HAVE_LINUX_IF_PPP_H
#include <linux/if.h>
#include <linux/if_ppp.h>
#endif
#else
#include <net/if.h>
#include <net/if_ppp.h>
#endif

#else	/* STREAMS */
#include <sys/socket.h>
#include <sys/stropts.h>	/* SVR4, Solaris 2, SunOS 4, OSF/1, etc. */
#include <net/ppp_defs.h>
#include <net/pppio.h>
#include <net/if.h>
#include <sys/sockio.h>

#endif	/* STREAMS */

#include <qtimer.h>
#include <kdebug.h>

PPPStats::PPPStats() {
  timer = new QTimer;
  connect(timer, SIGNAL(timeout()), SLOT(timerClick()));
}

PPPStats::~PPPStats() {
  stop();
  delete timer;
}

void PPPStats::timerClick() {
  enum IOStatus newStatus;

  doStats();

  if((ibytes != ibytes_last) && (obytes != obytes_last))
    newStatus = BytesBoth;
  else if(ibytes != ibytes_last)
    newStatus = BytesIn;
  else if(obytes != obytes_last)
    newStatus = BytesOut;
  else
    newStatus = BytesNone;

  if(newStatus != ioStatus)
    emit statsChanged(ioStatus = newStatus);

  ibytes_last = ibytes;
  obytes_last = obytes;
}

void PPPStats::setUnit(int u) {
  unit = u;
  sprintf(unitName, "ppp%d", unit);
}

void PPPStats::start() {
  timer->start(PPP_STATS_INTERVAL);
}

void PPPStats::stop() {
  emit statsChanged(BytesNone);
  timer->stop();
}

bool PPPStats::ifIsUp() {
  bool is_up;
  struct ifreq ifr;

#if defined(__svr4__ )
  usleep(1000000); // Needed for Solaris ?!
#endif

#ifdef STREAMS
    if ((t = open("/dev/ppp", O_RDONLY)) < 0) {
	perror("pppstats: Couldn't open /dev/ppp: ");
	return false;
    }
    if (!strioctl(t, PPPIO_ATTACH, (char*)&unit, sizeof(int), 0)) {
	fprintf(stderr, "pppstats: ppp%d is not available\n", unit);
	::close(t);
	return false;
    }
    // TODO: close t somewhere again
#endif
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("Couldn't create IP socket");
	return false;
    }

    strncpy(ifr.ifr_name, unitName, sizeof(ifr.ifr_name));

    if(ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
        if (errno)
          fprintf(stderr, "Couldn't find interface %s: %s\n",
                  unitName, strerror(errno));
	::close(s);
	s = 0;
	return 0;
    }

    if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != 0) {
	is_up = true;
	kdDebug(5002) << "Interface is up" << endl;
    }
    else{
      is_up = false;
      ::close(s);
      s = 0;
      kdDebug(5002) << "Interface is down" << endl;
    }

    return is_up;
}

bool PPPStats::initStats() {

  struct sockaddr_in *sinp;
  struct ifreq ifr;

  ibytes = 0;
  ipackets = 0;
  ibytes_last = 0;
  obytes_last = 0;
  compressedin = 0;
  uncompressedin = 0;
  errorin = 0;
  obytes = 0;
  opackets = 0;
  compressed = 0;
  packetsunc = 0;
  packetsoutunc = 0;
  ioStatus = BytesNone;

  strcpy(ifr.ifr_name, unitName);

  if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
  }

  sinp = (struct sockaddr_in*)&ifr.ifr_addr;

  if(sinp->sin_addr.s_addr)
    local_ip_address = inet_ntoa(sinp->sin_addr);
  else
    local_ip_address = "";
  kdDebug(5002) << "Local IP: " << local_ip_address << endl;

  if (ioctl(s, SIOCGIFDSTADDR, &ifr) < 0)
    ;

  sinp = (struct sockaddr_in*)&ifr.ifr_dstaddr;

  if(sinp->sin_addr.s_addr)
    remote_ip_address = inet_ntoa(sinp->sin_addr);
  else
    remote_ip_address = "";
  kdDebug(5002) << "Remote IP: " << remote_ip_address << endl;

  return true;

}

bool PPPStats::doStats() {
  struct ppp_stats cur;

  if(! get_ppp_stats(&cur)){
    return false;
  }

  // "in"  "pack"  "comp"  "uncomp"  "err"
  // IN    PACK    VJCOMP  VJUNC     VJERR

  ibytes =   cur.p.ppp_ibytes; 			// bytes received
  ipackets =   cur.p.ppp_ipackets; 		// packets recieved
  compressedin =  cur.vj.vjs_compressedin; 	// inbound compressed packets
  uncompressedin =   cur.vj.vjs_uncompressedin; // inbound uncompressed packets
  errorin =  cur.vj.vjs_errorin; 		//receive errors

  //  "out"  "pack"  "comp"  "uncomp"  "ip"
  // OUT       PACK   JCOMP   VJUNC    NON-VJ

  obytes =  cur.p.ppp_obytes; 		       	// raw bytes sent
  opackets =  cur.p.ppp_opackets; 		// packets sent
  compressed =  cur.vj.vjs_compressed; 		//outbound compressed packets

  // outbound packets - outbound compressed packets
  packetsunc =  cur.vj.vjs_packets - cur.vj.vjs_compressed;

  // packets sent - oubount compressed
  packetsoutunc = cur.p.ppp_opackets - cur.vj.vjs_packets;

  return true;
}

#ifndef STREAMS
bool PPPStats::get_ppp_stats(struct ppp_stats *curp){

  struct ifpppstatsreq req;

    if(s==0)
      return false;

#ifdef __linux__
    req.stats_ptr = (caddr_t) &req.stats;
    sprintf(req.ifr__name, "ppp%d", unit);
#else
    sprintf(req.ifr_name, "ppp%d", unit);
#endif
    if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
	if (errno == ENOTTY)
	    fprintf(stderr, "pppstats: kernel support missing\n");
	else
	    perror("ioctl(SIOCGPPPSTATS)");
	return false;
    }
    *curp = req.stats;
    return true;
}

#else	/* STREAMS */
bool PPPStats::get_ppp_stats( struct ppp_stats *curp){

    if (!strioctl(t, PPPIO_GETSTAT, (char*)curp, 0, sizeof(*curp))) {
	if (errno == EINVAL)
	    fprintf(stderr, "pppstats: kernel support missing\n");
	else
	    perror("pppstats: Couldn't get statistics");
	return false;
    }
    return true;
}

bool PPPStats::strioctl(int fd, int cmd, char* ptr, int ilen, int olen){

    struct strioctl str;

    str.ic_cmd = cmd;
    str.ic_timout = 0;
    str.ic_len = ilen;
    str.ic_dp = ptr;
    if (ioctl(fd, I_STR, &str) == -1)
	return false;
    if (str.ic_len != olen)
	fprintf(stderr, "strioctl: expected %d bytes, got %d for cmd %x\n",
	       olen, str.ic_len, cmd);
    return true;
}
#endif /* STREAMS */

#include "pppstats.moc"

<|endoftext|>


<commit_before>/*
    This file is part of KOrganizer.
    Copyright (c) 1998 Barry D Benowitz
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

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

#include <unistd.h>
#include <stdio.h>

#include <klocale.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <kurl.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kprocess.h>

#include <libkcal/event.h>
#include <libkcal/todo.h>

#include "version.h"
#include "koprefs.h"

#include "komailclient.h"

KOMailClient::KOMailClient()
{
}

KOMailClient::~KOMailClient()
{
}

bool KOMailClient::mailAttendees(IncidenceBase *incidence,const QString &attachment)
{
  Attendee::List attendees = incidence->attendees();
  if (attendees.count() == 0) return false;

  QString to;
  for(uint i=0; i<attendees.count();++i) {
    to += (*attendees.at(i))->email();
    if (i != attendees.count()-1) to += ", ";
  }

  QString from = KOPrefs::instance()->email();

  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Object";
  }

  QString body = createBody(incidence);

  bool bcc = KOPrefs::instance()->mBcc;

  return send(from,to,subject,body,bcc,attachment);
}

bool KOMailClient::mailOrganizer(IncidenceBase *incidence,const QString &attachment)
{
  QString to = incidence->organizer();

  QString from = KOPrefs::instance()->email();

  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Message";
  }

  QString body = createBody(incidence);

  bool bcc = KOPrefs::instance()->mBcc;

  return send(from,to,subject,body,bcc,attachment);
}

bool KOMailClient::mailTo(IncidenceBase *incidence,const QString &recipients,
                          const QString &attachment)
{
  QString from = KOPrefs::instance()->email();
  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Message";
  }
  QString body = createBody(incidence);
  bool bcc = KOPrefs::instance()->mBcc;
  kdDebug () << "KOMailClient::mailTo " << recipients << endl;
  return send(from,recipients,subject,body,bcc,attachment);
}

bool KOMailClient::send(const QString &from,const QString &to,
                        const QString &subject,const QString &body,bool bcc,
                        const QString &attachment)
{
  kdDebug(5850) << "KOMailClient::sendMail():\nFrom: " << from << "\nTo: " << to
            << "\nSubject: " << subject << "\nBody: \n" << body
            << "\nAttachment:\n" << attachment << endl;

  if (KOPrefs::instance()->mMailClient == KOPrefs::MailClientSendmail) {
    bool needHeaders = true;

    QString command = KStandardDirs::findExe(QString::fromLatin1("sendmail"),
        QString::fromLatin1("/sbin:/usr/sbin:/usr/lib"));
    if (!command.isNull()) command += QString::fromLatin1(" -oi -t");
    else {
      command = KStandardDirs::findExe(QString::fromLatin1("mail"));
      if (command.isNull()) return false; // give up

      command.append(QString::fromLatin1(" -s "));
      command.append(KProcess::quote(subject));

      if (bcc) {
        command.append(QString::fromLatin1(" -b "));
        command.append(KProcess::quote(from));
      }

      command.append(" ");
      command.append(KProcess::quote(to));

      needHeaders = false;
    }

    FILE * fd = popen(command.local8Bit(),"w");
    if (!fd)
    {
      kdError() << "Unable to open a pipe to " << command << endl;
      return false;
    }

    QString textComplete;
    if (needHeaders)
    {
      textComplete += QString::fromLatin1("From: ") + from + '\n';
      textComplete += QString::fromLatin1("To: ") + to + '\n';
      if (bcc) textComplete += QString::fromLatin1("Bcc: ") + from + '\n';
      textComplete += QString::fromLatin1("Subject: ") + subject + '\n';
      textComplete += QString::fromLatin1("X-Mailer: KOrganizer") + korgVersion + '\n';
    }
    textComplete += '\n'; // end of headers
    textComplete += body;
    textComplete += '\n';
    textComplete += attachment;

    fwrite(textComplete.local8Bit(),textComplete.length(),1,fd);

    pclose(fd);
  } else {
    if (!kapp->dcopClient()->isApplicationRegistered("kmail")) {
			if (KApplication::startServiceByDesktopName("kmail")) {
        KMessageBox::error(0,i18n("No running instance of KMail found."));
        return false;
			}
    }

    if (attachment.isEmpty()) {
      if (!kMailOpenComposer(to,"",from,subject,body,0,KURL())) return false;
    } else {
      QString meth;
      int idx = attachment.find("METHOD");
      if (idx>=0) {
        idx = attachment.find(':',idx)+1;
        meth = attachment.mid(idx,attachment.find('\n',idx)-idx);
	meth = meth.lower();
      } else {
        meth = "publish";
      }
      if (!kMailOpenComposer(to,"",from,subject,body,0,"cal.ics","7bit",
                             attachment.utf8(),"text","calendar","method",meth,
                             "attachment")) return false;
    }
  }
  return true;
}

int KOMailClient::kMailOpenComposer(const QString& arg0,const QString& arg1,
  const QString& arg2,const QString& arg3,const QString& arg4,int arg5,
  const KURL& arg6)
{
  int result = 0;

  QByteArray data, replyData;
  QCString replyType;
  QDataStream arg( data, IO_WriteOnly );
  arg << arg0;
  arg << arg1;
  arg << arg2;
  arg << arg3;
  arg << arg4;
  arg << arg5;
  arg << arg6;
  if (kapp->dcopClient()->call("kmail","KMailIface","openComposer(QString,QString,QString,QString,QString,int,KURL)", data, replyType, replyData ) ) {
    if ( replyType == "int" ) {
      QDataStream _reply_stream( replyData, IO_ReadOnly );
      _reply_stream >> result;
    } else {
      kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
    }
  } else {
    kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
  }
  return result;
}

int KOMailClient::kMailOpenComposer( const QString& arg0, const QString& arg1,
                                     const QString& arg2, const QString& arg3,
                                     const QString& arg4, int arg5, const QString& arg6,
                                     const QCString& arg7, const QCString& arg8,
                                     const QCString& arg9, const QCString& arg10,
                                     const QCString& arg11, const QString& arg12,
                                     const QCString& arg13 )
{
    int result = 0;

    QByteArray data, replyData;
    QCString replyType;
    QDataStream arg( data, IO_WriteOnly );
    arg << arg0;
    arg << arg1;
    arg << arg2;
    arg << arg3;
    arg << arg4;
    arg << arg5;
    arg << arg6;
    arg << arg7;
    arg << arg8;
    arg << arg9;
    arg << arg10;
    arg << arg11;
    arg << arg12;
    arg << arg13;
    if ( kapp->dcopClient()->call("kmail","KMailIface","openComposer(QString,QString,QString,QString,QString,int,QString,QCString,QCString,QCString,QCString,QCString,QString,QCString)", data, replyType, replyData ) ) {
	if ( replyType == "int" ) {
	    QDataStream _reply_stream( replyData, IO_ReadOnly );
	    _reply_stream >> result;
	} else {
            kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
	}
    } else {
        kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
    }
    return result;
}

QString KOMailClient::createBody(IncidenceBase *incidence)
{
  QString CR = ("\n");

  QString body;

  // mailbody for Event
  if (incidence->type()=="Event") {
    Event *selectedEvent = static_cast<Event *>(incidence);
    QString recurrence[]= {i18n("no recurrence", "None"),i18n("Daily"),i18n("Weekly"),i18n("Monthly Same Day"),
                           i18n("Monthly Same Position"),i18n("Yearly"),i18n("Yearly")};

    if (!selectedEvent->organizer().isEmpty()) {
      body += i18n("Organizer: %1").arg(selectedEvent->organizer());
      body += CR;
    }
    body += i18n("Summary: %1").arg(selectedEvent->summary());
    if (!selectedEvent->location().isEmpty()) {
      body += CR;
      body += i18n("Location: %1").arg(selectedEvent->location());
    }
    if (!selectedEvent->doesFloat()) {
      body += CR;
      body += i18n("Start Date: %1").arg(selectedEvent->dtStartDateStr());
      body += CR;
      body += i18n("Start Time: %1").arg(selectedEvent->dtStartTimeStr());
      body += CR;
      if (selectedEvent->recurrence()->doesRecur()) {
        body += i18n("Recurs: %1")
                 .arg(recurrence[selectedEvent->recurrence()->frequency()]);
        body += CR;
        if (selectedEvent->recurrence()->duration() > 0 ) {
          body += i18n ("Repeats %1 times")
                   .arg(QString::number(selectedEvent->recurrence()->duration()));
          body += CR;
        } else {
          if (selectedEvent->recurrence()->duration() != -1) {
            body += i18n("End Date: %1")
                     .arg(selectedEvent->recurrence()->endDateStr());
            body += CR;
          } else {
            body += i18n("Repeats forever");
            body += CR;
          }
        }
      }
      body += i18n("End Time: %1").arg(selectedEvent->dtEndTimeStr());
      body += CR;
      QString details = selectedEvent->description();
      if (!details.isEmpty()) {
        body += i18n("Details:");
	body += CR;
	body += details;
      }
    }
  }

  // mailbody for Todo
  if (incidence->type()=="Todo") {
    Todo *selectedEvent = static_cast<Todo *>(incidence);
    if (!selectedEvent->organizer().isEmpty()) {
      body += i18n("Organizer: %1").arg(selectedEvent->organizer());
      body += CR;
    }
    body += i18n("Summary: %1").arg(selectedEvent->summary());
    if (!selectedEvent->location().isEmpty()) {
      body += CR;
      body += i18n("Location: %1").arg(selectedEvent->location());
    }
    if (!selectedEvent->hasStartDate()) {
      body += CR;
      body += i18n("Start Date: %1").arg(selectedEvent->dtStartDateStr());
      body += CR;
      if (!selectedEvent->doesFloat()) {
	body += i18n("Start Time: %1").arg(selectedEvent->dtStartTimeStr());
	body += CR;
      }
    }
    if (!selectedEvent->hasDueDate()) {
      body += CR;
      body += i18n("Due Date: %1").arg(selectedEvent->dtDueDateStr());
      body += CR;
      if (!selectedEvent->doesFloat()) {
	body += i18n("Due Time: %1").arg(selectedEvent->dtDueTimeStr());
	body += CR;
      }
    }
    body += CR;
    QString details = selectedEvent->description();
    if (!details.isEmpty()) {
      body += i18n("Details:");
      body += CR;
      body += details;
    }
  }

  // mailbody for FreeBusy
  if(incidence->type()=="FreeBusy") {
    body = i18n("This is a Free Busy Object");
  }

  // mailbody for Journal
  if(incidence->type()=="Journal") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    body = inc->summary();
    body += CR;
    body += inc->description();
  }

  return body;
}
<commit_msg>Fixed the mails sent with group scheduling. First, the recurrence type used the wrong variable, and also wrong array values for the strings (bug #62352) Second, todos used wrong conditions to check for due and start date (bug #60273)<commit_after>/*
    This file is part of KOrganizer.
    Copyright (c) 1998 Barry D Benowitz
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

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

#include <unistd.h>
#include <stdio.h>

#include <klocale.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <kurl.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kprocess.h>

#include <libkcal/event.h>
#include <libkcal/todo.h>

#include "version.h"
#include "koprefs.h"

#include "komailclient.h"

KOMailClient::KOMailClient()
{
}

KOMailClient::~KOMailClient()
{
}

bool KOMailClient::mailAttendees(IncidenceBase *incidence,const QString &attachment)
{
  Attendee::List attendees = incidence->attendees();
  if (attendees.count() == 0) return false;

  QString to;
  for(uint i=0; i<attendees.count();++i) {
    to += (*attendees.at(i))->email();
    if (i != attendees.count()-1) to += ", ";
  }

  QString from = KOPrefs::instance()->email();

  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Object";
  }

  QString body = createBody(incidence);

  bool bcc = KOPrefs::instance()->mBcc;

  return send(from,to,subject,body,bcc,attachment);
}

bool KOMailClient::mailOrganizer(IncidenceBase *incidence,const QString &attachment)
{
  QString to = incidence->organizer();

  QString from = KOPrefs::instance()->email();

  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Message";
  }

  QString body = createBody(incidence);

  bool bcc = KOPrefs::instance()->mBcc;

  return send(from,to,subject,body,bcc,attachment);
}

bool KOMailClient::mailTo(IncidenceBase *incidence,const QString &recipients,
                          const QString &attachment)
{
  QString from = KOPrefs::instance()->email();
  QString subject;
  if(incidence->type()!="FreeBusy") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    subject = inc->summary();
  } else {
    subject = "Free Busy Message";
  }
  QString body = createBody(incidence);
  bool bcc = KOPrefs::instance()->mBcc;
  kdDebug () << "KOMailClient::mailTo " << recipients << endl;
  return send(from,recipients,subject,body,bcc,attachment);
}

bool KOMailClient::send(const QString &from,const QString &to,
                        const QString &subject,const QString &body,bool bcc,
                        const QString &attachment)
{
  kdDebug(5850) << "KOMailClient::sendMail():\nFrom: " << from << "\nTo: " << to
            << "\nSubject: " << subject << "\nBody: \n" << body
            << "\nAttachment:\n" << attachment << endl;

  if (KOPrefs::instance()->mMailClient == KOPrefs::MailClientSendmail) {
    bool needHeaders = true;

    QString command = KStandardDirs::findExe(QString::fromLatin1("sendmail"),
        QString::fromLatin1("/sbin:/usr/sbin:/usr/lib"));
    if (!command.isNull()) command += QString::fromLatin1(" -oi -t");
    else {
      command = KStandardDirs::findExe(QString::fromLatin1("mail"));
      if (command.isNull()) return false; // give up

      command.append(QString::fromLatin1(" -s "));
      command.append(KProcess::quote(subject));

      if (bcc) {
        command.append(QString::fromLatin1(" -b "));
        command.append(KProcess::quote(from));
      }

      command.append(" ");
      command.append(KProcess::quote(to));

      needHeaders = false;
    }

    FILE * fd = popen(command.local8Bit(),"w");
    if (!fd)
    {
      kdError() << "Unable to open a pipe to " << command << endl;
      return false;
    }

    QString textComplete;
    if (needHeaders)
    {
      textComplete += QString::fromLatin1("From: ") + from + '\n';
      textComplete += QString::fromLatin1("To: ") + to + '\n';
      if (bcc) textComplete += QString::fromLatin1("Bcc: ") + from + '\n';
      textComplete += QString::fromLatin1("Subject: ") + subject + '\n';
      textComplete += QString::fromLatin1("X-Mailer: KOrganizer") + korgVersion + '\n';
    }
    textComplete += '\n'; // end of headers
    textComplete += body;
    textComplete += '\n';
    textComplete += attachment;

    fwrite(textComplete.local8Bit(),textComplete.length(),1,fd);

    pclose(fd);
  } else {
    if (!kapp->dcopClient()->isApplicationRegistered("kmail")) {
			if (KApplication::startServiceByDesktopName("kmail")) {
        KMessageBox::error(0,i18n("No running instance of KMail found."));
        return false;
			}
    }

    if (attachment.isEmpty()) {
      if (!kMailOpenComposer(to,"",from,subject,body,0,KURL())) return false;
    } else {
      QString meth;
      int idx = attachment.find("METHOD");
      if (idx>=0) {
        idx = attachment.find(':',idx)+1;
        meth = attachment.mid(idx,attachment.find('\n',idx)-idx);
	meth = meth.lower();
      } else {
        meth = "publish";
      }
      if (!kMailOpenComposer(to,"",from,subject,body,0,"cal.ics","7bit",
                             attachment.utf8(),"text","calendar","method",meth,
                             "attachment")) return false;
    }
  }
  return true;
}

int KOMailClient::kMailOpenComposer(const QString& arg0,const QString& arg1,
  const QString& arg2,const QString& arg3,const QString& arg4,int arg5,
  const KURL& arg6)
{
  int result = 0;

  QByteArray data, replyData;
  QCString replyType;
  QDataStream arg( data, IO_WriteOnly );
  arg << arg0;
  arg << arg1;
  arg << arg2;
  arg << arg3;
  arg << arg4;
  arg << arg5;
  arg << arg6;
  if (kapp->dcopClient()->call("kmail","KMailIface","openComposer(QString,QString,QString,QString,QString,int,KURL)", data, replyType, replyData ) ) {
    if ( replyType == "int" ) {
      QDataStream _reply_stream( replyData, IO_ReadOnly );
      _reply_stream >> result;
    } else {
      kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
    }
  } else {
    kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
  }
  return result;
}

int KOMailClient::kMailOpenComposer( const QString& arg0, const QString& arg1,
                                     const QString& arg2, const QString& arg3,
                                     const QString& arg4, int arg5, const QString& arg6,
                                     const QCString& arg7, const QCString& arg8,
                                     const QCString& arg9, const QCString& arg10,
                                     const QCString& arg11, const QString& arg12,
                                     const QCString& arg13 )
{
    int result = 0;

    QByteArray data, replyData;
    QCString replyType;
    QDataStream arg( data, IO_WriteOnly );
    arg << arg0;
    arg << arg1;
    arg << arg2;
    arg << arg3;
    arg << arg4;
    arg << arg5;
    arg << arg6;
    arg << arg7;
    arg << arg8;
    arg << arg9;
    arg << arg10;
    arg << arg11;
    arg << arg12;
    arg << arg13;
    if ( kapp->dcopClient()->call("kmail","KMailIface","openComposer(QString,QString,QString,QString,QString,int,QString,QCString,QCString,QCString,QCString,QCString,QString,QCString)", data, replyType, replyData ) ) {
	if ( replyType == "int" ) {
	    QDataStream _reply_stream( replyData, IO_ReadOnly );
	    _reply_stream >> result;
	} else {
            kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
	}
    } else {
        kdDebug(5850) << "kMailOpenComposer() call failed." << endl;
    }
    return result;
}

QString KOMailClient::createBody(IncidenceBase *incidence)
{
  QString CR = ("\n");

  QString body;

  // mailbody for Event
  if (incidence->type()=="Event") {
    Event *selectedEvent = static_cast<Event *>(incidence);
    QString recurrence[]= {i18n("no recurrence", "None"),
      i18n("Minutely"), i18n("Hourly"), i18n("Daily"),
      i18n("Weekly"), i18n("Monthly Same Day"), i18n("Monthly Same Position"),
      i18n("Yearly"), i18n("Yearly"), i18n("Yearly")};

    if (!selectedEvent->organizer().isEmpty()) {
      body += i18n("Organizer: %1").arg(selectedEvent->organizer());
      body += CR;
    }
    body += i18n("Summary: %1").arg(selectedEvent->summary());
    body += CR;
    if (!selectedEvent->location().isEmpty()) {
      body += i18n("Location: %1").arg(selectedEvent->location());
      body += CR;
    }
    body += i18n("Start Date: %1").arg(selectedEvent->dtStartDateStr());
    body += CR;
    if (!selectedEvent->doesFloat()) {
      body += i18n("Start Time: %1").arg(selectedEvent->dtStartTimeStr());
      body += CR;
    }
    if ( selectedEvent->dtStart()!=selectedEvent->dtEnd() ) {
      body += i18n("End Date: %1").arg(selectedEvent->dtEndDateStr());
      body += CR;
    }
    if (!selectedEvent->doesFloat()) {
      body += i18n("End Time: %1").arg(selectedEvent->dtEndTimeStr());
      body += CR;
    }
    if (selectedEvent->recurrence()->doesRecur()) {
      body += i18n("Recurs: %1")
               .arg(recurrence[selectedEvent->recurrence()->doesRecur()]);
      body += CR;
/* TODO: frequency
      body += i18n("Frequency: %1")
               .arg(recurrence[selectedEvent->recurrence()->frequency()]);
      body += CR;
*/
      if (selectedEvent->recurrence()->duration() > 0 ) {
        body += i18n ("Repeats %1 times")
                 .arg(QString::number(selectedEvent->recurrence()->duration()));
        body += CR;
      } else {
        if (selectedEvent->recurrence()->duration() != -1) {
//          body += i18n("Repeat until: %1")
          body += i18n("End Date: %1")
                   .arg(selectedEvent->recurrence()->endDateStr());
          body += CR;
        } else {
          body += i18n("Repeats forever");
          body += CR;
        }
      }
    }
    QString details = selectedEvent->description();
    if (!details.isEmpty()) {
      body += i18n("Details:");
      body += CR;
      body += details;
      body += CR;
    }
  }

  // mailbody for Todo
  if (incidence->type()=="Todo") {
    Todo *selectedEvent = static_cast<Todo *>(incidence);
    if (!selectedEvent->organizer().isEmpty()) {
      body += i18n("Organizer: %1").arg(selectedEvent->organizer());
      body += CR;
    }
    body += i18n("Summary: %1").arg(selectedEvent->summary());
    body += CR;
    if (!selectedEvent->location().isEmpty()) {
      body += i18n("Location: %1").arg(selectedEvent->location());
      body += CR;
    }
    if (selectedEvent->hasStartDate()) {
      body += i18n("Start Date: %1").arg(selectedEvent->dtStartDateStr());
      body += CR;
      if (!selectedEvent->doesFloat()) {
        body += i18n("Start Time: %1").arg(selectedEvent->dtStartTimeStr());
        body += CR;
      }
    }
    if (selectedEvent->hasDueDate()) {
      body += i18n("Due Date: %1").arg(selectedEvent->dtDueDateStr());
      body += CR;
      if (!selectedEvent->doesFloat()) {
        body += i18n("Due Time: %1").arg(selectedEvent->dtDueTimeStr());
        body += CR;
      }
    }
    QString details = selectedEvent->description();
    if (!details.isEmpty()) {
      body += i18n("Details:");
      body += CR;
      body += details;
      body += CR;
    }
  }

  // mailbody for FreeBusy
  if(incidence->type()=="FreeBusy") {
    body = i18n("This is a Free Busy Object");
  }

  // mailbody for Journal
  if(incidence->type()=="Journal") {
    Incidence *inc = static_cast<Incidence *>(incidence);
    body = inc->summary();
    body += CR;
    body += inc->description();
    body += CR;
  }

  return body;
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS icuupgrade (1.11.8); FILE MERGED 2006/11/14 20:40:31 khong 1.11.8.3: RESYNC: (1.12-1.13); FILE MERGED 2006/10/11 06:08:49 khong 1.11.8.2: RESYNC: (1.11-1.12); FILE MERGED 2006/08/04 12:25:56 er 1.11.8.1: #i60645# warnings guards for some ICU header files<commit_after><|endoftext|>


<commit_before>#include "ContextGDIPlus.h"

#include "utf8.h"

#include <cassert>

bool canvas::ContextGDIPlus::is_initialized = false;
ULONG_PTR canvas::ContextGDIPlus::m_gdiplusToken;

using namespace std;
using namespace canvas;

static std::wstring convert_to_wstring(const std::string & input) {
  const char * str = input.c_str();
  const char * str_i = str;
  const char * end = str + input.size();
  std::wstring output;
  while (str_i < end) {
    output += (wchar_t)utf8::next(str_i, end);
  }
  return output;
}

static void toGDIPath(const Path & path, Gdiplus::GraphicsPath & output, float display_scale) {
  output.StartFigure();
  Gdiplus::PointF current_pos;

  for (auto pc : path.getData()) {
    switch (pc.type) {
    case PathComponent::MOVE_TO:
      current_pos = Gdiplus::PointF(Gdiplus::REAL(pc.x0 * display_scale), Gdiplus::REAL(pc.y0 * display_scale));
      break;
    case PathComponent::LINE_TO:
      {
	Gdiplus::PointF point(Gdiplus::REAL(pc.x0 * display_scale), Gdiplus::REAL(pc.y0 * display_scale));
	output.AddLine(current_pos, point);
	current_pos = point;
      }
      break;
    case PathComponent::CLOSE:
      output.CloseFigure();
      break;
    case PathComponent::ARC:
      {
	double span = 0;
	if (0 && ((!pc.anticlockwise && (pc.ea - pc.sa >= 2 * M_PI)) || (pc.anticlockwise && (pc.sa - pc.ea >= 2 * M_PI)))) {
	  // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
	  // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
	  // circumference of this circle.
	  span = 2 * M_PI;
	} else {
	  if (!pc.anticlockwise && (pc.ea < pc.sa)) {
	    span += 2 * M_PI;
	  } else if (pc.anticlockwise && (pc.sa < pc.ea)) {
	    span -= 2 * M_PI;
	  }

#if 0
    // this is also due to switched coordinate system
    // we would end up with a 0 span instead of 360
    if (!(qFuzzyCompare(span + (ea - sa) + 1, 1.0) && qFuzzyCompare(qAbs(span), 360.0))) {
      // mod 360
      span += (ea - sa) - (static_cast<int>((ea - sa) / 360)) * 360;
    }
#else
	  span += pc.ea - pc.sa;
#endif
	}

#if 0
  // If the path is empty, move to where the arc will start to avoid painting a line from (0,0)
  // NOTE: QPainterPath::isEmpty() won't work here since it ignores a lone MoveToElement
  if (!m_path.elementCount())
    m_path.arcMoveTo(xs, ys, width, height, sa);
  else if (!radius) {
    m_path.lineTo(xc, yc);
    return;
  }
#endif

#if 0
  if (anticlockwise) {
    span = -M_PI / 2.0;
  } else {
    span = M_PI / 2.0;
  }
#endif
  Gdiplus::RectF rect(Gdiplus::REAL(pc.x0 * display_scale - pc.radius * display_scale), Gdiplus::REAL(pc.y0 * display_scale - pc.radius * display_scale), Gdiplus::REAL(2 * pc.radius * display_scale), Gdiplus::REAL(2 * pc.radius * display_scale));

	output.AddArc(rect, Gdiplus::REAL(pc.sa * 180.0f / M_PI), Gdiplus::REAL(span * 180.0f / M_PI));
	output.GetLastPoint(&current_pos);
      }
      break;
    }
  }
}

static Gdiplus::Color toGDIColor(const Color & input, float alpha = 1.0f) {
  int red = int(input.red * 255), green = int(input.green * 255), blue = int(input.blue * 255), alpha = int(input.alpha * alpha * 255);
  if (red < 0) red = 0;
  else if (red > 255) red = 255;
  if (green < 0) green = 0;
  else if (green > 255) green = 255;
  if (blue < 0) blue = 0;
  else if (blue > 255) blue = 255;
  if (alpha < 0) alpha = 0;
  else if (alpha > 255) alpha = 255;
#if 0
  return Gdiplus::Color::FromArgb(alpha, red, green, blue);
#else
  return Gdiplus::Color(alpha, red, green, blue);
#endif
}

GDIPlusSurface::GDIPlusSurface(const std::string & filename) : Surface(0, 0, 0, 0, false) {
  std::wstring tmp = convert_to_wstring(filename);
  bitmap = std::shared_ptr<Gdiplus::Bitmap>(Gdiplus::Bitmap::FromFile(tmp.data()));
  Surface::resize(bitmap->GetWidth(), bitmap->GetHeight(), bitmap->GetWidth(), bitmap->GetHeight(), true);
}

GDIPlusSurface::GDIPlusSurface(const unsigned char * buffer, size_t size) : Surface(0, 0, 0, 0, false) {
	assert(0);
}

void
GDIPlusSurface::renderPath(RenderMode mode, const Path & input_path, const Style & style, float lineWidth, Operator op, float display_scale, float globalAlpha) {
  initializeContext();

  switch (op) {
  case SOURCE_OVER:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
    break;
  case COPY:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
    break;
  }

  Gdiplus::GraphicsPath path;
  toGDIPath(input_path, path, display_scale);

  switch (mode) {
  case STROKE:
    {
      Gdiplus::Pen pen(toGDIColor(style.color, globalAlpha), lineWidth);
      g->DrawPath(&pen, &path);
    }
    break;
  case FILL:
    if (style.getType() == Style::LINEAR_GRADIENT) {
      const std::map<float, Color> & colors = style.getColors();
      if (!colors.empty()) {
	std::map<float, Color>::const_iterator it0 = colors.begin(), it1 = colors.end();
	it1--;
	const Color & c0 = it0->second, c1 = it1->second;
	Gdiplus::LinearGradientBrush brush(Gdiplus::PointF(Gdiplus::REAL(style.x0), Gdiplus::REAL(style.y0)),
					   Gdiplus::PointF(Gdiplus::REAL(style.x1), Gdiplus::REAL(style.y1)),
					   toGDIColor(c0, globalAlpha),
					   toGDIColor(c1, globalAlpha));
	g->FillPath(&brush, &path);
      }
    } else {
      Gdiplus::SolidBrush brush(toGDIColor(style.color, globalAlpha));
      g->FillPath(&brush, &path);
    }
  }
}

void
GDIPlusSurface::clip(const Path & input_path, float display_scale) {
  initializeContext();

  Gdiplus::GraphicsPath path;
  toGDIPath(input_path, path, display_scale);

  Gdiplus::Region region(&path);
  g->SetClip(&region);
}

void
GDIPlusSurface::drawNativeSurface(GDIPlusSurface & img, double x, double y, double w, double h, double alpha, bool imageSmoothingEnabled) {
  initializeContext();

  g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);

  if (imageSmoothingEnabled) {
    // g->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBicubic );
    g->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear );
  } else {
    g->SetInterpolationMode( Gdiplus::InterpolationModeNearestNeighbor );
  }
  if (alpha < 1.0f && 0) {
#if 0
    ImageAttributes  imageAttributes;
    ColorMatrix colorMatrix = {
      1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
      0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
      0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
      0.0f, 0.0f, 0.0f, alpha, 0.0f,
      0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    imageAttributes.SetColorMatrix( &colorMatrix,
				    ColorMatrixFlagsDefault,
				    ColorAdjustTypeBitmap);
    graphics.DrawImage( &(*(img.bitmap)),
			Gdiplus::Rect(x, y, w, h),  // destination rectangle
			0, 0,        // upper-left corner of source rectangle
			getWidth(),       // width of source rectangle
			getHeight(),      // height of source rectangle
			Gdiplus::UnitPixel,
			&imageAttributes);
#endif
  } else if (img.getActualWidth() == (unsigned int)w && img.getActualHeight() == (unsigned int)h && 0) { // this scales image weirdly
    g->DrawImage(&(*(img.bitmap)), Gdiplus::REAL(x), Gdiplus::REAL(y));
  } else {
    g->DrawImage(&(*(img.bitmap)), Gdiplus::REAL(x), Gdiplus::REAL(y), Gdiplus::REAL(w), Gdiplus::REAL(h));
  }
}

void
GDIPlusSurface::drawImage(Surface & _img, double x, double y, double w, double h, float alpha, bool imageSmoothingEnabled) {
  GDIPlusSurface * img = dynamic_cast<GDIPlusSurface*>(&_img);
  if (img) {
    drawNativeSurface(*img, x, y, w, h, alpha, imageSmoothingEnabled);
  } else {
    auto img = _img.createImage();
    GDIPlusSurface cs(*img);
    drawNativeSurface(cs, x, y, w, h, alpha, imageSmoothingEnabled);
  }
}

void
GDIPlusSurface::renderText(RenderMode mode, const Font & font, const Style & style, TextBaseline textBaseline, TextAlign textAlign, const std::string & text, double x, double y, float lineWidth, Operator op, float display_scale) {
  initializeContext();

  x = round(x);
  y = round(y);

  switch (op) {
  case SOURCE_OVER:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
    break;
  case COPY:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
    break;
  }

  if (font.cleartype) {
	g->SetTextRenderingHint(Gdiplus::TextRenderingHintClearTypeGridFit);
  } else if (font.antialiasing && font.hinting && 0) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAliasGridFit );
  } else if (font.antialiasing) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
  } else if (font.hinting) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintSingleBitPerPixelGridFit );
  } else {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintSingleBitPerPixel );
  }

  std::wstring text2 = convert_to_wstring(text);
  int style_bits = 0;
  if (font.weight == Font::BOLD || font.weight == Font::BOLDER) {
    style_bits |= Gdiplus::FontStyleBold;
  }
  if (font.slant == Font::ITALIC) {
    style_bits |= Gdiplus::FontStyleItalic;
  }
  Gdiplus::Font gdifont(&Gdiplus::FontFamily(L"Arial"), font.size * display_scale, style_bits, Gdiplus::UnitPixel);

  Gdiplus::RectF rect(Gdiplus::REAL(x * display_scale), Gdiplus::REAL(y * display_scale), 0.0f, 0.0f);
  Gdiplus::StringFormat f;

  switch (textBaseline.getType()) {
  case TextBaseline::TOP: break;
  case TextBaseline::HANGING: break;
  case TextBaseline::MIDDLE: f.SetLineAlignment(Gdiplus::StringAlignmentCenter); break;
  case TextBaseline::BOTTOM: f.SetLineAlignment(Gdiplus::StringAlignmentFar);
  }

  switch (textAlign.getType()) {
  case TextAlign::CENTER: f.SetAlignment(Gdiplus::StringAlignmentCenter); break;
  case TextAlign::END: case TextAlign::RIGHT: f.SetAlignment(Gdiplus::StringAlignmentFar); break;
  case TextAlign::START: case TextAlign::LEFT: f.SetAlignment(Gdiplus::StringAlignmentNear); break;
  }

  f.SetFormatFlags(Gdiplus::StringFormatFlagsBypassGDI);

  switch (mode) {
  case STROKE:
    // implement
    break;
  case FILL:
    {
      Gdiplus::SolidBrush brush(toGDIColor(style.color));
      g->DrawString(text2.data(), text2.size(), &gdifont, rect, &f, &brush);
    }
    break;
  }
}

TextMetrics
GDIPlusSurface::measureText(const Font & font, const std::string & text, float display_scale) {
  initializeContext();
  std::wstring text2 = convert_to_wstring(text);
  int style = 0;
  if (font.weight == Font::BOLD || font.weight == Font::BOLDER) {
    style |= Gdiplus::FontStyleBold;
  }
  if (font.slant == Font::ITALIC) {
    style |= Gdiplus::FontStyleItalic;
  }
  Gdiplus::Font gdi_font(&Gdiplus::FontFamily(L"Arial"), font.size * display_scale, style, Gdiplus::UnitPixel);
  Gdiplus::RectF layoutRect(0, 0, 512, 512), boundingBox;
  g->MeasureString(text2.data(), text2.size(), &gdi_font, layoutRect, &boundingBox);
  Gdiplus::SizeF size;
  boundingBox.GetSize(&size);

  return TextMetrics(size.Width / display_scale);
}
<commit_msg>fix globalAlpha parameter<commit_after>#include "ContextGDIPlus.h"

#include "utf8.h"

#include <cassert>

bool canvas::ContextGDIPlus::is_initialized = false;
ULONG_PTR canvas::ContextGDIPlus::m_gdiplusToken;

using namespace std;
using namespace canvas;

static std::wstring convert_to_wstring(const std::string & input) {
  const char * str = input.c_str();
  const char * str_i = str;
  const char * end = str + input.size();
  std::wstring output;
  while (str_i < end) {
    output += (wchar_t)utf8::next(str_i, end);
  }
  return output;
}

static void toGDIPath(const Path & path, Gdiplus::GraphicsPath & output, float display_scale) {
  output.StartFigure();
  Gdiplus::PointF current_pos;

  for (auto pc : path.getData()) {
    switch (pc.type) {
    case PathComponent::MOVE_TO:
      current_pos = Gdiplus::PointF(Gdiplus::REAL(pc.x0 * display_scale), Gdiplus::REAL(pc.y0 * display_scale));
      break;
    case PathComponent::LINE_TO:
      {
	Gdiplus::PointF point(Gdiplus::REAL(pc.x0 * display_scale), Gdiplus::REAL(pc.y0 * display_scale));
	output.AddLine(current_pos, point);
	current_pos = point;
      }
      break;
    case PathComponent::CLOSE:
      output.CloseFigure();
      break;
    case PathComponent::ARC:
      {
	double span = 0;
	if (0 && ((!pc.anticlockwise && (pc.ea - pc.sa >= 2 * M_PI)) || (pc.anticlockwise && (pc.sa - pc.ea >= 2 * M_PI)))) {
	  // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
	  // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
	  // circumference of this circle.
	  span = 2 * M_PI;
	} else {
	  if (!pc.anticlockwise && (pc.ea < pc.sa)) {
	    span += 2 * M_PI;
	  } else if (pc.anticlockwise && (pc.sa < pc.ea)) {
	    span -= 2 * M_PI;
	  }

#if 0
    // this is also due to switched coordinate system
    // we would end up with a 0 span instead of 360
    if (!(qFuzzyCompare(span + (ea - sa) + 1, 1.0) && qFuzzyCompare(qAbs(span), 360.0))) {
      // mod 360
      span += (ea - sa) - (static_cast<int>((ea - sa) / 360)) * 360;
    }
#else
	  span += pc.ea - pc.sa;
#endif
	}

#if 0
  // If the path is empty, move to where the arc will start to avoid painting a line from (0,0)
  // NOTE: QPainterPath::isEmpty() won't work here since it ignores a lone MoveToElement
  if (!m_path.elementCount())
    m_path.arcMoveTo(xs, ys, width, height, sa);
  else if (!radius) {
    m_path.lineTo(xc, yc);
    return;
  }
#endif

#if 0
  if (anticlockwise) {
    span = -M_PI / 2.0;
  } else {
    span = M_PI / 2.0;
  }
#endif
  Gdiplus::RectF rect(Gdiplus::REAL(pc.x0 * display_scale - pc.radius * display_scale), Gdiplus::REAL(pc.y0 * display_scale - pc.radius * display_scale), Gdiplus::REAL(2 * pc.radius * display_scale), Gdiplus::REAL(2 * pc.radius * display_scale));

	output.AddArc(rect, Gdiplus::REAL(pc.sa * 180.0f / M_PI), Gdiplus::REAL(span * 180.0f / M_PI));
	output.GetLastPoint(&current_pos);
      }
      break;
    }
  }
}

static Gdiplus::Color toGDIColor(const Color & input, float globalAlpha = 1.0f) {
  int red = int(input.red * 255), green = int(input.green * 255), blue = int(input.blue * 255), alpha = int(input.alpha * globalAlpha * 255);
  if (red < 0) red = 0;
  else if (red > 255) red = 255;
  if (green < 0) green = 0;
  else if (green > 255) green = 255;
  if (blue < 0) blue = 0;
  else if (blue > 255) blue = 255;
  if (alpha < 0) alpha = 0;
  else if (alpha > 255) alpha = 255;
#if 0
  return Gdiplus::Color::FromArgb(alpha, red, green, blue);
#else
  return Gdiplus::Color(alpha, red, green, blue);
#endif
}

GDIPlusSurface::GDIPlusSurface(const std::string & filename) : Surface(0, 0, 0, 0, false) {
  std::wstring tmp = convert_to_wstring(filename);
  bitmap = std::shared_ptr<Gdiplus::Bitmap>(Gdiplus::Bitmap::FromFile(tmp.data()));
  Surface::resize(bitmap->GetWidth(), bitmap->GetHeight(), bitmap->GetWidth(), bitmap->GetHeight(), true);
}

GDIPlusSurface::GDIPlusSurface(const unsigned char * buffer, size_t size) : Surface(0, 0, 0, 0, false) {
	assert(0);
}

void
GDIPlusSurface::renderPath(RenderMode mode, const Path & input_path, const Style & style, float lineWidth, Operator op, float display_scale, float globalAlpha) {
  initializeContext();

  switch (op) {
  case SOURCE_OVER:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
    break;
  case COPY:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
    break;
  }

  Gdiplus::GraphicsPath path;
  toGDIPath(input_path, path, display_scale);

  switch (mode) {
  case STROKE:
    {
      Gdiplus::Pen pen(toGDIColor(style.color, globalAlpha), lineWidth);
      g->DrawPath(&pen, &path);
    }
    break;
  case FILL:
    if (style.getType() == Style::LINEAR_GRADIENT) {
      const std::map<float, Color> & colors = style.getColors();
      if (!colors.empty()) {
	std::map<float, Color>::const_iterator it0 = colors.begin(), it1 = colors.end();
	it1--;
	const Color & c0 = it0->second, c1 = it1->second;
	Gdiplus::LinearGradientBrush brush(Gdiplus::PointF(Gdiplus::REAL(style.x0), Gdiplus::REAL(style.y0)),
					   Gdiplus::PointF(Gdiplus::REAL(style.x1), Gdiplus::REAL(style.y1)),
					   toGDIColor(c0, globalAlpha),
					   toGDIColor(c1, globalAlpha));
	g->FillPath(&brush, &path);
      }
    } else {
      Gdiplus::SolidBrush brush(toGDIColor(style.color, globalAlpha));
      g->FillPath(&brush, &path);
    }
  }
}

void
GDIPlusSurface::clip(const Path & input_path, float display_scale) {
  initializeContext();

  Gdiplus::GraphicsPath path;
  toGDIPath(input_path, path, display_scale);

  Gdiplus::Region region(&path);
  g->SetClip(&region);
}

void
GDIPlusSurface::drawNativeSurface(GDIPlusSurface & img, double x, double y, double w, double h, double alpha, bool imageSmoothingEnabled) {
  initializeContext();

  g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);

  if (imageSmoothingEnabled) {
    // g->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBicubic );
    g->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear );
  } else {
    g->SetInterpolationMode( Gdiplus::InterpolationModeNearestNeighbor );
  }
  if (alpha < 1.0f && 0) {
#if 0
    ImageAttributes  imageAttributes;
    ColorMatrix colorMatrix = {
      1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
      0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
      0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
      0.0f, 0.0f, 0.0f, alpha, 0.0f,
      0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    imageAttributes.SetColorMatrix( &colorMatrix,
				    ColorMatrixFlagsDefault,
				    ColorAdjustTypeBitmap);
    graphics.DrawImage( &(*(img.bitmap)),
			Gdiplus::Rect(x, y, w, h),  // destination rectangle
			0, 0,        // upper-left corner of source rectangle
			getWidth(),       // width of source rectangle
			getHeight(),      // height of source rectangle
			Gdiplus::UnitPixel,
			&imageAttributes);
#endif
  } else if (img.getActualWidth() == (unsigned int)w && img.getActualHeight() == (unsigned int)h && 0) { // this scales image weirdly
    g->DrawImage(&(*(img.bitmap)), Gdiplus::REAL(x), Gdiplus::REAL(y));
  } else {
    g->DrawImage(&(*(img.bitmap)), Gdiplus::REAL(x), Gdiplus::REAL(y), Gdiplus::REAL(w), Gdiplus::REAL(h));
  }
}

void
GDIPlusSurface::drawImage(Surface & _img, double x, double y, double w, double h, float alpha, bool imageSmoothingEnabled) {
  GDIPlusSurface * img = dynamic_cast<GDIPlusSurface*>(&_img);
  if (img) {
    drawNativeSurface(*img, x, y, w, h, alpha, imageSmoothingEnabled);
  } else {
    auto img = _img.createImage();
    GDIPlusSurface cs(*img);
    drawNativeSurface(cs, x, y, w, h, alpha, imageSmoothingEnabled);
  }
}

void
GDIPlusSurface::renderText(RenderMode mode, const Font & font, const Style & style, TextBaseline textBaseline, TextAlign textAlign, const std::string & text, double x, double y, float lineWidth, Operator op, float display_scale, float globalAlpha) {
  initializeContext();

  x = round(x);
  y = round(y);

  switch (op) {
  case SOURCE_OVER:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
    break;
  case COPY:
    g->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
    break;
  }

  if (font.cleartype) {
    g->SetTextRenderingHint(Gdiplus::TextRenderingHintClearTypeGridFit);
  } else if (font.antialiasing && font.hinting && 0) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAliasGridFit );
  } else if (font.antialiasing) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
  } else if (font.hinting) {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintSingleBitPerPixelGridFit );
  } else {
    g->SetTextRenderingHint( Gdiplus::TextRenderingHintSingleBitPerPixel );
  }

  std::wstring text2 = convert_to_wstring(text);
  int style_bits = 0;
  if (font.weight == Font::BOLD || font.weight == Font::BOLDER) {
    style_bits |= Gdiplus::FontStyleBold;
  }
  if (font.slant == Font::ITALIC) {
    style_bits |= Gdiplus::FontStyleItalic;
  }
  Gdiplus::Font gdifont(&Gdiplus::FontFamily(L"Arial"), font.size * display_scale, style_bits, Gdiplus::UnitPixel);

  Gdiplus::RectF rect(Gdiplus::REAL(x * display_scale), Gdiplus::REAL(y * display_scale), 0.0f, 0.0f);
  Gdiplus::StringFormat f;

  switch (textBaseline.getType()) {
  case TextBaseline::TOP: break;
  case TextBaseline::HANGING: break;
  case TextBaseline::MIDDLE: f.SetLineAlignment(Gdiplus::StringAlignmentCenter); break;
  case TextBaseline::BOTTOM: f.SetLineAlignment(Gdiplus::StringAlignmentFar);
  }

  switch (textAlign.getType()) {
  case TextAlign::CENTER: f.SetAlignment(Gdiplus::StringAlignmentCenter); break;
  case TextAlign::END: case TextAlign::RIGHT: f.SetAlignment(Gdiplus::StringAlignmentFar); break;
  case TextAlign::START: case TextAlign::LEFT: f.SetAlignment(Gdiplus::StringAlignmentNear); break;
  }

  f.SetFormatFlags(Gdiplus::StringFormatFlagsBypassGDI);

  switch (mode) {
  case STROKE:
    // implement
    break;
  case FILL:
    {
      Gdiplus::SolidBrush brush(toGDIColor(style.color, globalAlpha));
      g->DrawString(text2.data(), text2.size(), &gdifont, rect, &f, &brush);
    }
    break;
  }
}

TextMetrics
GDIPlusSurface::measureText(const Font & font, const std::string & text, float display_scale) {
  initializeContext();
  std::wstring text2 = convert_to_wstring(text);
  int style = 0;
  if (font.weight == Font::BOLD || font.weight == Font::BOLDER) {
    style |= Gdiplus::FontStyleBold;
  }
  if (font.slant == Font::ITALIC) {
    style |= Gdiplus::FontStyleItalic;
  }
  Gdiplus::Font gdi_font(&Gdiplus::FontFamily(L"Arial"), font.size * display_scale, style, Gdiplus::UnitPixel);
  Gdiplus::RectF layoutRect(0, 0, 512, 512), boundingBox;
  g->MeasureString(text2.data(), text2.size(), &gdi_font, layoutRect, &boundingBox);
  Gdiplus::SizeF size;
  boundingBox.GetSize(&size);

  return TextMetrics(size.Width / display_scale);
}
<|endoftext|>


<commit_before>/*
** Copyright 2011 Merethis
**
** This file is part of Centreon Clib.
**
** Centreon Clib 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.
**
** Centreon Clib 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 Centreon Clib. If not, see
** <http://www.gnu.org/licenses/>.
*/

#ifndef CC_CONCURRENCY_MUTEX_WIN32_HH
#  define CC_CONCURRENCY_MUTEX_WIN32_HH

#  include <windows.h>
#  include "com/centreon/namespace.hh"

CC_BEGIN()

namespace            concurrency {
  /**
   *  @class mutex mutex_win32.hh "com/centreon/concurrency/mutex.hh"
   *  @brief Implements a mutex.
   *
   *  Win32-base implementation of a mutex (intra-process
   *  synchronisation). On Windows the mutex class is a critical
   *  section and should not be confused with a Win32 mutex which is
   *  used for inter-process synchronisation.
   */
  class              mutex {
  public:
                     mutex();
                     ~mutex() throw ();
    void             lock();
    bool             trylock();
    void             unlock();

  private:
                     mutex(mutex const& right);
    mutex&           operator=(mutex const& right);
    mutex&           _internal_copy(mutex const& right);

    CRITICAL_SECTION _csection;
  };
}

CC_END()

#endif // !CC_CONCURRENCY_MUTEX_WIN32_HH
<commit_msg>Fix Win32 mutex compilation error.<commit_after>/*
** Copyright 2011 Merethis
**
** This file is part of Centreon Clib.
**
** Centreon Clib 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.
**
** Centreon Clib 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 Centreon Clib. If not, see
** <http://www.gnu.org/licenses/>.
*/

#ifndef CC_CONCURRENCY_MUTEX_WIN32_HH
#  define CC_CONCURRENCY_MUTEX_WIN32_HH

#  include <windows.h>
#  include "com/centreon/namespace.hh"

CC_BEGIN()

namespace            concurrency {
  /**
   *  @class mutex mutex_win32.hh "com/centreon/concurrency/mutex.hh"
   *  @brief Implements a mutex.
   *
   *  Win32-base implementation of a mutex (intra-process
   *  synchronisation). On Windows the mutex class is a critical
   *  section and should not be confused with a Win32 mutex which is
   *  used for inter-process synchronisation.
   */
  class              mutex {
  public:
                     mutex();
                     ~mutex() throw ();
    void             lock();
    bool             trylock();
    void             unlock();

  private:
                     mutex(mutex const& right);
    mutex&           operator=(mutex const& right);
    void             _internal_copy(mutex const& right);

    CRITICAL_SECTION _csection;
  };
}

CC_END()

#endif // !CC_CONCURRENCY_MUTEX_WIN32_HH
<|endoftext|>


<commit_before>
#include "Triton.h"
#include "analysis/formatString.h"

void formatStringBugAnalysis(unsigned long rdi)
{
  list<UINT64>::iterator i;
  std::string content = std::string((const char *)rdi);
  std::stringstream str;

  if (taintEngine->isMemoryTainted(rdi)){
    if (content.find("%s") == string::npos){
      str << "[call::printf] RDI content is tainted: " << content;
      displayBug(str.str());
      str.str("[call::printf] This printf is probably vulnerable");
      displayBug(str.str());
    }
  }
}

<commit_msg>Add comments<commit_after>
#include "Triton.h"
#include "analysis/formatString.h"

void formatStringBugAnalysis(unsigned long rdi)
{
  list<UINT64>::iterator i;
  std::string content = std::string((const char *)rdi);
  std::stringstream str;

  /* In 64-bit, RDI holds the first argument.
   * If this argument is tainted, it's probably vulnerable */
  if (taintEngine->isMemoryTainted(rdi)){
    str << "[call::printf] RDI content is tainted: " << content;
    displayBug(str.str());
    str.str("[call::printf] This printf is probably vulnerable");
    displayBug(str.str());
  }
}

<|endoftext|>