<commit_before>// $Id$
//
//  Copyright (C) 2007-2008 Greg Landrum
//
//   @@ All Rights Reserved  @@
//
#include <RDBoost/Wrap.h>
#include <GraphMol/Atom.h>
#include <GraphMol/GraphMol.h>

#include <GraphMol/Descriptors/MolDescriptors.h>
#include <GraphMol/Fingerprints/AtomPairs.h>
#include <GraphMol/Fingerprints/MorganFingerprints.h>

#include <vector>

namespace python = boost::python;

namespace {
  std::vector<unsigned int> atomPairTypes(RDKit::AtomPairs::atomNumberTypes,
					  RDKit::AtomPairs::atomNumberTypes+sizeof(RDKit::AtomPairs::atomNumberTypes)/sizeof(unsigned int));
  python::tuple computeASAContribs(const RDKit::ROMol &mol,bool includeHs=true,
				   bool force=false){
    std::vector<double> contribs(mol.getNumAtoms());
    double hContrib=0.0;
    RDKit::Descriptors::getLabuteAtomContribs(mol,contribs,hContrib,includeHs,force);
    python::tuple pycontribs(contribs);
    return python::make_tuple(contribs,hContrib);
  }
  python::list computeCrippenContribs(const RDKit::ROMol &mol,
				       bool force=false){
    std::vector<double> logpContribs(mol.getNumAtoms());
    std::vector<double> mrContribs(mol.getNumAtoms());

    RDKit::Descriptors::getCrippenAtomContribs(mol,logpContribs,mrContribs,force);
    python::list pycontribs;
    for(unsigned int i=0;i<mol.getNumAtoms();++i){
      pycontribs.append(python::make_tuple(logpContribs[i],mrContribs[i]));
    }
    return pycontribs;
  }
  python::tuple calcCrippenDescriptors(const RDKit::ROMol &mol,bool includeHs=true,
				       bool force=false){
    double logp,mr;
    RDKit::Descriptors::CalcCrippenDescriptors(mol,logp,mr,includeHs,force);
    return python::make_tuple(logp,mr);
  }

  RDKit::SparseIntVect<boost::int32_t> *GetAtomPairFingerprint(const RDKit::ROMol &mol,
                                                               unsigned int minLength,
                                                               unsigned int maxLength,
                                                               python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }

    RDKit::SparseIntVect<boost::int32_t> *res;
    res = RDKit::AtomPairs::getAtomPairFingerprint(mol,minLength,maxLength,
                                                                vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::int64_t> *GetTopologicalTorsionFingerprint(const RDKit::ROMol &mol,
                                                                         unsigned int targetSize,
                                                                         python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }

    if(targetSize*RDKit::AtomPairs::codeSize>64){
      std::ostringstream errout;
      errout << "Maximum supported topological torsion path length is " << 64/RDKit::AtomPairs::codeSize<<std::endl;
      throw_value_error(errout.str());
    }

    RDKit::SparseIntVect<boost::int64_t> *res;
    res = RDKit::AtomPairs::getTopologicalTorsionFingerprint(mol,targetSize,vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::int64_t> *GetHashedTopologicalTorsionFingerprint(const RDKit::ROMol &mol,
                                                                               unsigned int nBits,
                                                                         unsigned int targetSize,
                                                                         python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }
    RDKit::SparseIntVect<boost::int64_t> *res;
    res = RDKit::AtomPairs::getHashedTopologicalTorsionFingerprint(mol,nBits,targetSize,vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::uint32_t> *GetMorganFingerprint(const RDKit::ROMol &mol,
                                                              int radius,
                                                              python::object invariants,
                                                              python::object fromAtoms){
    std::vector<boost::uint32_t> *invars=0;
    if(invariants){
      unsigned int nInvar=python::extract<unsigned int>(invariants.attr("__len__")());
      if(nInvar){
        if(nInvar!=mol.getNumAtoms()){
          throw_value_error("length of invariant vector != number of atoms");
        }
        invars = new std::vector<boost::uint32_t>(mol.getNumAtoms());
        for(unsigned int i=0;i<mol.getNumAtoms();++i){
          (*invars)[i] = python::extract<boost::uint32_t>(invariants[i]);
        }
      }
    }
    std::vector<boost::uint32_t> *froms=0;
    if(fromAtoms){
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      if(nFrom){
        froms = new std::vector<boost::uint32_t>();
        for(unsigned int i=0;i<nFrom;++i){
          froms->push_back(python::extract<boost::uint32_t>(fromAtoms[i]));
        }
      }
    }
    RDKit::SparseIntVect<boost::uint32_t> *res;
    res = RDKit::MorganFingerprints::getFingerprint(mol,
                                                    static_cast<unsigned int>(radius),
                                                    invars,froms);
    if(invars) delete invars;
    if(froms) delete froms;
    return res;
  }

}
python::list GetConnectivityInvariants(const RDKit::ROMol &mol,bool includeRingMembership){
  std::vector<boost::uint32_t> invars(mol.getNumAtoms());
  RDKit::MorganFingerprints::getConnectivityInvariants(mol,invars,includeRingMembership);
  python::list res;
  for(std::vector<boost::uint32_t>::const_iterator iv=invars.begin();iv!=invars.end();++iv){
    res.append(python::long_(*iv));
  }
  return res;
}

BOOST_PYTHON_MODULE(rdMolDescriptors) {
  python::scope().attr("__doc__") =
    "Module containing functions to compute molecular descriptors"
    ;

  python::register_exception_translator<IndexErrorException>(&translate_index_error);
  python::register_exception_translator<ValueErrorException>(&translate_value_error);

  std::string docString = "";

  python::class_<python::object>("AtomPairsParameters")
    .setattr("version",
		  RDKit::AtomPairs::atomPairsVersion)
    .setattr("numTypeBits",
		  RDKit::AtomPairs::numTypeBits)
    .setattr("numPiBits",
		  RDKit::AtomPairs::numPiBits)
    .setattr("numBranchBits",
		  RDKit::AtomPairs::numBranchBits)
    .setattr("codeSize",
		  RDKit::AtomPairs::codeSize)
    .setattr("atomTypes",
		  atomPairTypes)
    .setattr("numPathBits",
		  RDKit::AtomPairs::numPathBits)
    .setattr("numAtomPairFingerprintBits",
		  RDKit::AtomPairs::numAtomPairFingerprintBits)
    ;
  docString="Returns the atom code (hash) for an atom";
  python::def("GetAtomPairAtomCode", RDKit::AtomPairs::getAtomCode,
              (python::arg("atom"), python::arg("branchSubtract")=0),
              docString.c_str());
  docString="Returns the atom-pair fingerprint for a molecule as an IntSparseIntVect";
  python::def("GetAtomPairFingerprint", GetAtomPairFingerprint,
              (python::arg("mol"),
               python::arg("minLength")=1,
               python::arg("maxLength")=RDKit::AtomPairs::maxPathLen-1,
               python::arg("fromAtoms")=python::list()),
              docString.c_str(),
              python::return_value_policy<python::manage_new_object>());

  python::def("GetHashedAtomPairFingerprint",
	      (RDKit::SparseIntVect<boost::int32_t> *(*)(const RDKit::ROMol&,unsigned int,unsigned int,unsigned int))RDKit::AtomPairs::getHashedAtomPairFingerprint,
	      (python::arg("mol"),
               python::arg("nBits")=2048,
               python::arg("minLength")=1,
               python::arg("maxLength")=RDKit::AtomPairs::maxPathLen-1),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());
  docString="Returns the topological-torsion fingerprint for a molecule as a LongIntSparseIntVect";
  python::def("GetTopologicalTorsionFingerprint",
	      GetTopologicalTorsionFingerprint,
	      (python::arg("mol"),python::arg("targetSize")=4,
               python::arg("fromAtoms")=0),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());
  python::def("GetHashedTopologicalTorsionFingerprint",
	      GetHashedTopologicalTorsionFingerprint,
	      (python::arg("mol"),
               python::arg("nBits")=2048,
               python::arg("targetSize")=4,
               python::arg("fromAtoms")=0),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());

  docString="Returns a Morgan fingerprint for a molecule";
  python::def("GetMorganFingerprint", GetMorganFingerprint,
              (python::arg("mol"),python::arg("radius"),
               python::arg("invariants")=python::list(),
               python::arg("fromAtoms")=python::list()),
              docString.c_str(),
              python::return_value_policy<python::manage_new_object>());
  python::scope().attr("_MorganFingerprint_version")=
    RDKit::MorganFingerprints::morganFingerprintVersion;
  docString="Returns connectivity invariants (ECFP-like) for a molecule.";
  python::def("GetConnectivityInvariants", GetConnectivityInvariants,
              (python::arg("mol"),python::arg("includeRingMembership")=false),
              docString.c_str());
  python::scope().attr("_ConnectivityInvariants_version")=
    RDKit::MorganFingerprints::morganFingerprintVersion;

  docString="returns (as a list of 2-tuples) the contributions of each atom to\n"
    "the Wildman-Cripppen logp and mr value";
  python::def("_CalcCrippenContribs",
	      computeCrippenContribs,
	      (python::arg("mol"),
	       python::arg("force")=false),
              docString.c_str());
  docString="returns a 2-tuple with the Wildman-Crippen logp,mr values";
  python::def("CalcCrippenDescriptors",
	      calcCrippenDescriptors,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());
  python::scope().attr("_CalcCrippenDescriptors_version")=
    RDKit::Descriptors::crippenVersion;

  docString="returns the Labute ASA value for a molecule";
  python::def("CalcLabuteASA",
	      RDKit::Descriptors::calcLabuteASA,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());
  python::scope().attr("_CalcLabuteASA_version")=RDKit::Descriptors::labuteASAVersion;

  docString="returns a list of atomic contributions to the Labute ASA";
  python::def("_CalcLabuteASAContribs",
	      computeASAContribs,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());

  docString="returns the molecule's molecular weight";
  python::def("_CalcMolWt",
	      RDKit::Descriptors::CalcAMW,
	      (python::arg("mol"),python::arg("onlyHeavy")=false),
              docString.c_str());
  python::scope().attr("_CalcMolWt_version")="1.0.0";

}
<commit_msg>add a bit more morgan functionality<commit_after>// $Id$
//
//  Copyright (C) 2007-2010 Greg Landrum
//
//   @@ All Rights Reserved  @@
//
#include <RDBoost/Wrap.h>
#include <GraphMol/Atom.h>
#include <GraphMol/GraphMol.h>

#include <GraphMol/Descriptors/MolDescriptors.h>
#include <GraphMol/Fingerprints/AtomPairs.h>
#include <GraphMol/Fingerprints/MorganFingerprints.h>

#include <vector>

namespace python = boost::python;

namespace {
  std::vector<unsigned int> atomPairTypes(RDKit::AtomPairs::atomNumberTypes,
					  RDKit::AtomPairs::atomNumberTypes+sizeof(RDKit::AtomPairs::atomNumberTypes)/sizeof(unsigned int));
  python::tuple computeASAContribs(const RDKit::ROMol &mol,bool includeHs=true,
				   bool force=false){
    std::vector<double> contribs(mol.getNumAtoms());
    double hContrib=0.0;
    RDKit::Descriptors::getLabuteAtomContribs(mol,contribs,hContrib,includeHs,force);
    python::tuple pycontribs(contribs);
    return python::make_tuple(contribs,hContrib);
  }
  python::list computeCrippenContribs(const RDKit::ROMol &mol,
				       bool force=false){
    std::vector<double> logpContribs(mol.getNumAtoms());
    std::vector<double> mrContribs(mol.getNumAtoms());

    RDKit::Descriptors::getCrippenAtomContribs(mol,logpContribs,mrContribs,force);
    python::list pycontribs;
    for(unsigned int i=0;i<mol.getNumAtoms();++i){
      pycontribs.append(python::make_tuple(logpContribs[i],mrContribs[i]));
    }
    return pycontribs;
  }
  python::tuple calcCrippenDescriptors(const RDKit::ROMol &mol,bool includeHs=true,
				       bool force=false){
    double logp,mr;
    RDKit::Descriptors::CalcCrippenDescriptors(mol,logp,mr,includeHs,force);
    return python::make_tuple(logp,mr);
  }

  RDKit::SparseIntVect<boost::int32_t> *GetAtomPairFingerprint(const RDKit::ROMol &mol,
                                                               unsigned int minLength,
                                                               unsigned int maxLength,
                                                               python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }

    RDKit::SparseIntVect<boost::int32_t> *res;
    res = RDKit::AtomPairs::getAtomPairFingerprint(mol,minLength,maxLength,
                                                                vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::int64_t> *GetTopologicalTorsionFingerprint(const RDKit::ROMol &mol,
                                                                         unsigned int targetSize,
                                                                         python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }

    if(targetSize*RDKit::AtomPairs::codeSize>64){
      std::ostringstream errout;
      errout << "Maximum supported topological torsion path length is " << 64/RDKit::AtomPairs::codeSize<<std::endl;
      throw_value_error(errout.str());
    }

    RDKit::SparseIntVect<boost::int64_t> *res;
    res = RDKit::AtomPairs::getTopologicalTorsionFingerprint(mol,targetSize,vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::int64_t> *GetHashedTopologicalTorsionFingerprint(const RDKit::ROMol &mol,
                                                                               unsigned int nBits,
                                                                         unsigned int targetSize,
                                                                         python::object fromAtoms){
    std::vector<boost::uint32_t> *vect=0;
    if(fromAtoms){
      vect = new std::vector<boost::uint32_t>;
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      for(unsigned int i=0;i<nFrom;++i){
        boost::uint32_t v=python::extract<boost::uint32_t>(fromAtoms[i]);
        if(v>=mol.getNumAtoms()){
          throw_value_error("atom index specified that is larger than the number of atoms");
        }
        vect->push_back(v);
      }
    }
    RDKit::SparseIntVect<boost::int64_t> *res;
    res = RDKit::AtomPairs::getHashedTopologicalTorsionFingerprint(mol,nBits,targetSize,vect);
    if(vect) delete vect;
    return res;
  }

  RDKit::SparseIntVect<boost::uint32_t> *GetMorganFingerprint(const RDKit::ROMol &mol,
                                                              int radius,
                                                              python::object invariants,
                                                              python::object fromAtoms){
    std::vector<boost::uint32_t> *invars=0;
    if(invariants){
      unsigned int nInvar=python::extract<unsigned int>(invariants.attr("__len__")());
      if(nInvar){
        if(nInvar!=mol.getNumAtoms()){
          throw_value_error("length of invariant vector != number of atoms");
        }
        invars = new std::vector<boost::uint32_t>(mol.getNumAtoms());
        for(unsigned int i=0;i<mol.getNumAtoms();++i){
          (*invars)[i] = python::extract<boost::uint32_t>(invariants[i]);
        }
      }
    }
    std::vector<boost::uint32_t> *froms=0;
    if(fromAtoms){
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      if(nFrom){
        froms = new std::vector<boost::uint32_t>();
        for(unsigned int i=0;i<nFrom;++i){
          froms->push_back(python::extract<boost::uint32_t>(fromAtoms[i]));
        }
      }
    }
    RDKit::SparseIntVect<boost::uint32_t> *res;
    res = RDKit::MorganFingerprints::getFingerprint(mol,
                                                    static_cast<unsigned int>(radius),
                                                    invars,froms);
    if(invars) delete invars;
    if(froms) delete froms;
    return res;
  }

  ExplicitBitVect *GetMorganFingerprintBV(const RDKit::ROMol &mol,
                                             int radius,
                                             unsigned int nBits,
                                             python::object invariants,
                                             python::object fromAtoms){
    std::vector<boost::uint32_t> *invars=0;
    if(invariants){
      unsigned int nInvar=python::extract<unsigned int>(invariants.attr("__len__")());
      if(nInvar){
        if(nInvar!=mol.getNumAtoms()){
          throw_value_error("length of invariant vector != number of atoms");
        }
        invars = new std::vector<boost::uint32_t>(mol.getNumAtoms());
        for(unsigned int i=0;i<mol.getNumAtoms();++i){
          (*invars)[i] = python::extract<boost::uint32_t>(invariants[i]);
        }
      }
    }
    std::vector<boost::uint32_t> *froms=0;
    if(fromAtoms){
      unsigned int nFrom=python::extract<unsigned int>(fromAtoms.attr("__len__")());
      if(nFrom){
        froms = new std::vector<boost::uint32_t>();
        for(unsigned int i=0;i<nFrom;++i){
          froms->push_back(python::extract<boost::uint32_t>(fromAtoms[i]));
        }
      }
    }
    ExplicitBitVect *res;
    res = RDKit::MorganFingerprints::getFingerprint(mol,
                                                    static_cast<unsigned int>(radius),
                                                    nBits,
                                                    invars,froms);
    if(invars) delete invars;
    if(froms) delete froms;
    return res;
  }

  python::list GetConnectivityInvariants(const RDKit::ROMol &mol,bool includeRingMembership){
    std::vector<boost::uint32_t> invars(mol.getNumAtoms());
    RDKit::MorganFingerprints::getConnectivityInvariants(mol,invars,includeRingMembership);
    python::list res;
    for(std::vector<boost::uint32_t>::const_iterator iv=invars.begin();iv!=invars.end();++iv){
      res.append(python::long_(*iv));
    }
    return res;
  }
}

BOOST_PYTHON_MODULE(rdMolDescriptors) {
  python::scope().attr("__doc__") =
    "Module containing functions to compute molecular descriptors"
    ;

  python::register_exception_translator<IndexErrorException>(&translate_index_error);
  python::register_exception_translator<ValueErrorException>(&translate_value_error);

  std::string docString = "";

  python::class_<python::object>("AtomPairsParameters")
    .setattr("version",
		  RDKit::AtomPairs::atomPairsVersion)
    .setattr("numTypeBits",
		  RDKit::AtomPairs::numTypeBits)
    .setattr("numPiBits",
		  RDKit::AtomPairs::numPiBits)
    .setattr("numBranchBits",
		  RDKit::AtomPairs::numBranchBits)
    .setattr("codeSize",
		  RDKit::AtomPairs::codeSize)
    .setattr("atomTypes",
		  atomPairTypes)
    .setattr("numPathBits",
		  RDKit::AtomPairs::numPathBits)
    .setattr("numAtomPairFingerprintBits",
		  RDKit::AtomPairs::numAtomPairFingerprintBits)
    ;
  docString="Returns the atom code (hash) for an atom";
  python::def("GetAtomPairAtomCode", RDKit::AtomPairs::getAtomCode,
              (python::arg("atom"), python::arg("branchSubtract")=0),
              docString.c_str());
  docString="Returns the atom-pair fingerprint for a molecule as an IntSparseIntVect";
  python::def("GetAtomPairFingerprint", GetAtomPairFingerprint,
              (python::arg("mol"),
               python::arg("minLength")=1,
               python::arg("maxLength")=RDKit::AtomPairs::maxPathLen-1,
               python::arg("fromAtoms")=python::list()),
              docString.c_str(),
              python::return_value_policy<python::manage_new_object>());

  python::def("GetHashedAtomPairFingerprint",
	      (RDKit::SparseIntVect<boost::int32_t> *(*)(const RDKit::ROMol&,unsigned int,unsigned int,unsigned int))RDKit::AtomPairs::getHashedAtomPairFingerprint,
	      (python::arg("mol"),
               python::arg("nBits")=2048,
               python::arg("minLength")=1,
               python::arg("maxLength")=RDKit::AtomPairs::maxPathLen-1),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());
  docString="Returns the topological-torsion fingerprint for a molecule as a LongIntSparseIntVect";
  python::def("GetTopologicalTorsionFingerprint",
	      GetTopologicalTorsionFingerprint,
	      (python::arg("mol"),python::arg("targetSize")=4,
               python::arg("fromAtoms")=0),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());
  python::def("GetHashedTopologicalTorsionFingerprint",
	      GetHashedTopologicalTorsionFingerprint,
	      (python::arg("mol"),
               python::arg("nBits")=2048,
               python::arg("targetSize")=4,
               python::arg("fromAtoms")=0),
              docString.c_str(),
	      python::return_value_policy<python::manage_new_object>());

  docString="Returns a Morgan fingerprint for a molecule";
  python::def("GetMorganFingerprint", GetMorganFingerprint,
              (python::arg("mol"),python::arg("radius"),
               python::arg("invariants")=python::list(),
               python::arg("fromAtoms")=python::list()),
              docString.c_str(),
              python::return_value_policy<python::manage_new_object>());
  docString="Returns a Morgan fingerprint for a molecule as a bit vector";
  python::def("GetMorganFingerprintAsBitVect", GetMorganFingerprintBV,
              (python::arg("mol"),python::arg("radius"),python::arg("nBits")=2048,
               python::arg("invariants")=python::list(),
               python::arg("fromAtoms")=python::list()),
              docString.c_str(),
              python::return_value_policy<python::manage_new_object>());
  python::scope().attr("_MorganFingerprint_version")=
    RDKit::MorganFingerprints::morganFingerprintVersion;
  docString="Returns connectivity invariants (ECFP-like) for a molecule.";
  python::def("GetConnectivityInvariants", GetConnectivityInvariants,
              (python::arg("mol"),python::arg("includeRingMembership")=false),
              docString.c_str());
  python::scope().attr("_ConnectivityInvariants_version")=
    RDKit::MorganFingerprints::morganFingerprintVersion;

  docString="returns (as a list of 2-tuples) the contributions of each atom to\n"
    "the Wildman-Cripppen logp and mr value";
  python::def("_CalcCrippenContribs",
	      computeCrippenContribs,
	      (python::arg("mol"),
	       python::arg("force")=false),
              docString.c_str());
  docString="returns a 2-tuple with the Wildman-Crippen logp,mr values";
  python::def("CalcCrippenDescriptors",
	      calcCrippenDescriptors,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());
  python::scope().attr("_CalcCrippenDescriptors_version")=
    RDKit::Descriptors::crippenVersion;

  docString="returns the Labute ASA value for a molecule";
  python::def("CalcLabuteASA",
	      RDKit::Descriptors::calcLabuteASA,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());
  python::scope().attr("_CalcLabuteASA_version")=RDKit::Descriptors::labuteASAVersion;

  docString="returns a list of atomic contributions to the Labute ASA";
  python::def("_CalcLabuteASAContribs",
	      computeASAContribs,
	      (python::arg("mol"),python::arg("includeHs")=true,
	       python::arg("force")=false),
              docString.c_str());

  docString="returns the molecule's molecular weight";
  python::def("_CalcMolWt",
	      RDKit::Descriptors::CalcAMW,
	      (python::arg("mol"),python::arg("onlyHeavy")=false),
              docString.c_str());
  python::scope().attr("_CalcMolWt_version")="1.0.0";

}
<|endoftext|>


<commit_before>#ifndef LIBPORT_SINGLETON_PTR_HH
# define LIBPORT_SINGLETON_PTR_HH

# define STATIC_INSTANCE_(Cl, Name)					\
  class Cl ## Name;							\
  libport::SingletonPtr<Cl ## Name> Name;				\
  template<> Cl ## Name* libport::SingletonPtr<Cl ## Name>::ptr = 0

# define STATIC_INSTANCE_DECL_(Cl, Name)				\
  class Cl ## Name							\
    : public Cl								\
  {};									\
  STATIC_INSTANCE_(Cl, Name)

# define EXTERN_STATIC_INSTANCE_EX(Cl, Name, Api)			\
  class Api Cl ## Name							\
    : public Cl								\
  {};									\
  Api extern libport::SingletonPtr<Cl ## Name> Name;

# define EXTERN_STATIC_INSTANCE(Cl, Name)				\
  EXTERN_STATIC_INSTANCE_EX(Cl, Name, /* No API. */)

// These _NS version are made to bypass vcxx error C2888
// cf: http://msdn.microsoft.com/en-us/library/27zksbks(VS.80).aspx
// Symbol in libport cannot be defined inside urbi. This appeared
// after changes done for liburbi Java.
// Use them "outside" of any namespace.

# define STATIC_INSTANCE_NS_EX(Cl, Name, NS, Api)			\
  namespace NS {							\
    Api libport::SingletonPtr<Cl ## Name> Name;				\
  }									\
  template<> NS::Cl ## Name*						\
  libport::SingletonPtr<NS::Cl ## Name>::ptr = 0

# define STATIC_INSTANCE_NS(Cl, Name, NS)				\
  STATIC_INSTANCE_NS_EX(Cl, Name, NS, /* No API */)

# define STATIC_INSTANCE_DECL_NS(Cl, Name, NS)				\
  namespace NS {							\
    class Cl ## Name							\
      : public Cl							\
    {};									\
  }									\
  STATIC_INSTANCE_NS(Cl, Name, NS)

namespace libport
{
  /// Singleton smart pointer that creates the object on demand.
  template<typename T>
  class SingletonPtr
  {
  public:
    operator T* ();
    operator T& ();
    T* operator ->();

  private:
    static T* instance();
    static T* ptr;
  };

}  // namespace libport

# include <libport/singleton-ptr.hxx>

#endif // !LIBPORT_SINGLETON_PTR_HH
<commit_msg>Properly export the singleton.<commit_after>#ifndef LIBPORT_SINGLETON_PTR_HH
# define LIBPORT_SINGLETON_PTR_HH

# define STATIC_INSTANCE_(Cl, Name)					\
  class Cl ## Name;							\
  libport::SingletonPtr<Cl ## Name> Name;				\
  template<> Cl ## Name* libport::SingletonPtr<Cl ## Name>::ptr = 0

# define STATIC_INSTANCE_DECL_(Cl, Name)				\
  class Cl ## Name							\
    : public Cl								\
  {};									\
  STATIC_INSTANCE_(Cl, Name)

# define EXTERN_STATIC_INSTANCE_EX(Cl, Name, Api)			\
  class Api Cl ## Name							\
    : public Cl								\
  {};									\
  Api extern libport::SingletonPtr<Cl ## Name> Name;

# define EXTERN_STATIC_INSTANCE(Cl, Name)				\
  EXTERN_STATIC_INSTANCE_EX(Cl, Name, /* No API. */)

// These _NS version are made to bypass vcxx error C2888
// cf: http://msdn.microsoft.com/en-us/library/27zksbks(VS.80).aspx
// Symbol in libport cannot be defined inside urbi. This appeared
// after changes done for liburbi Java.
// Use them "outside" of any namespace.

# define STATIC_INSTANCE_NS_EX(Cl, Name, NS, Api)			\
  namespace NS {							\
    Api libport::SingletonPtr<Cl ## Name> Name;				\
  }									\
  template<> Api NS::Cl ## Name*					\
  libport::SingletonPtr<NS::Cl ## Name>::ptr = 0

# define STATIC_INSTANCE_NS(Cl, Name, NS)				\
  STATIC_INSTANCE_NS_EX(Cl, Name, NS, /* No API */)

# define STATIC_INSTANCE_DECL_NS(Cl, Name, NS)				\
  namespace NS {							\
    class Cl ## Name							\
      : public Cl							\
    {};									\
  }									\
  STATIC_INSTANCE_NS(Cl, Name, NS)

namespace libport
{
  /// Singleton smart pointer that creates the object on demand.
  template<typename T>
  class SingletonPtr
  {
  public:
    operator T* ();
    operator T& ();
    T* operator ->();

  private:
    static T* instance();
    static T* ptr;
  };

}  // namespace libport

# include <libport/singleton-ptr.hxx>

#endif // !LIBPORT_SINGLETON_PTR_HH
<|endoftext|>


<commit_before>/*

Copyright (c) 2009-2014, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ALLOCATOR_HPP_INCLUDED
#define TORRENT_ALLOCATOR_HPP_INCLUDED

#include <cstddef>
#include "libtorrent/config.hpp"

namespace libtorrent
{

	TORRENT_EXTRA_EXPORT int page_size();

	struct TORRENT_EXTRA_EXPORT page_aligned_allocator
	{
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;

		static char* malloc(const size_type bytes);
		static void free(char* block);
	};

	struct TORRENT_EXTRA_EXPORT aligned_holder
	{
		aligned_holder(): m_buf(0) {}
		aligned_holder(int size): m_buf(page_aligned_allocator::malloc(size)) {}
		~aligned_holder() { if (m_buf) page_aligned_allocator::free(m_buf); }
		char* get() const { return m_buf; }
		void reset(char* buf = 0)
		{
			if (m_buf) page_aligned_allocator::free(m_buf);
			m_buf = buf;
		}
		void swap(aligned_holder& h)
		{
			char* tmp = m_buf;
			m_buf = h.m_buf;
			h.m_buf =  tmp;
		}
	private:
		char* m_buf;
	};

}

#endif

<commit_msg>aligned_holder should not be copyable<commit_after>/*

Copyright (c) 2009-2014, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ALLOCATOR_HPP_INCLUDED
#define TORRENT_ALLOCATOR_HPP_INCLUDED

#include <cstddef>
#include "libtorrent/config.hpp"

namespace libtorrent
{

	TORRENT_EXTRA_EXPORT int page_size();

	struct TORRENT_EXTRA_EXPORT page_aligned_allocator
	{
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;

		static char* malloc(const size_type bytes);
		static void free(char* block);
	};

	struct TORRENT_EXTRA_EXPORT aligned_holder
	{
		aligned_holder(): m_buf(0) {}
		aligned_holder(int size): m_buf(page_aligned_allocator::malloc(size)) {}
		~aligned_holder() { if (m_buf) page_aligned_allocator::free(m_buf); }
		char* get() const { return m_buf; }
		void reset(char* buf = 0)
		{
			if (m_buf) page_aligned_allocator::free(m_buf);
			m_buf = buf;
		}
		void swap(aligned_holder& h)
		{
			char* tmp = m_buf;
			m_buf = h.m_buf;
			h.m_buf =  tmp;
		}
	private:
		aligned_holder(aligned_holder const&);
		aligned_holder& operator=(aligned_holder const&);
		char* m_buf;
	};

}

#endif

<|endoftext|>


<commit_before>/*
 * PatternLayout.hh
 *
 * Copyright 2002, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_PATTERNLAYOUT_HH
#define _LOG4CPP_PATTERNLAYOUT_HH

#include <log4cpp/Portability.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/Configurator.hh>
#include <vector>
#ifdef LOG4CPP_HAVE_SSTREAM
#include <sstream>
#endif

namespace log4cpp {

    /**
     * PatternLayout is a simple fixed format Layout implementation.
     **/
    class LOG4CPP_EXPORT PatternLayout : public Layout {
        public:
        /**
           The default conversion pattern
        **/
        static const char* DEFAULT_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the SimpleLayout.
        **/
        static const char* SIMPLE_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the BasicLayout.
        **/
        static const char* BASIC_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the TTCCLayout.
           Note: TTCCLayout is in log4j but not log4cpp.
        **/
        static const char* TTCC_CONVERSION_PATTERN;

        PatternLayout();
        virtual ~PatternLayout();

        // NOTE: All double percentage signs ('%%') followed by a character
        //       in the following comments should actually be a single char.
        //       The doubles are included so that doxygen will print them correctly.
        /**
         * Formats the LoggingEvent in the style set by
		 * the setConversionPattern call. By default, set
		 * to "%%m%%n"
         **/
        virtual std::string format(const LoggingEvent& event);

        /**
         * Sets the format of log lines handled by this
         * PatternLayout. By default, set to "%%m%%n".

         * Format characters are as follows:

         *
%%%% - a single percent sign

         *
%%c - the category

         *
%%d - the date\n
         *  Date format: The date format character may be followed by a date format
         *  specifier enclosed between braces. For example, %%d{%%H:%%M:%%S,%%l} or %%d{%%d %%m %%Y %%H:%%M:%%S,%%l}.
         *  If no date format specifier is given then the following format is used:
         *  "Wed Jan 02 02:03:55 1980". The date format specifier admits the same syntax
         *  as the ANSI C function strftime, with 1 addition. The addition is the specifier
         *  %%l for milliseconds, padded with zeros to make 3 digits.

         *
%%m - the message

         *
%%n - the platform specific line separator

         *
%%p - the priority

         *
%%r - milliseconds since this layout was created.

         *
%%R - seconds since Jan 1, 1970

         *
%%u - clock ticks since process start

         *
%%x - the NDC

         * @param conversionPattern the conversion pattern
         * @exception ConfigureFailure if the pattern is invalid
         **/
        virtual void setConversionPattern(const std::string& conversionPattern)
            throw(ConfigureFailure);

        virtual std::string getConversionPattern() const;

        virtual void clearConversionPattern();

        class LOG4CPP_EXPORT PatternComponent {
            public:
            inline virtual ~PatternComponent() {};
            virtual void append(std::ostringstream& out, const LoggingEvent& event) = 0;
        };

        private:
        typedef std::vector<PatternComponent*> ComponentVector;
        ComponentVector _components;

        std::string _conversionPattern;
    };
}

#endif // _LOG4CPP_PATTERNLAYOUT_HH
<commit_msg>Doc fix.<commit_after>/*
 * PatternLayout.hh
 *
 * Copyright 2002, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_PATTERNLAYOUT_HH
#define _LOG4CPP_PATTERNLAYOUT_HH

#include <log4cpp/Portability.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/Configurator.hh>
#include <vector>
#ifdef LOG4CPP_HAVE_SSTREAM
#include <sstream>
#endif

namespace log4cpp {

    /**
     * PatternLayout is a simple fixed format Layout implementation.
     **/
    class LOG4CPP_EXPORT PatternLayout : public Layout {
        public:
        /**
           The default conversion pattern
        **/
        static const char* DEFAULT_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the SimpleLayout.
        **/
        static const char* SIMPLE_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the BasicLayout.
        **/
        static const char* BASIC_CONVERSION_PATTERN;

        /**
           A conversion pattern equivalent to the TTCCLayout.
           Note: TTCCLayout is in log4j but not log4cpp.
        **/
        static const char* TTCC_CONVERSION_PATTERN;

        PatternLayout();
        virtual ~PatternLayout();

        // NOTE: All double percentage signs ('%%') followed by a character
        //       in the following comments should actually be a single char.
        //       The doubles are included so that doxygen will print them correctly.
        /**
         * Formats the LoggingEvent in the style set by
		 * the setConversionPattern call. By default, set
		 * to "%%m%%n"
         **/
        virtual std::string format(const LoggingEvent& event);

        /**
         * Sets the format of log lines handled by this
         * PatternLayout. By default, set to "%%m%%n".

         * Format characters are as follows:

         *
%% - a single percent sign

         *
%%c - the category

         *
%%d - the date\n
         *  Date format: The date format character may be followed by a date format
         *  specifier enclosed between braces. For example, %%d{%%H:%%M:%%S,%%l} or %%d{%%d %%m %%Y %%H:%%M:%%S,%%l}.
         *  If no date format specifier is given then the following format is used:
         *  "Wed Jan 02 02:03:55 1980". The date format specifier admits the same syntax
         *  as the ANSI C function strftime, with 1 addition. The addition is the specifier
         *  %%l for milliseconds, padded with zeros to make 3 digits.

         *
%%m - the message

         *
%%n - the platform specific line separator

         *
%%p - the priority

         *
%%r - milliseconds since this layout was created.

         *
%%R - seconds since Jan 1, 1970

         *
%%u - clock ticks since process start

         *
%%x - the NDC

         * @param conversionPattern the conversion pattern
         * @exception ConfigureFailure if the pattern is invalid
         **/
        virtual void setConversionPattern(const std::string& conversionPattern)
            throw(ConfigureFailure);

        virtual std::string getConversionPattern() const;

        virtual void clearConversionPattern();

        class LOG4CPP_EXPORT PatternComponent {
            public:
            inline virtual ~PatternComponent() {};
            virtual void append(std::ostringstream& out, const LoggingEvent& event) = 0;
        };

        private:
        typedef std::vector<PatternComponent*> ComponentVector;
        ComponentVector _components;

        std::string _conversionPattern;
    };
}

#endif // _LOG4CPP_PATTERNLAYOUT_HH
<|endoftext|>


<commit_before>// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Disable exception handler warnings.
#pragma warning( disable : 4530 )

#include "client/windows/sender/crash_report_sender.h"
#include "common/windows/http_upload.h"

#if _MSC_VER < 1400  // MSVC 2005/8
// Older MSVC doesn't have fscanf_s, but they are compatible as long as
// we don't use the string conversions (%s/%c/%S/%C).
#define fscanf_s fscanf
#endif

namespace google_breakpad {

static const char kCheckpointSignature[] = "GBP1\n";

CrashReportSender::CrashReportSender(const wstring &checkpoint_file)
    : checkpoint_file_(checkpoint_file),
      max_reports_per_day_(-1),
      last_sent_date_(-1),
      reports_sent_(0) {
  FILE *fd;
  if (OpenCheckpointFile(L"r", &fd) == 0) {
    ReadCheckpoint(fd);
    fclose(fd);
  }
}

ReportResult CrashReportSender::SendCrashReport(
    const wstring &url, const map<wstring, wstring> &parameters,
    const wstring &dump_file_name, wstring *report_code) {
  int today = GetCurrentDate();
  if (today == last_sent_date_ &&
      max_reports_per_day_ != -1 &&
      reports_sent_ >= max_reports_per_day_) {
    return RESULT_THROTTLED;
  }

  int http_response = 0;
  bool result = HTTPUpload::SendRequest(
    url, parameters, dump_file_name, L"upload_file_minidump", report_code,
    &http_response);
  ReportSent(today);

  if (result) {
    return RESULT_SUCCEEDED;
  } else if (http_response == 400) {  // TODO: update if/when the server
                                      //       switches to a different code
    return RESULT_REJECTED;
  } else {
    return RESULT_FAILED;
  }
}

void CrashReportSender::ReadCheckpoint(FILE *fd) {
  char buf[128];
  if (!fgets(buf, sizeof(buf), fd) ||
      strcmp(buf, kCheckpointSignature) != 0) {
    return;
  }

  if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) {
    last_sent_date_ = -1;
    return;
  }
  if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) {
    reports_sent_ = 0;
    return;
  }
}

void CrashReportSender::ReportSent(int today) {
  // Update the report stats
  if (today != last_sent_date_) {
    last_sent_date_ = today;
    reports_sent_ = 0;
  }
  ++reports_sent_;

  // Update the checkpoint file
  FILE *fd;
  if (OpenCheckpointFile(L"w", &fd) == 0) {
    fputs(kCheckpointSignature, fd);
    fprintf(fd, "%d\n", last_sent_date_);
    fprintf(fd, "%d\n", reports_sent_);
    fclose(fd);
  }
}

int CrashReportSender::GetCurrentDate() const {
  SYSTEMTIME system_time;
  GetSystemTime(&system_time);
  return (system_time.wYear * 10000) + (system_time.wMonth * 100) +
      system_time.wDay;
}

int CrashReportSender::OpenCheckpointFile(const wchar_t *mode, FILE **fd) {
#if _MSC_VER >= 1400  // MSVC 2005/8
  return _wfopen_s(fd, checkpoint_file_.c_str(), mode);
#else
  *fd = _wfopen(checkpoint_file_.c_str(), mode);
  if (*fd == NULL) {
    return errno;
  }
  return 0;
#endif
}

}  // namespace google_breakpad
<commit_msg>Assertion in CrashReportSender (windows) when no checkpoint file is desired (#216).  Patch by Ben Turner <bent.mozilla>.  r=me.<commit_after>// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Disable exception handler warnings.
#pragma warning( disable : 4530 )

#include "client/windows/sender/crash_report_sender.h"
#include "common/windows/http_upload.h"

#if _MSC_VER < 1400  // MSVC 2005/8
// Older MSVC doesn't have fscanf_s, but they are compatible as long as
// we don't use the string conversions (%s/%c/%S/%C).
#define fscanf_s fscanf
#endif

namespace google_breakpad {

static const char kCheckpointSignature[] = "GBP1\n";

CrashReportSender::CrashReportSender(const wstring &checkpoint_file)
    : checkpoint_file_(checkpoint_file),
      max_reports_per_day_(-1),
      last_sent_date_(-1),
      reports_sent_(0) {
  FILE *fd;
  if (OpenCheckpointFile(L"r", &fd) == 0) {
    ReadCheckpoint(fd);
    fclose(fd);
  }
}

ReportResult CrashReportSender::SendCrashReport(
    const wstring &url, const map<wstring, wstring> &parameters,
    const wstring &dump_file_name, wstring *report_code) {
  int today = GetCurrentDate();
  if (today == last_sent_date_ &&
      max_reports_per_day_ != -1 &&
      reports_sent_ >= max_reports_per_day_) {
    return RESULT_THROTTLED;
  }

  int http_response = 0;
  bool result = HTTPUpload::SendRequest(
    url, parameters, dump_file_name, L"upload_file_minidump", report_code,
    &http_response);
  ReportSent(today);

  if (result) {
    return RESULT_SUCCEEDED;
  } else if (http_response == 400) {  // TODO: update if/when the server
                                      //       switches to a different code
    return RESULT_REJECTED;
  } else {
    return RESULT_FAILED;
  }
}

void CrashReportSender::ReadCheckpoint(FILE *fd) {
  char buf[128];
  if (!fgets(buf, sizeof(buf), fd) ||
      strcmp(buf, kCheckpointSignature) != 0) {
    return;
  }

  if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) {
    last_sent_date_ = -1;
    return;
  }
  if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) {
    reports_sent_ = 0;
    return;
  }
}

void CrashReportSender::ReportSent(int today) {
  // Update the report stats
  if (today != last_sent_date_) {
    last_sent_date_ = today;
    reports_sent_ = 0;
  }
  ++reports_sent_;

  // Update the checkpoint file
  FILE *fd;
  if (OpenCheckpointFile(L"w", &fd) == 0) {
    fputs(kCheckpointSignature, fd);
    fprintf(fd, "%d\n", last_sent_date_);
    fprintf(fd, "%d\n", reports_sent_);
    fclose(fd);
  }
}

int CrashReportSender::GetCurrentDate() const {
  SYSTEMTIME system_time;
  GetSystemTime(&system_time);
  return (system_time.wYear * 10000) + (system_time.wMonth * 100) +
      system_time.wDay;
}

int CrashReportSender::OpenCheckpointFile(const wchar_t *mode, FILE **fd) {
  if (checkpoint_file_.empty()) {
    return ENOENT;
  }
#if _MSC_VER >= 1400  // MSVC 2005/8
  return _wfopen_s(fd, checkpoint_file_.c_str(), mode);
#else
  *fd = _wfopen(checkpoint_file_.c_str(), mode);
  if (*fd == NULL) {
    return errno;
  }
  return 0;
#endif
}

}  // namespace google_breakpad
<|endoftext|>


<commit_before>#ifndef DROPCONNECT_HPP
#define DROPCONNECT_HPP

#include "module.hpp"

namespace nnlib
{

/// A module decorator that randomly drops parameters with a given probability.
template <typename T = double>
class DropConnect : public Module<T>
{
public:
	DropConnect(Module<T> *module, T dropProbability = 0.1) :
		m_module(module),
		m_dropProbability(dropProbability),
		m_training(true)
	{
		NNAssertGreaterThanOrEquals(dropProbability, 0, "Expected a probability!");
		NNAssertLessThan(dropProbability, 1, "Expected a probability!");
	}

	DropConnect(const DropConnect &module) :
		m_module(module.m_module->copy()),
		m_dropProbability(module.m_dropProbability),
		m_training(module.m_training)
	{}

	DropConnect(const Serialized &node) :
		m_module(node.get<Module<T> *>("module")),
		m_dropProbability(node.get<T>("dropProbability")),
		m_training(node.get<bool>("training"))
	{}

	DropConnect &operator=(DropConnect module)
	{
		swap(*this, module);
		return *this;
	}

	virtual ~DropConnect()
	{
		delete m_module;
	}

	friend void swap(DropConnect &a, DropConnect &b)
	{
		using std::swap;
		swap(a.m_module, b.m_module);
		swap(a.m_dropProbability, b.m_dropProbability);
		swap(a.m_training, b.m_training);
	}

	/// Get the module this is decorating.
	Module<T> &module()
	{
		return *m_module;
	}

	/// Set the module this is decorating.
	DropConnect &module(Module<T> *module)
	{
		delete m_module;
		m_module = module;
	}

	/// Get the probability that an output is not dropped.
	T dropProbability() const
	{
		return m_dropProbability;
	}

	/// Set the probability that an output is not dropped.
	DropConnect &dropProbability(T dropProbability)
	{
		NNAssertGreaterThanOrEquals(dropProbability, 0, "Expected a probability!");
		NNAssertLessThan(dropProbability, 1, "Expected a probability!");
		m_dropProbability = dropProbability;
		return *this;
	}

	bool isTraining() const
	{
		return m_training;
	}

	virtual void training(bool training = true) override
	{
		m_training = training;
		m_module->training(training);
	}

	virtual void forget() override
	{
		m_module->forget();
	}

	// MARK: Serialization

	virtual void save(Serialized &node) const override
	{
		node.set("module", m_module);
		node.set("dropProbability", m_dropProbability);
		node.set("training", m_training);
	}

	// MARK: Computation

	virtual Tensor<T> &forward(const Tensor<T> &input) override
	{
		if(m_training)
		{
			m_output.resize(input.shape());
			m_mask.resize(m_module->params().shape());
			m_backup.resize(m_module->params().shape());
			m_backup.copy(m_module->params());
			m_module->params().pointwiseProduct(m_mask.bernoulli(1 - m_dropProbability));
			m_output = m_module->forward(input);
		}
		else
			m_output = m_module->forward(input).scale(1 - m_dropProbability);

		return m_output;
	}

	virtual Tensor<T> &backward(const Tensor<T> &input, const Tensor<T> &outGrad) override
	{
		if(m_training)
		{
			m_inGrad = m_module->backward(input, outGrad);
			m_module->params().copy(m_backup);
		}
		else
			m_inGrad = m_module->backward(input, outGrad).scale(1 - m_dropProbability);

		return m_inGrad;
	}

	// MARK: Buffers

	virtual Storage<Tensor<T> *> paramsList() override
	{
		return m_module->paramsList();
	}

	virtual Storage<Tensor<T> *> gradList() override
	{
		return m_module->gradList();
	}

	virtual Storage<Tensor<T> *> stateList() override
	{
		return Module<T>::stateList().append(m_module->stateList()).append({ &m_mask, &m_backup });
	}

protected:
	using Module<T>::m_output;
	using Module<T>::m_inGrad;

private:
	Module<T> *m_module;
	Tensor<T> m_backup;
	Tensor<T> m_mask;
	T m_dropProbability;
	bool m_training;
};

}

NNRegisterType(DropConnect, Module);

#endif
<commit_msg>Split DropConnect.<commit_after>#ifndef DROPCONNECT_HPP
#define DROPCONNECT_HPP

#include "module.hpp"

namespace nnlib
{

template <typename T>
class DropConnect;

template <typename T>
void swap(DropConnect<T> &, DropConnect<T> &);

/// A module decorator that randomly drops parameters with a given probability.
template <typename T = double>
class DropConnect : public Module<T>
{
public:
	DropConnect(Module<T> *module, T dropProbability = 0.1);
	DropConnect(const DropConnect &module);
	DropConnect(const Serialized &node);

	DropConnect &operator=(DropConnect module);

	virtual ~DropConnect();

	friend void swap <> (DropConnect &a, DropConnect &b);

	/// Get the module this is decorating.
	Module<T> &module();

	/// Set the module this is decorating.
	DropConnect &module(Module<T> *module);

	/// Get the probability that an output is not dropped.
	T dropProbability() const;

	/// Set the probability that an output is not dropped.
	DropConnect &dropProbability(T dropProbability);

	bool isTraining() const;

	virtual void training(bool training = true) override;
	virtual void forget() override;

	// MARK: Serialization

	virtual void save(Serialized &node) const override;

	// MARK: Computation

	virtual Tensor<T> &forward(const Tensor<T> &input) override;
	virtual Tensor<T> &backward(const Tensor<T> &input, const Tensor<T> &outGrad) override;

	// MARK: Buffers

	virtual Storage<Tensor<T> *> paramsList() override;
	virtual Storage<Tensor<T> *> gradList() override;
	virtual Storage<Tensor<T> *> stateList() override;

protected:
	using Module<T>::m_output;
	using Module<T>::m_inGrad;

private:
	Module<T> *m_module;
	Tensor<T> m_backup;
	Tensor<T> m_mask;
	T m_dropProbability;
	bool m_training;
};

}

NNRegisterType(DropConnect, Module);
NNTemplateDefinition(DropConnect, "detail/dropconnect.tpp");

#endif
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2021-present ScyllaDB
 */

#pragma once

#include <concepts>
#include <type_traits>
#include <tuple>
#include <seastar/core/coroutine.hh>

namespace seastar::coroutine {

template <typename Future>
constexpr inline bool is_future_v = is_future<Future>::value;

template <typename Future>
concept future_type = is_future_v<Future>;

namespace internal {

// Given a bunch of futures, find the indexes of the ones that are not avoid
// and store them in member type `type` as an std::integer_sequence.
//
// `IndexSequence` and `current` are intermediates used for recursion.
template <typename IndexSequence, size_t current, typename... Futures>
struct index_sequence_for_non_void_futures_helper;

// Terminate recursion be returning the accumulated `IndexSequence`
template <typename IndexSequence, size_t current>
struct index_sequence_for_non_void_futures_helper<IndexSequence, current> {
    using type = IndexSequence;
};

// Process a future<T> by adding it to the current IndexSequence and recursing
template <size_t... Existing, size_t current, typename T, typename... Futures>
struct index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current, future<T>, Futures...> {
    using type = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing..., current>, current + 1, Futures...>::type;
};

// Process a future<void> by ignoring it and recursing
template <size_t... Existing, size_t current, typename... Futures>
struct index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current, future<>, Futures...> {
    using type = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current + 1, Futures...>::type;
};

// Simple interface for the above.
template <typename... Futures>
using index_sequence_for_non_void_futures = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t>, 0, Futures...>::type;

// Given a tuple of futures, return a tuple of the value types, excluding future<void>.
template <typename IndexSequence, typename FutureTuple>
struct value_tuple_for_non_void_futures_helper;

template <size_t... Idx, typename FutureTuple>
struct value_tuple_for_non_void_futures_helper<std::integer_sequence<size_t, Idx...>, FutureTuple> {
    using type = std::tuple<typename std::tuple_element_t<Idx, FutureTuple>::value_type...>;
};

// Simple interface for the above
template <typename... Futures>
using value_tuple_for_non_void_futures = typename value_tuple_for_non_void_futures_helper<index_sequence_for_non_void_futures<Futures...>, std::tuple<Futures...>>::type;

}

/// Wait for serveral futures to complete in a coroutine.
///
/// `all` can be used to launch several computations concurrently
/// and wait for all of them to complete. Computations are provided
/// as callable objects (typically lambda coroutines) that are invoked
/// by `all`. Waiting is performend by `co_await` and returns a tuple
/// of values, one for each non-void future.
///
/// If one or more of the function objects throws an exception, or if one
/// or more of the futures resolves to an exception, then the exception is
/// thrown. All of the futures are waited for, even in the case of exceptions.
/// If more than one exception is present, an arbitrary one is thrown.
///
/// Example
///
/// ```
/// future<int> add() {
///     auto [a, b] = co_await all(
///         [] () -> future<int> {
///             co_await sleep(1ms);
///             co_return 2;
///         },
///         [] () -> future<int> {
///             co_await sleep(1ms);
///             co_return 3;
///         }
///     );
///     co_return a + b;
/// };
/// ```
template <typename... Futures>
class [[nodiscard("must co_await an all() object")]] all {
    using tuple = std::tuple<Futures...>;
    using value_tuple = typename internal::value_tuple_for_non_void_futures<Futures...>;
    struct awaiter;
    template <size_t idx>
    struct intermediate_task final : continuation_base_from_future_t<std::tuple_element_t<idx, tuple>> {
        awaiter& container;
        explicit intermediate_task(awaiter& container) : container(container) {}
        virtual void run_and_dispose() noexcept {
            using value_type = typename std::tuple_element_t<idx, tuple>::value_type;
            if (__builtin_expect(this->_state.failed(), false)) {
                using futurator = futurize<std::tuple_element_t<idx, tuple>>;
                std::get<idx>(container.state._futures) = futurator::make_exception_future(std::move(this->_state).get_exception());
            } else {
                if constexpr (std::same_as<std::tuple_element_t<idx, tuple>, future<>>) {
                    std::get<idx>(container.state._futures) = make_ready_future<>();
                } else {
                    std::get<idx>(container.state._futures) = make_ready_future<value_type>(std::move(this->_state).get0());
                }
            }
            this->~intermediate_task();
            container.template process<idx+1>();
        }
    };
    template <typename IndexSequence>
    struct generate_aligned_union;
    template <size_t... idx>
    struct generate_aligned_union<std::integer_sequence<size_t, idx...>> {
        using type = std::aligned_union_t<1, intermediate_task<idx>...>;
    };
    using continuation_storage_t = typename generate_aligned_union<std::make_index_sequence<std::tuple_size_v<tuple>>>::type;
    using coroutine_handle_t = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
private:
    tuple _futures;
private:
    struct awaiter {
        all& state;
        continuation_storage_t _continuation_storage;
        coroutine_handle_t when_ready;
        awaiter(all& state) : state(state) {}
        bool await_ready() const {
            return std::apply([] (const Futures&... futures) {
                return (... && futures.available());
            }, state._futures);
        }
        void await_suspend(coroutine_handle_t h) {
            when_ready = h;
            process<0>();
        }
        value_tuple await_resume() {
            std::apply([] (Futures&... futures) {
                std::exception_ptr e;
                // Call get_exception for every failed future, to avoid exceptional future
                // ignored warnings.
                (void)(..., (futures.failed() ? (e = futures.get_exception(), 0) : 0));
                if (e) {
                    std::rethrow_exception(std::move(e));
                }
            }, state._futures);
            // This immediately-invoked lambda is used to materialize the indexes
            // of non-void futures in the tuple.
            return [&] <size_t... Idx> (std::integer_sequence<size_t, Idx...>) {
                return value_tuple(std::get<Idx>(state._futures).get0()...);
            } (internal::index_sequence_for_non_void_futures<Futures...>());
        }
        template <unsigned idx>
        void process() {
            if constexpr (idx == sizeof...(Futures)) {
                when_ready.resume();
            } else {
                if (!std::get<idx>(state._futures).available()) {
                    auto task = new (&_continuation_storage) intermediate_task<idx>(*this);
                    seastar::internal::set_callback(std::move(std::get<idx>(state._futures)), task);
                } else {
                    process<idx + 1>();
                }
            }
        }
    };
public:
    template <typename... Func>
    requires (... && std::invocable<Func>) && (... && future_type<std::invoke_result_t<Func>>)
    explicit all(Func&&... funcs)
            : _futures(futurize_invoke(funcs)...) {
    }
    awaiter operator co_await() { return awaiter{*this}; }
};

template <typename... Func>
explicit all(Func&&... funcs) -> all<std::invoke_result_t<Func>...>;

}<commit_msg>coroutines/all: ensure the template argument deduction work with clang-15<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2021-present ScyllaDB
 */

#pragma once

#include <concepts>
#include <type_traits>
#include <tuple>
#include <seastar/core/coroutine.hh>

namespace seastar::coroutine {

template <typename Future>
constexpr inline bool is_future_v = is_future<Future>::value;

template <typename Future>
concept future_type = is_future_v<Future>;

namespace internal {

// Given a bunch of futures, find the indexes of the ones that are not avoid
// and store them in member type `type` as an std::integer_sequence.
//
// `IndexSequence` and `current` are intermediates used for recursion.
template <typename IndexSequence, size_t current, typename... Futures>
struct index_sequence_for_non_void_futures_helper;

// Terminate recursion be returning the accumulated `IndexSequence`
template <typename IndexSequence, size_t current>
struct index_sequence_for_non_void_futures_helper<IndexSequence, current> {
    using type = IndexSequence;
};

// Process a future<T> by adding it to the current IndexSequence and recursing
template <size_t... Existing, size_t current, typename T, typename... Futures>
struct index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current, future<T>, Futures...> {
    using type = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing..., current>, current + 1, Futures...>::type;
};

// Process a future<void> by ignoring it and recursing
template <size_t... Existing, size_t current, typename... Futures>
struct index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current, future<>, Futures...> {
    using type = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t, Existing...>, current + 1, Futures...>::type;
};

// Simple interface for the above.
template <typename... Futures>
using index_sequence_for_non_void_futures = typename index_sequence_for_non_void_futures_helper<std::integer_sequence<size_t>, 0, Futures...>::type;

// Given a tuple of futures, return a tuple of the value types, excluding future<void>.
template <typename IndexSequence, typename FutureTuple>
struct value_tuple_for_non_void_futures_helper;

template <size_t... Idx, typename FutureTuple>
struct value_tuple_for_non_void_futures_helper<std::integer_sequence<size_t, Idx...>, FutureTuple> {
    using type = std::tuple<typename std::tuple_element_t<Idx, FutureTuple>::value_type...>;
};

// Simple interface for the above
template <typename... Futures>
using value_tuple_for_non_void_futures = typename value_tuple_for_non_void_futures_helper<index_sequence_for_non_void_futures<Futures...>, std::tuple<Futures...>>::type;

}

/// Wait for serveral futures to complete in a coroutine.
///
/// `all` can be used to launch several computations concurrently
/// and wait for all of them to complete. Computations are provided
/// as callable objects (typically lambda coroutines) that are invoked
/// by `all`. Waiting is performend by `co_await` and returns a tuple
/// of values, one for each non-void future.
///
/// If one or more of the function objects throws an exception, or if one
/// or more of the futures resolves to an exception, then the exception is
/// thrown. All of the futures are waited for, even in the case of exceptions.
/// If more than one exception is present, an arbitrary one is thrown.
///
/// Example
///
/// ```
/// future<int> add() {
///     auto [a, b] = co_await all(
///         [] () -> future<int> {
///             co_await sleep(1ms);
///             co_return 2;
///         },
///         [] () -> future<int> {
///             co_await sleep(1ms);
///             co_return 3;
///         }
///     );
///     co_return a + b;
/// };
/// ```
template <typename... Futures>
class [[nodiscard("must co_await an all() object")]] all {
    using tuple = std::tuple<Futures...>;
    using value_tuple = typename internal::value_tuple_for_non_void_futures<Futures...>;
    struct awaiter;
    template <size_t idx>
    struct intermediate_task final : continuation_base_from_future_t<std::tuple_element_t<idx, tuple>> {
        awaiter& container;
        explicit intermediate_task(awaiter& container) : container(container) {}
        virtual void run_and_dispose() noexcept {
            using value_type = typename std::tuple_element_t<idx, tuple>::value_type;
            if (__builtin_expect(this->_state.failed(), false)) {
                using futurator = futurize<std::tuple_element_t<idx, tuple>>;
                std::get<idx>(container.state._futures) = futurator::make_exception_future(std::move(this->_state).get_exception());
            } else {
                if constexpr (std::same_as<std::tuple_element_t<idx, tuple>, future<>>) {
                    std::get<idx>(container.state._futures) = make_ready_future<>();
                } else {
                    std::get<idx>(container.state._futures) = make_ready_future<value_type>(std::move(this->_state).get0());
                }
            }
            this->~intermediate_task();
            container.template process<idx+1>();
        }
    };
    template <typename IndexSequence>
    struct generate_aligned_union;
    template <size_t... idx>
    struct generate_aligned_union<std::integer_sequence<size_t, idx...>> {
        using type = std::aligned_union_t<1, intermediate_task<idx>...>;
    };
    using continuation_storage_t = typename generate_aligned_union<std::make_index_sequence<std::tuple_size_v<tuple>>>::type;
    using coroutine_handle_t = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
private:
    tuple _futures;
private:
    struct awaiter {
        all& state;
        continuation_storage_t _continuation_storage;
        coroutine_handle_t when_ready;
        awaiter(all& state) : state(state) {}
        bool await_ready() const {
            return std::apply([] (const Futures&... futures) {
                return (... && futures.available());
            }, state._futures);
        }
        void await_suspend(coroutine_handle_t h) {
            when_ready = h;
            process<0>();
        }
        value_tuple await_resume() {
            std::apply([] (Futures&... futures) {
                std::exception_ptr e;
                // Call get_exception for every failed future, to avoid exceptional future
                // ignored warnings.
                (void)(..., (futures.failed() ? (e = futures.get_exception(), 0) : 0));
                if (e) {
                    std::rethrow_exception(std::move(e));
                }
            }, state._futures);
            // This immediately-invoked lambda is used to materialize the indexes
            // of non-void futures in the tuple.
            return [&] <size_t... Idx> (std::integer_sequence<size_t, Idx...>) {
                return value_tuple(std::get<Idx>(state._futures).get0()...);
            } (internal::index_sequence_for_non_void_futures<Futures...>());
        }
        template <unsigned idx>
        void process() {
            if constexpr (idx == sizeof...(Futures)) {
                when_ready.resume();
            } else {
                if (!std::get<idx>(state._futures).available()) {
                    auto task = new (&_continuation_storage) intermediate_task<idx>(*this);
                    seastar::internal::set_callback(std::move(std::get<idx>(state._futures)), task);
                } else {
                    process<idx + 1>();
                }
            }
        }
    };
public:
    template <typename... Func>
    requires (... && std::invocable<Func>) && (... && future_type<std::invoke_result_t<Func>>)
    explicit all(Func&&... funcs)
            : _futures(futurize_invoke(funcs)...) {
    }
    awaiter operator co_await() { return awaiter{*this}; }
};

template <typename FirstFunc, typename... MoreFuncs>
explicit all(FirstFunc&&, MoreFuncs&&...) -> all<std::invoke_result_t<FirstFunc>,
                                                 std::invoke_result_t<MoreFuncs>...>;

}
<|endoftext|>


<commit_before><commit_msg>Render box<commit_after><|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <Eigen/Dense>

struct PointCloud {
    PointCloud();
    PointCloud(const PointCloud &cloud, const std::vector<size_t> &indices);

    std::vector<Eigen::Vector3f> points;
    std::vector<Eigen::Vector3f> normals;
    std::vector<Eigen::Vector3f> colors;
};
<commit_msg>Added size() hasColors() hasNormals() convenience methods to PointCloud<commit_after>#pragma once

#include <vector>
#include <Eigen/Dense>

struct PointCloud {
    PointCloud();
    PointCloud(const PointCloud &cloud, const std::vector<size_t> &indices);

    std::vector<Eigen::Vector3f> points;
    std::vector<Eigen::Vector3f> normals;
    std::vector<Eigen::Vector3f> colors;

    inline size_t size() { return points.size(); };
    inline bool hasColors() { return size() > 0 && colors.size() == size(); };
    inline bool hasNormals() { return size() > 0 && normals.size() == size(); };

    // TODO: add empty() and clear() methods
};

<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/internal/common.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMMON_HPP
#define VSMC_INTERNAL_COMMON_HPP

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/defines.hpp>
#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/forward.hpp>
#include <vsmc/internal/traits.hpp>

#include <vsmc/cxx11/cmath.hpp>
#include <vsmc/cxx11/functional.hpp>
#include <vsmc/cxx11/random.hpp>
#include <vsmc/cxx11/type_traits.hpp>

#include <vsmc/math/cblas.hpp>
#include <vsmc/math/constants.hpp>
#include <vsmc/math/vmath.hpp>

#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <exception>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#endif // VSMC_INTERNAL_COMMON_HPP
<commit_msg>add memory<commit_after>//============================================================================
// include/vsmc/internal/common.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMMON_HPP
#define VSMC_INTERNAL_COMMON_HPP

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/defines.hpp>
#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/forward.hpp>
#include <vsmc/internal/traits.hpp>

#include <vsmc/cxx11/cmath.hpp>
#include <vsmc/cxx11/functional.hpp>
#include <vsmc/cxx11/random.hpp>
#include <vsmc/cxx11/type_traits.hpp>

#include <vsmc/math/cblas.hpp>
#include <vsmc/math/constants.hpp>
#include <vsmc/math/vmath.hpp>

#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <exception>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#endif // VSMC_INTERNAL_COMMON_HPP
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
	MODCONSTRUCTOR(CBacklogMod) {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage);
	virtual ~CBacklogMod();
	virtual void OnModCommand(const CString& sCommand);
	bool inChan(const CString& Chan);

private:
	CString			LogPath;
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
	LogPath = sArgs;

	if(LogPath.empty()) {
		LogPath = GetNV("LogPath");
		if(LogPath.empty()) {
			// TODO: guess logpath?
			PutModule("LogPath is empty, set it with the LogPath command");
			PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW)");
		}
	} else {
		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
	}
	return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
	if (sCommand.Token(0).CaseCmp("help") == 0) {
		// TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
		PutModule("Help");
		return;
	}
	else if (sCommand.Token(0).CaseCmp("logpath") == 0) {
		LogPath = sCommand.Token(1, true);

		if(LogPath.empty()) {
			PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW)");
			PutModule("Current LogPath is set to: " + GetNV("LogPath"));
			return;
		}

		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
		return;
	}

	// TODO: handle these differently depending on how the module was loaded
	CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
	CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
	CString Channel = sCommand.Token(0);

	int printedLines = 0;
	int reqLines = sCommand.Token(1).ToInt();
	if(reqLines <= 0) {
		reqLines = 150;
	}

	CString Path = LogPath.substr(); // make copy
	Path.Replace("$NETWORK", Network);
	Path.Replace("$WINDOW", Channel);
	Path.Replace("$USER", User);

	CString DirPath = Path.substr(0, Path.find_last_of("/"));
	CString FilePath;

	std::vector<CString> FileList;
	std::vector<CString> LinesToPrint;

	// gather list of all log files for requested channel/window
	DIR *dir;
	struct dirent *ent;
	if ((dir = opendir (DirPath.c_str())) != NULL) {
		while ((ent = readdir (dir)) != NULL) {
			FilePath = DirPath + "/" + ent->d_name;
			//PutModule("DEBUG: " + FilePath + " " + Path);
			if(FilePath.StrCmp(Path, Path.find_last_of("*")) == 0) {
				FileList.push_back(FilePath);
			}
		}
		closedir (dir);
	} else {
		PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
		return;
	}

	std::sort(FileList.begin(), FileList.end());

	// loop through list of log files one by one starting from most recent...
	for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
		CFile LogFile(*it);
		CString Line;
		std::vector<CString> Lines;

		if (LogFile.Open()) {
			while (LogFile.ReadLine(Line)) {
				// store lines from file into Lines
				Lines.push_back(Line);
			}
		} else {
			PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
			continue;
		}

		LogFile.Close();

		// loop through Lines in reverse order, push to LinesToPrint
		for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
			LinesToPrint.push_back(*itl);
			printedLines++;

			if(printedLines >= reqLines) {
				break;
			}
		}

		if(printedLines >= reqLines) {
			break;
		}
	}

	bool isInChan = CBacklogMod::inChan(Channel);

	// now actually print
	for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
		 if(isInChan) {
			CString Nick = "foo";
			m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + *it, GetClient());
		 } else {
			PutModule(*it);
		 }
	}

	if(printedLines == 0) {
		PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
	}
}

bool CBacklogMod::inChan(const CString& Chan) {
	const std::vector <CChan*>& vChans (m_pNetwork->GetChans());

	for (std::vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); ++it) {
		CChan *curChan = *it;
		if(Chan.StrCmp(curChan->GetName()) == 0) {
			return true;
		}
	}

	return false;
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
	Info.AddType(CModInfo::NetworkModule);
	Info.AddType(CModInfo::GlobalModule);
	Info.SetWikiPage("backlog");
	Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
	Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<commit_msg>parse nicknames from log file<commit_after>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
	MODCONSTRUCTOR(CBacklogMod) {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage);
	virtual ~CBacklogMod();
	virtual void OnModCommand(const CString& sCommand);
	bool inChan(const CString& Chan);

private:
	CString			LogPath;
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
	LogPath = sArgs;

	if(LogPath.empty()) {
		LogPath = GetNV("LogPath");
		if(LogPath.empty()) {
			// TODO: guess logpath?
			PutModule("LogPath is empty, set it with the LogPath command");
			PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW)");
		}
	} else {
		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
	}
	return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
	if (sCommand.Token(0).CaseCmp("help") == 0) {
		// TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
		PutModule("Help");
		return;
	}
	else if (sCommand.Token(0).CaseCmp("logpath") == 0) {
		LogPath = sCommand.Token(1, true);

		if(LogPath.empty()) {
			PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW)");
			PutModule("Current LogPath is set to: " + GetNV("LogPath"));
			return;
		}

		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
		return;
	}

	// TODO: handle these differently depending on how the module was loaded
	CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
	CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
	CString Channel = sCommand.Token(0);

	int printedLines = 0;
	int reqLines = sCommand.Token(1).ToInt();
	if(reqLines <= 0) {
		reqLines = 150;
	}

	CString Path = LogPath.substr(); // make copy
	Path.Replace("$NETWORK", Network);
	Path.Replace("$WINDOW", Channel);
	Path.Replace("$USER", User);

	CString DirPath = Path.substr(0, Path.find_last_of("/"));
	CString FilePath;

	std::vector<CString> FileList;
	std::vector<CString> LinesToPrint;

	// gather list of all log files for requested channel/window
	DIR *dir;
	struct dirent *ent;
	if ((dir = opendir (DirPath.c_str())) != NULL) {
		while ((ent = readdir (dir)) != NULL) {
			FilePath = DirPath + "/" + ent->d_name;
			//PutModule("DEBUG: " + FilePath + " " + Path);
			if(FilePath.StrCmp(Path, Path.find_last_of("*")) == 0) {
				FileList.push_back(FilePath);
			}
		}
		closedir (dir);
	} else {
		PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
		return;
	}

	std::sort(FileList.begin(), FileList.end());

	// loop through list of log files one by one starting from most recent...
	for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
		CFile LogFile(*it);
		CString Line;
		std::vector<CString> Lines;

		if (LogFile.Open()) {
			while (LogFile.ReadLine(Line)) {
				// store lines from file into Lines
				Lines.push_back(Line);
			}
		} else {
			PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
			continue;
		}

		LogFile.Close();

		// loop through Lines in reverse order, push to LinesToPrint
		for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
			LinesToPrint.push_back(*itl);
			printedLines++;

			if(printedLines >= reqLines) {
				break;
			}
		}

		if(printedLines >= reqLines) {
			break;
		}
	}

	bool isInChan = CBacklogMod::inChan(Channel);

	// now actually print
	for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
		 if(isInChan) {
			CString Line = *it;
			size_t FirstSpace = Line.find_first_of(' ');
			size_t Len = Line.find_first_of(' ', FirstSpace + 1) - FirstSpace;
			CString Nick = Line.substr(FirstSpace + 2, Len - 3);

			m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + Line.substr(0, FirstSpace) + Line.substr(FirstSpace + Len, Line.npos), GetClient());
		 } else {
			PutModule(*it);
		 }
	}

	if(printedLines == 0) {
		PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
	}
}

bool CBacklogMod::inChan(const CString& Chan) {
	const std::vector <CChan*>& vChans (m_pNetwork->GetChans());

	for (std::vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); ++it) {
		CChan *curChan = *it;
		if(Chan.StrCmp(curChan->GetName()) == 0) {
			return true;
		}
	}

	return false;
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
	Info.AddType(CModInfo::NetworkModule);
	Info.AddType(CModInfo::GlobalModule);
	Info.SetWikiPage("backlog");
	Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
	Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <shlobj.h>
#include <shobjidl.h>
#include <atlcomcli.h>

#include "chrome/common/win_safe_util.h"

#include "app/win_util.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"

namespace win_util {

// This function implementation is based on the attachment execution
// services functionally deployed with IE6 or Service pack 2. This
// functionality is exposed in the IAttachmentExecute COM interface.
// more information at:
// http://msdn2.microsoft.com/en-us/library/ms647048.aspx
bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
                           const FilePath& full_path,
                           const std::wstring& source_url) {
  ATL::CComPtr<IAttachmentExecute> attachment_services;
  HRESULT hr = attachment_services.CoCreateInstance(CLSID_AttachmentServices);
  if (FAILED(hr)) {
    // We don't have Attachment Execution Services, it must be a pre-XP.SP2
    // Windows installation, or the thread does not have COM initialized.
    if (hr == CO_E_NOTINITIALIZED) {
      NOTREACHED();
      return false;
    }
    return OpenItemViaShell(full_path);
  }

  // This GUID is associated with any 'don't ask me again' settings that the
  // user can select for different file types.
  // {2676A9A2-D919-4fee-9187-152100393AB2}
  static const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee,
    { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } };

  attachment_services->SetClientGuid(kClientID);

  if (!window_title.empty())
    attachment_services->SetClientTitle(window_title.c_str());

  // To help windows decide if the downloaded file is dangerous we can provide
  // what the documentation calls evidence. Which we provide now:
  //
  // Set the file itself as evidence.
  hr = attachment_services->SetLocalPath(full_path.value().c_str());
  if (FAILED(hr))
    return false;
  // Set the origin URL as evidence.
  hr = attachment_services->SetSource(source_url.c_str());
  if (FAILED(hr))
    return false;

  // Now check the windows policy.
  bool do_prompt;
  hr = attachment_services->CheckPolicy();
  if (S_FALSE == hr) {
    // The user prompt is required.
    do_prompt = true;
  } else if (S_OK == hr) {
    // An S_OK means that the file is safe to open without user consent.
    do_prompt = false;
  } else {
    // It is possible that the last call returns an undocumented result
    // equal to 0x800c000e which seems to indicate that the URL failed the
    // the security check. If you proceed with the Prompt() call the
    // Shell might show a dialog that says:
    // "windows found that this file is potentially harmful. To help protect
    // your computer, Windows has blocked access to this file."
    // Upon dismissal of the dialog windows will delete the file (!!).
    // So, we can 'return' here but maybe is best to let it happen to fail on
    // the safe side.
  }
  if (do_prompt) {
    ATTACHMENT_ACTION action;
    // We cannot control what the prompt says or does directly but it
    // is a pretty decent dialog; for example, if an excutable is signed it can
    // decode and show the publisher and the certificate.
    hr = attachment_services->Prompt(hwnd, ATTACHMENT_PROMPT_EXEC, &action);
    if (FAILED(hr) || (ATTACHMENT_ACTION_CANCEL == action))
    {
      // The user has declined opening the item.
      return false;
    }
  }
  return OpenItemViaShellNoZoneCheck(full_path);
}

bool SetInternetZoneIdentifier(const FilePath& full_path) {
  const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
  std::wstring path = full_path.value() + L":Zone.Identifier";
  HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, NULL,
                           OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (INVALID_HANDLE_VALUE == file)
    return false;

  const char kIdentifier[] = "[ZoneTransfer]\nZoneId=3";
  DWORD written = 0;
  BOOL result = WriteFile(file, kIdentifier, arraysize(kIdentifier), &written,
                          NULL);
  CloseHandle(file);

  if (!result || written != arraysize(kIdentifier)) {
    DCHECK(FALSE);
    return false;
  }

  return true;
}

}  // namespace win_util
<commit_msg>Attempt to make DownloadTest UI test less flaky.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <shlobj.h>
#include <shobjidl.h>
#include <atlcomcli.h>

#include "chrome/common/win_safe_util.h"

#include "app/win_util.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"

namespace win_util {

// This function implementation is based on the attachment execution
// services functionally deployed with IE6 or Service pack 2. This
// functionality is exposed in the IAttachmentExecute COM interface.
// more information at:
// http://msdn2.microsoft.com/en-us/library/ms647048.aspx
bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
                           const FilePath& full_path,
                           const std::wstring& source_url) {
  ATL::CComPtr<IAttachmentExecute> attachment_services;
  HRESULT hr = attachment_services.CoCreateInstance(CLSID_AttachmentServices);
  if (FAILED(hr)) {
    // We don't have Attachment Execution Services, it must be a pre-XP.SP2
    // Windows installation, or the thread does not have COM initialized.
    if (hr == CO_E_NOTINITIALIZED) {
      NOTREACHED();
      return false;
    }
    return OpenItemViaShell(full_path);
  }

  // This GUID is associated with any 'don't ask me again' settings that the
  // user can select for different file types.
  // {2676A9A2-D919-4fee-9187-152100393AB2}
  static const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee,
    { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } };

  attachment_services->SetClientGuid(kClientID);

  if (!window_title.empty())
    attachment_services->SetClientTitle(window_title.c_str());

  // To help windows decide if the downloaded file is dangerous we can provide
  // what the documentation calls evidence. Which we provide now:
  //
  // Set the file itself as evidence.
  hr = attachment_services->SetLocalPath(full_path.value().c_str());
  if (FAILED(hr))
    return false;
  // Set the origin URL as evidence.
  hr = attachment_services->SetSource(source_url.c_str());
  if (FAILED(hr))
    return false;

  // Now check the windows policy.
  bool do_prompt;
  hr = attachment_services->CheckPolicy();
  if (S_FALSE == hr) {
    // The user prompt is required.
    do_prompt = true;
  } else if (S_OK == hr) {
    // An S_OK means that the file is safe to open without user consent.
    do_prompt = false;
  } else {
    // It is possible that the last call returns an undocumented result
    // equal to 0x800c000e which seems to indicate that the URL failed the
    // the security check. If you proceed with the Prompt() call the
    // Shell might show a dialog that says:
    // "windows found that this file is potentially harmful. To help protect
    // your computer, Windows has blocked access to this file."
    // Upon dismissal of the dialog windows will delete the file (!!).
    // So, we can 'return' here but maybe is best to let it happen to fail on
    // the safe side.
  }
  if (do_prompt) {
    ATTACHMENT_ACTION action;
    // We cannot control what the prompt says or does directly but it
    // is a pretty decent dialog; for example, if an excutable is signed it can
    // decode and show the publisher and the certificate.
    hr = attachment_services->Prompt(hwnd, ATTACHMENT_PROMPT_EXEC, &action);
    if (FAILED(hr) || (ATTACHMENT_ACTION_CANCEL == action))
    {
      // The user has declined opening the item.
      return false;
    }
  }
  return OpenItemViaShellNoZoneCheck(full_path);
}

bool SetInternetZoneIdentifier(const FilePath& full_path) {
  const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
  std::wstring path = full_path.value() + L":Zone.Identifier";
  HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, NULL,
                           OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (INVALID_HANDLE_VALUE == file)
    return false;

  const char kIdentifier[] = "[ZoneTransfer]\nZoneId=3";
  DWORD written = 0;
  BOOL result = WriteFile(file, kIdentifier, arraysize(kIdentifier), &written,
                          NULL);
  BOOL flush_result = FlushFileBuffers(file);
  CloseHandle(file);

  if (!result || !flush_result || written != arraysize(kIdentifier)) {
    NOTREACHED();
    return false;
  }

  return true;
}

}  // namespace win_util
<|endoftext|>