<commit_before>#include "thor/adjacencylist.h"

namespace valhalla {
namespace thor {

// Default constructor
AdjacencyList::AdjacencyList()
    : bucketrange_(0),
      bucketcount_(0),
      bucketsize_(0),
      mincost_(0),
      maxcost_(0),
      currentcost_(0) {
}

// Constructor with bucket sizes and range.
AdjacencyList::AdjacencyList(const unsigned int mincost,
                             const unsigned int range,
                             const unsigned int bucketsize) {
  mincost_ = mincost;
  currentcost_ = mincost_;
  bucketrange_ = range;
  bucketsize_ = bucketsize;

  // Set the maximum cost (above this goes into the overflow bucket)
  maxcost_ = mincost + bucketrange_;

  // Allocate the low-level buckets
  bucketcount_ = (range / bucketsize_);
  buckets_.resize(bucketcount_);
  currentbucket_ = buckets_.begin();

  // Set the current bucket to the lowest cost low level bucket
  currentbucket_ = buckets_.begin();
}

// Destructor
AdjacencyList::~AdjacencyList() {
  Clear();
}

// Clear all edge labels from from the adjacency list. Deletes the
// allocated edge labels.
void AdjacencyList::Clear() {
  // Empty the overflow bucket first for efficiency
  EdgeLabel* elem;
  while (!overflowbucket_.empty()) {
    elem = overflowbucket_.front();
    overflowbucket_.pop_front();
    delete elem;
  }

  // Delete edge labels from the low-level buckets
  while ((elem = Remove()) != nullptr)
    delete elem;
}

// Add an edge label to the adjacency list. Adds it to the appropriate bucket
// based on its sort cost.
void AdjacencyList::Add(EdgeLabel* edgelabel) {
  if (edgelabel->sortcost() < currentcost_) {
    currentbucket_->push_front(edgelabel);
  } else {
    Bucket(edgelabel->sortcost()).push_back(edgelabel);
  }
}

/**
 * The specified edge label now has a smaller cost.  Reorders it in
 * the sorted list.
 * @param   edgelabel  Directed edge to reorder in the adjacency list
 * @param   previouscost Previous cost.
 */
void AdjacencyList::DecreaseCost(EdgeLabel* edgelabel,
                                 const unsigned int previouscost) {
  // Get the bucket the edge label currently is in. Protect against
  // previous cost less than current cost
  std::list<EdgeLabel*>& previousbucket =
      (previouscost < currentcost_) ?
          Bucket(currentcost_) : Bucket(previouscost);

  // If less than current cost add to the front of the current bucket
  unsigned int cost = edgelabel->sortcost();
  if (cost < currentcost_) {
    // Remove the edge label from the old bucket and push it on the
    // front of the current (so it is the next edge processed)
    previousbucket.remove(edgelabel);
    currentbucket_->push_front(edgelabel);
    return;
  }

  // If the old cost and the new cost are in the same bucket just return
  std::list<EdgeLabel*>& newbucket = Bucket(cost);
  if (previousbucket == newbucket)
    return;

  // Remove the edge label from the old bucket and add to the new bucket
  previousbucket.remove(edgelabel);
  newbucket.push_back(edgelabel);
}

/**
 * Removes the lowest cost edge label from the sorted list.
 * @return  Pointer to the edge label with lowest cost.
 */
EdgeLabel* AdjacencyList::Remove() {
  // If the current bucket is not empty return the edge label off the front
  if (!currentbucket_->empty()) {
    EdgeLabel* edgelabel = currentbucket_->front();
    currentbucket_->pop_front();
    return edgelabel;
  }

  // If current bucket is empty increment until a non-empty low-level
  // bucket is found. If we get to the end of the regular buckets
  // we move edge labels from the overflow buckets into the regular buckets.
  for ( ; currentbucket_ != buckets_.end(); currentbucket_++) {
    // If the current bucket is not empty get the first edge label off the list
    if (!currentbucket_->empty()) {
      EdgeLabel* edgelabel = currentbucket_->front();
      currentbucket_->pop_front();
      return edgelabel;
    }
    currentcost_ += bucketsize_;
  }

  // If no edge labels are in the overflow buckets, there are no more entries
  if (overflowbucket_.empty())
    return nullptr;

  // No edge labels in the low level buckets.  Move edge labels from the
  // overflow bucket to the low level buckets. Then find smallest bucket
  // that is not empty
  EmptyOverflow();
  for (currentbucket_ = buckets_.begin(); currentbucket_ != buckets_.end();
      currentbucket_++) {
    // If current bucket is not empty get the first edge label off the list
    if (!currentbucket_->empty()) {
      EdgeLabel* edgelabel = currentbucket_->front();
      currentbucket_->pop_front();
      return edgelabel;
    }
    currentcost_ += bucketsize_;
  }
  return nullptr;
}

// Returns the bucket given the cost
std::list<EdgeLabel*>& AdjacencyList::Bucket(const unsigned int cost) {
  return
      (cost < maxcost_) ?
          buckets_[((cost - mincost_) / bucketsize_)] : overflowbucket_;
}

// Empties the overflow bucket by placing the edgelabels into the
// low level buckets.
void AdjacencyList::EmptyOverflow() {
  bool found = false;
  unsigned int cost;
  EdgeLabel* edgelabel;
  std::vector<EdgeLabel*> tmp;
  while (!found && !overflowbucket_.empty()) {
    // Adjust cost range
    mincost_ += bucketrange_;
    maxcost_ += bucketrange_;
    currentcost_ = mincost_;

    tmp.clear();
    while (!overflowbucket_.empty()) {
      edgelabel = overflowbucket_.front();
      overflowbucket_.pop_front();
      cost = edgelabel->sortcost();
      if (cost < maxcost_) {
        buckets_[((cost - mincost_) / bucketsize_)].push_back(edgelabel);
        found = true;
      } else {
        tmp.push_back(edgelabel);
      }
    }

    // Clear overflow and add any edge labels that lie outside the new range
    overflowbucket_.clear();
    for (auto edgelabel : tmp) {
      overflowbucket_.push_back(edgelabel);
    }
  }
}

}
}

<commit_msg>Check that we are not at the end of the bucket list when clearing (was causing a crash).<commit_after>#include "thor/adjacencylist.h"

namespace valhalla {
namespace thor {

// Default constructor
AdjacencyList::AdjacencyList()
    : bucketrange_(0),
      bucketcount_(0),
      bucketsize_(0),
      mincost_(0),
      maxcost_(0),
      currentcost_(0) {
}

// Constructor with bucket sizes and range.
AdjacencyList::AdjacencyList(const unsigned int mincost,
                             const unsigned int range,
                             const unsigned int bucketsize) {
  mincost_ = mincost;
  currentcost_ = mincost_;
  bucketrange_ = range;
  bucketsize_ = bucketsize;

  // Set the maximum cost (above this goes into the overflow bucket)
  maxcost_ = mincost + bucketrange_;

  // Allocate the low-level buckets
  bucketcount_ = (range / bucketsize_);
  buckets_.resize(bucketcount_);
  currentbucket_ = buckets_.begin();

  // Set the current bucket to the lowest cost low level bucket
  currentbucket_ = buckets_.begin();
}

// Destructor
AdjacencyList::~AdjacencyList() {
  Clear();
}

// Clear all edge labels from from the adjacency list. Deletes the
// remaining allocated edge labels.
void AdjacencyList::Clear() {
  // Empty the overflow bucket first for efficiency
  EdgeLabel* elem;
  while (!overflowbucket_.empty()) {
    elem = overflowbucket_.front();
    overflowbucket_.pop_front();
    delete elem;
  }

  // Delete edge labels from the low-level buckets
  if (currentbucket_ != buckets_.end()) {
    while ((elem = Remove()) != nullptr)
      delete elem;
  }
}

// Add an edge label to the adjacency list. Adds it to the appropriate bucket
// based on its sort cost.
void AdjacencyList::Add(EdgeLabel* edgelabel) {
  if (edgelabel->sortcost() < currentcost_) {
    currentbucket_->push_front(edgelabel);
  } else {
    Bucket(edgelabel->sortcost()).push_back(edgelabel);
  }
}

/**
 * The specified edge label now has a smaller cost.  Reorders it in
 * the sorted list.
 * @param   edgelabel  Directed edge to reorder in the adjacency list
 * @param   previouscost Previous cost.
 */
void AdjacencyList::DecreaseCost(EdgeLabel* edgelabel,
                                 const unsigned int previouscost) {
  // Get the bucket the edge label currently is in. Protect against
  // previous cost less than current cost
  std::list<EdgeLabel*>& previousbucket =
      (previouscost < currentcost_) ?
          Bucket(currentcost_) : Bucket(previouscost);

  // If less than current cost add to the front of the current bucket
  unsigned int cost = edgelabel->sortcost();
  if (cost < currentcost_) {
    // Remove the edge label from the old bucket and push it on the
    // front of the current (so it is the next edge processed)
    previousbucket.remove(edgelabel);
    currentbucket_->push_front(edgelabel);
    return;
  }

  // If the old cost and the new cost are in the same bucket just return
  std::list<EdgeLabel*>& newbucket = Bucket(cost);
  if (previousbucket == newbucket)
    return;

  // Remove the edge label from the old bucket and add to the new bucket
  previousbucket.remove(edgelabel);
  newbucket.push_back(edgelabel);
}

/**
 * Removes the lowest cost edge label from the sorted list.
 * @return  Pointer to the edge label with lowest cost.
 */
EdgeLabel* AdjacencyList::Remove() {
  // If the current bucket is not empty return the edge label off the front
  if (!currentbucket_->empty()) {
    EdgeLabel* edgelabel = currentbucket_->front();
    currentbucket_->pop_front();
    return edgelabel;
  }

  // If current bucket is empty increment until a non-empty low-level
  // bucket is found. If we get to the end of the regular buckets
  // we move edge labels from the overflow buckets into the regular buckets.
  for ( ; currentbucket_ != buckets_.end(); currentbucket_++) {
    // If the current bucket is not empty get the first edge label off the list
    if (!currentbucket_->empty()) {
      EdgeLabel* edgelabel = currentbucket_->front();
      currentbucket_->pop_front();
      return edgelabel;
    }
    currentcost_ += bucketsize_;
  }

  // If no edge labels are in the overflow buckets, there are no more entries
  if (overflowbucket_.empty())
    return nullptr;

  // No edge labels in the low level buckets.  Move edge labels from the
  // overflow bucket to the low level buckets. Then find smallest bucket
  // that is not empty
  EmptyOverflow();
  for (currentbucket_ = buckets_.begin(); currentbucket_ != buckets_.end();
      currentbucket_++) {
    // If current bucket is not empty get the first edge label off the list
    if (!currentbucket_->empty()) {
      EdgeLabel* edgelabel = currentbucket_->front();
      currentbucket_->pop_front();
      return edgelabel;
    }
    currentcost_ += bucketsize_;
  }
  return nullptr;
}

// Returns the bucket given the cost
std::list<EdgeLabel*>& AdjacencyList::Bucket(const unsigned int cost) {
  return
      (cost < maxcost_) ?
          buckets_[((cost - mincost_) / bucketsize_)] : overflowbucket_;
}

// Empties the overflow bucket by placing the edgelabels into the
// low level buckets.
void AdjacencyList::EmptyOverflow() {
  bool found = false;
  unsigned int cost;
  EdgeLabel* edgelabel;
  std::vector<EdgeLabel*> tmp;
  while (!found && !overflowbucket_.empty()) {
    // Adjust cost range
    mincost_ += bucketrange_;
    maxcost_ += bucketrange_;
    currentcost_ = mincost_;

    tmp.clear();
    while (!overflowbucket_.empty()) {
      edgelabel = overflowbucket_.front();
      overflowbucket_.pop_front();
      cost = edgelabel->sortcost();
      if (cost < maxcost_) {
        buckets_[((cost - mincost_) / bucketsize_)].push_back(edgelabel);
        found = true;
      } else {
        tmp.push_back(edgelabel);
      }
    }

    // Clear overflow and add any edge labels that lie outside the new range
    overflowbucket_.clear();
    for (auto edgelabel : tmp) {
      overflowbucket_.push_back(edgelabel);
    }
  }
}

}
}

<|endoftext|>


<commit_before>//
// File:   template.cc
// Author: ruehle
//
// Created on June 8, 2008, 10:41 PM
//

#include <math.h>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <topologyreader.h>
#include <libversion.h>
#include "cgengine.h"

using namespace std;

using boost::format;

void WriteAtoms(ostream &out, Molecule &cg)
{
    out << "[atoms]\n";
    out << "; nr type resnr residue atom cgnr charge mass\n";
    for(int i=0; i<cg.BeadCount(); ++i) {
        Bead *b=cg.getBead(i);

        out << format("%d A 1 RES %s 1 %f %f\n")
            % (i+1) % b->getName() % b->getQ() % b->getM();
    }
    out << endl;
}

void WriteInteractions(ostream &out, Molecule &cg)
{
    int nb=-1;

    Interaction *ic;
    vector<Interaction *>::iterator iter;

    InteractionContainer &ics=cg.getParent()->BondedInteractions();

    for(iter=ics.begin(); iter!=ics.end(); ++iter) {
        ic = *iter;
        if(ic->getMolecule() != cg.getId()) continue;
        if(nb != ic->BeadCount()) {
            nb=ic->BeadCount();
            switch(nb) {
                case 2:
                    out << "\n[ bonds ]\n";
                    break;
                case 3:
                    out << "\n[ angles ]\n";
                    break;
                case 4:
                    out << "\n[ dihedrals ]\n";
                    break;
                default:
                    throw runtime_error(string("cannot handle number of beads in interaction:") +
                            ic->getName());
            }
        }
        for(int i=0; i<nb; ++i)
            out << ic->getBeadId(i)+1 << " ";
        out << "  1  ; " << ic->getName() << endl;
    }
}

void WriteMolecule(ostream &out, Molecule &cg)
{
    out << "[ moleculetype ]\n";
    out << cg.getName() << " 3\n\n";

    WriteAtoms(out, cg);
    WriteInteractions(out, cg);
}

int main(int argc, char** argv)
{
    // initialize the readers/writers,
    // this will be combined in an initialize function later
    //    TrajectoryReader::RegisterPlugins();
    TopologyReader::RegisterPlugins();

    // lets read in some program options
    namespace po = boost::program_options;

    // Declare the supported options.
    po::options_description desc("Allowed options");

    // let cg_engine add some program options
    desc.add_options()
    ("help", "produce this help message")
    //("version", "show version info")
    ("top", boost::program_options::value<string>(), "atomistic topology file")
    ("cg", boost::program_options::value<string>(), "coarse grained mapping")
    ("out", boost::program_options::value<string>(), "output topology (will create .top and in future also .itp)");

    // now read in the command line
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    // does the user want help?
    if (vm.count("help")) {
        cout << "csg_gmxtopol, lib version " << LIB_VERSION_STR << "\n\n";
        cout << desc << endl;
        return 0;
    }

    if(!vm.count("cg")) {
        cout << "no mapping specified\n";
        return 0;
    }

    if(!vm.count("out")) {
        cout << "no output topology specified\n";
        return 0;
    }

    if(!vm.count("top")) {
        cout << "no topology specified\n";
        return 0;
    }

    // try to run the cg process, go through the frames, etc...
    try {
        Topology top;
        Topology top_cg;
        CGEngine cg_engine;

        TopologyReader *reader;
        TopologyMap *map;

        reader = TopReaderFactory().Create(vm["top"].as<string>());
        if(reader == NULL)
            throw string("input format not supported: ") + vm["top"].as<string>();

        reader->ReadTopology(vm["top"].as<string>(), top);
        cout << "I have " << top.BeadCount() << " beads in " << top.MoleculeCount() << " molecules" << endl;

        cg_engine.LoadMoleculeType(vm["cg"].as<string>());
        map = cg_engine.CreateCGTopology(top, top_cg);

        cout << "I have " << top_cg.BeadCount() << " beads in " << top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;

        if(top.MoleculeCount() > 1)
                cout << "WARNING: cannot create topology for topology with"
                "multiple molecules, using only first molecule\n";
        map->Apply();
	ofstream fl;
        fl.open((vm["out"].as<string>() + ".top").c_str());

	WriteMolecule(fl, *top_cg.MoleculeByIndex(0));
        fl.close();
    }
    // did an error occour?
    catch(string error) {
        cerr << "An error occoured!" << endl << error << endl;
    }
    return 0;
}

<commit_msg>fixed two bugs in output, masses are still wrong<commit_after>//
// File:   template.cc
// Author: ruehle
//
// Created on June 8, 2008, 10:41 PM
//

#include <math.h>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <topologyreader.h>
#include <libversion.h>
#include "cgengine.h"

using namespace std;

using boost::format;

void WriteAtoms(ostream &out, Molecule &cg)
{
    out << "[atoms]\n";
    out << "; nr type resnr residue atom cgnr charge mass\n";
    for(int i=0; i<cg.BeadCount(); ++i) {
        Bead *b=cg.getBead(i);

        out << format("%d %s 1 RES %s %d %f %f\n")
            % (i+1) % b->getType()->getName() % b->getName() % (i+1) % b->getQ() % b->getM();
    }
    out << endl;
}

void WriteInteractions(ostream &out, Molecule &cg)
{
    int nb=-1;

    Interaction *ic;
    vector<Interaction *>::iterator iter;

    InteractionContainer &ics=cg.getParent()->BondedInteractions();

    for(iter=ics.begin(); iter!=ics.end(); ++iter) {
        ic = *iter;
        if(ic->getMolecule() != cg.getId()) continue;
        if(nb != ic->BeadCount()) {
            nb=ic->BeadCount();
            switch(nb) {
                case 2:
                    out << "\n[ bonds ]\n";
                    break;
                case 3:
                    out << "\n[ angles ]\n";
                    break;
                case 4:
                    out << "\n[ dihedrals ]\n";
                    break;
                default:
                    throw runtime_error(string("cannot handle number of beads in interaction:") +
                            ic->getName());
            }
        }
        for(int i=0; i<nb; ++i)
            out << ic->getBeadId(i)+1 << " ";
        out << "  1  ; " << ic->getName() << endl;
    }
}

void WriteMolecule(ostream &out, Molecule &cg)
{
    out << "[ moleculetype ]\n";
    out << cg.getName() << " 3\n\n";

    WriteAtoms(out, cg);
    WriteInteractions(out, cg);
}

int main(int argc, char** argv)
{
    // initialize the readers/writers,
    // this will be combined in an initialize function later
    //    TrajectoryReader::RegisterPlugins();
    TopologyReader::RegisterPlugins();

    // lets read in some program options
    namespace po = boost::program_options;

    // Declare the supported options.
    po::options_description desc("Allowed options");

    // let cg_engine add some program options
    desc.add_options()
    ("help", "produce this help message")
    //("version", "show version info")
    ("top", boost::program_options::value<string>(), "atomistic topology file")
    ("cg", boost::program_options::value<string>(), "coarse grained mapping")
    ("out", boost::program_options::value<string>(), "output topology (will create .top and in future also .itp)");

    // now read in the command line
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    // does the user want help?
    if (vm.count("help")) {
        cout << "csg_gmxtopol, lib version " << LIB_VERSION_STR << "\n\n";
        cout << desc << endl;
        return 0;
    }

    if(!vm.count("cg")) {
        cout << "no mapping specified\n";
        return 0;
    }

    if(!vm.count("out")) {
        cout << "no output topology specified\n";
        return 0;
    }

    if(!vm.count("top")) {
        cout << "no topology specified\n";
        return 0;
    }

    // try to run the cg process, go through the frames, etc...
    try {
        Topology top;
        Topology top_cg;
        CGEngine cg_engine;

        TopologyReader *reader;
        TopologyMap *map;

        reader = TopReaderFactory().Create(vm["top"].as<string>());
        if(reader == NULL)
            throw string("input format not supported: ") + vm["top"].as<string>();

        reader->ReadTopology(vm["top"].as<string>(), top);
        cout << "I have " << top.BeadCount() << " beads in " << top.MoleculeCount() << " molecules" << endl;

        cg_engine.LoadMoleculeType(vm["cg"].as<string>());
        map = cg_engine.CreateCGTopology(top, top_cg);

        cout << "I have " << top_cg.BeadCount() << " beads in " << top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;

        if(top.MoleculeCount() > 1)
                cout << "WARNING: cannot create topology for topology with"
                "multiple molecules, using only first molecule\n";
        map->Apply();
	ofstream fl;
        fl.open((vm["out"].as<string>() + ".top").c_str());

	WriteMolecule(fl, *top_cg.MoleculeByIndex(0));
        fl.close();
    }
    // did an error occour?
    catch(string error) {
        cerr << "An error occoured!" << endl << error << endl;
    }
    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/tools/spline.h>
#include <votca/tools/cubicspline.h>
#include <votca/tools/akimaspline.h>
#include <votca/tools/linspline.h>
#include <votca/tools/table.h>
#include <votca/tools/tokenizer.h>
#include <boost/program_options.hpp>
#include <iostream>
#include <votca/csg/version.h>

using namespace std;
namespace po = boost::program_options;
using namespace votca::csg;
using namespace votca::tools;

void help_text()
{
    votca::csg::HelpTextHeader("csg_resample");
    cout << "Change grid and interval of any sort of table files.\n"
            "Mainly called internally by inverse script, can also be\n"
            "used to manually prepare input files for coarse-grained\n"
            "simulations.\n\n";
}

void check_option(po::options_description &desc, po::variables_map &vm, const string &option)
{
    if(!vm.count(option)) {
        cout << "csg_resample \n\n";
        cout << desc << endl << "parameter " << option << " is not specified\n";
        exit(1);
    }
}

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

    string in_file, out_file, grid, fitgrid, comment, type, boundaries;
    Spline *spline;
    Table in, out, der;
    // program options
    po::options_description desc("Allowed options");

    desc.add_options()
      ("help", "produce this help message")
      ("in", po::value<string>(&in_file), "table to read")
      ("out", po::value<string>(&out_file), "table to write")
      ("derivative", po::value<string>(), "table to write")
      ("grid", po::value<string>(&grid), "new grid spacing (min:step:max). If 'grid' is specified only, interpolation is performed.")
      ("type", po::value<string>(&type)->default_value("akima"), "[cubic|akima|linear]. If option is not specified, the default type 'akima' is assumed.")
      ("fitgrid", po::value<string>(&fitgrid), "specify fit grid (min:step:max). If 'grid' and 'fitgrid' are specified, a fit is performed.")
      ("nocut", "Option for fitgrid: Normally, values out of fitgrid boundaries are cut off. If they shouldn't, choose --nocut.")
      ("comment", po::value<string>(&comment), "store a comment in the output table")
      ("boundaries", po::value<string>(&boundaries), "(natural|periodic|derivativezero) sets boundary conditions");

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch(po::error err) {
        cout << "error parsing command line: " << err.what() << endl;
        return -1;
    }

    // does the user want help?
    if (vm.count("help")) {
        help_text();
        cout << desc << endl;
        return 0;
    }

    check_option(desc, vm, "in");
    check_option(desc, vm, "out");

    if(!(vm.count("grid") || vm.count("fitgrid"))) {
            cout << "Need grid for interpolation or fitgrid for fit.\n";
            return 1;
    }

    if((!vm.count("grid")) && vm.count("fitgrid")) {
            cout << "Need a grid for fitting as well.\n";
            return 1;
    }

    double min, max, step;
    {
        Tokenizer tok(grid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format, use min:step:max\n";
            return 1;
        }
        min = boost::lexical_cast<double>(toks[0]);
        step = boost::lexical_cast<double>(toks[1]);
        max = boost::lexical_cast<double>(toks[2]);
    }

    in.Load(in_file);

    if (vm.count("type")) {
        if(type=="cubic") {
            spline = new CubicSpline();
        }
        else if(type=="akima") {
            spline = new AkimaSpline();
        }
        else if(type=="linear") {
            spline = new LinSpline();
        }
        else {
            throw std::runtime_error("unknown type");
        }
    }
    spline->setBC(Spline::splineNormal);

    if (vm.count("boundaries")) {
        if(boundaries=="periodic") {
            spline->setBC(Spline::splinePeriodic);
        }
        if(boundaries=="derivativezero") {
            spline->setBC(Spline::splineDerivativeZero);
        }
        //default: normal
    }

    // in case fit is specified
    if (vm.count("fitgrid")) {
        Tokenizer tok(fitgrid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format in fitgrid, use min:step:max\n";
            return 1;
        }
        double sp_min, sp_max, sp_step;
        sp_min = boost::lexical_cast<double>(toks[0]);
        sp_step = boost::lexical_cast<double>(toks[1]);
        sp_max = boost::lexical_cast<double>(toks[2]);
        cout << "doing " << type << " fit " << sp_min << ":" << sp_step << ":" << sp_max << endl;

        // cut off any values out of fitgrid boundaries (exception: do nothing in case of --nocut)
        ub::vector<double> x_copy;
        ub::vector<double> y_copy;
        if (!vm.count("nocut")) {
            // determine vector size
            int minindex=-1, maxindex;
            for (size_t i=0; i<in.x().size(); i++) {
                if(in.x(i)<sp_min) {
                    minindex = i;
                }
                if(in.x(i)<sp_max) {
                    maxindex = i;
                }
            }
            // copy data values in [sp_min,sp_max] into new vectors
            minindex++;
            x_copy = ub::zero_vector<double>(maxindex-minindex+1);
            y_copy = ub::zero_vector<double>(maxindex-minindex+1);
            for (int i=minindex; i<=maxindex; i++) {
                x_copy(i-minindex) = in.x(i);
                y_copy(i-minindex) = in.y(i);
            }
        }

        // fitting
        spline->GenerateGrid(sp_min, sp_max, sp_step);
        try {
            if (vm.count("nocut")) {
                spline->Fit(in.x(), in.y());
            } else {
                spline->Fit(x_copy, y_copy);
            }
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while fitting.");
        }
    } else {
        // otherwise do interpolation (default = cubic)
        try {
            spline->Interpolate(in.x(), in.y());
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while interpolating.");
        }
    }

    out.GenerateGridSpacing(min, max, step);
    spline->Calculate(out.x(), out.y());

    //store a comment line
    if (vm.count("comment")){
        out.set_comment(comment);
    }
    out.y() = out.y();
    out.flags() = ub::scalar_vector<double>(out.flags().size(), 'o');

    int i=0;
    for(i=0; out.x(i) < in.x(0) && i<out.size(); ++i);

    int j=0;
    for(;i < out.size(); ++i) {
        for(; j < in.size(); ++j)
            if(in.x(j) >= out.x(i)  || fabs(in.x(j)-out.x(i) ) < 1e-12) // fix for precison errors
                break;
        if(in.size() == j) break;
        out.flags(i) = in.flags(j);
    }

    out.Save(out_file);

    if (vm.count("derivative")) {
        der.GenerateGridSpacing(min, max, step);
        der.flags() = ub::scalar_vector<double>(der.flags().size(), 'o');

        spline->CalculateDerivative(der.x(), der.y());

        der.Save(vm["derivative"].as<string>());
    }

    delete spline;
    return 0;
}

<commit_msg>added catch to csg_resample (fixes issue 80)<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/tools/spline.h>
#include <votca/tools/cubicspline.h>
#include <votca/tools/akimaspline.h>
#include <votca/tools/linspline.h>
#include <votca/tools/table.h>
#include <votca/tools/tokenizer.h>
#include <boost/program_options.hpp>
#include <iostream>
#include <votca/csg/version.h>

using namespace std;
namespace po = boost::program_options;
using namespace votca::csg;
using namespace votca::tools;

void help_text()
{
    votca::csg::HelpTextHeader("csg_resample");
    cout << "Change grid and interval of any sort of table files.\n"
            "Mainly called internally by inverse script, can also be\n"
            "used to manually prepare input files for coarse-grained\n"
            "simulations.\n\n";
}

void check_option(po::options_description &desc, po::variables_map &vm, const string &option)
{
    if(!vm.count(option)) {
        cout << "csg_resample \n\n";
        cout << desc << endl << "parameter " << option << " is not specified\n";
        exit(1);
    }
}

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

    string in_file, out_file, grid, fitgrid, comment, type, boundaries;
    Spline *spline;
    Table in, out, der;
    // program options
    po::options_description desc("Allowed options");

    desc.add_options()
      ("help", "produce this help message")
      ("in", po::value<string>(&in_file), "table to read")
      ("out", po::value<string>(&out_file), "table to write")
      ("derivative", po::value<string>(), "table to write")
      ("grid", po::value<string>(&grid), "new grid spacing (min:step:max). If 'grid' is specified only, interpolation is performed.")
      ("type", po::value<string>(&type)->default_value("akima"), "[cubic|akima|linear]. If option is not specified, the default type 'akima' is assumed.")
      ("fitgrid", po::value<string>(&fitgrid), "specify fit grid (min:step:max). If 'grid' and 'fitgrid' are specified, a fit is performed.")
      ("nocut", "Option for fitgrid: Normally, values out of fitgrid boundaries are cut off. If they shouldn't, choose --nocut.")
      ("comment", po::value<string>(&comment), "store a comment in the output table")
      ("boundaries", po::value<string>(&boundaries), "(natural|periodic|derivativezero) sets boundary conditions");

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch(po::error err) {
        cout << "error parsing command line: " << err.what() << endl;
        return -1;
    }

    try {
    // does the user want help?
    if (vm.count("help")) {
        help_text();
        cout << desc << endl;
        return 0;
    }

    check_option(desc, vm, "in");
    check_option(desc, vm, "out");

    if(!(vm.count("grid") || vm.count("fitgrid"))) {
            cout << "Need grid for interpolation or fitgrid for fit.\n";
            return 1;
    }

    if((!vm.count("grid")) && vm.count("fitgrid")) {
            cout << "Need a grid for fitting as well.\n";
            return 1;
    }

    double min, max, step;
    {
        Tokenizer tok(grid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format, use min:step:max\n";
            return 1;
        }
        min = boost::lexical_cast<double>(toks[0]);
        step = boost::lexical_cast<double>(toks[1]);
        max = boost::lexical_cast<double>(toks[2]);
    }

    in.Load(in_file);

    if (vm.count("type")) {
        if(type=="cubic") {
            spline = new CubicSpline();
        }
        else if(type=="akima") {
            spline = new AkimaSpline();
        }
        else if(type=="linear") {
            spline = new LinSpline();
        }
        else {
            throw std::runtime_error("unknown type");
        }
    }
    spline->setBC(Spline::splineNormal);

    if (vm.count("boundaries")) {
        if(boundaries=="periodic") {
            spline->setBC(Spline::splinePeriodic);
        }
        if(boundaries=="derivativezero") {
            spline->setBC(Spline::splineDerivativeZero);
        }
        //default: normal
    }

    // in case fit is specified
    if (vm.count("fitgrid")) {
        Tokenizer tok(fitgrid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format in fitgrid, use min:step:max\n";
            return 1;
        }
        double sp_min, sp_max, sp_step;
        sp_min = boost::lexical_cast<double>(toks[0]);
        sp_step = boost::lexical_cast<double>(toks[1]);
        sp_max = boost::lexical_cast<double>(toks[2]);
        cout << "doing " << type << " fit " << sp_min << ":" << sp_step << ":" << sp_max << endl;

        // cut off any values out of fitgrid boundaries (exception: do nothing in case of --nocut)
        ub::vector<double> x_copy;
        ub::vector<double> y_copy;
        if (!vm.count("nocut")) {
            // determine vector size
            int minindex=-1, maxindex;
            for (size_t i=0; i<in.x().size(); i++) {
                if(in.x(i)<sp_min) {
                    minindex = i;
                }
                if(in.x(i)<sp_max) {
                    maxindex = i;
                }
            }
            // copy data values in [sp_min,sp_max] into new vectors
            minindex++;
            x_copy = ub::zero_vector<double>(maxindex-minindex+1);
            y_copy = ub::zero_vector<double>(maxindex-minindex+1);
            for (int i=minindex; i<=maxindex; i++) {
                x_copy(i-minindex) = in.x(i);
                y_copy(i-minindex) = in.y(i);
            }
        }

        // fitting
        spline->GenerateGrid(sp_min, sp_max, sp_step);
        try {
            if (vm.count("nocut")) {
                spline->Fit(in.x(), in.y());
            } else {
                spline->Fit(x_copy, y_copy);
            }
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while fitting.");
        }
    } else {
        // otherwise do interpolation (default = cubic)
        try {
            spline->Interpolate(in.x(), in.y());
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while interpolating.");
        }
    }

    out.GenerateGridSpacing(min, max, step);
    spline->Calculate(out.x(), out.y());

    //store a comment line
    if (vm.count("comment")){
        out.set_comment(comment);
    }
    out.y() = out.y();
    out.flags() = ub::scalar_vector<double>(out.flags().size(), 'o');

    int i=0;
    for(i=0; out.x(i) < in.x(0) && i<out.size(); ++i);

    int j=0;
    for(;i < out.size(); ++i) {
        for(; j < in.size(); ++j)
            if(in.x(j) >= out.x(i)  || fabs(in.x(j)-out.x(i) ) < 1e-12) // fix for precison errors
                break;
        if(in.size() == j) break;
        out.flags(i) = in.flags(j);
    }

    out.Save(out_file);

    if (vm.count("derivative")) {
        der.GenerateGridSpacing(min, max, step);
        der.flags() = ub::scalar_vector<double>(der.flags().size(), 'o');

        spline->CalculateDerivative(der.x(), der.y());

        der.Save(vm["derivative"].as<string>());
    }

    delete spline;
	}
    catch(std::exception &error) {
         cerr << "an error occurred:\n" << error.what() << endl;
         return -1;
    }
    return 0;
}

<|endoftext|>


<commit_before>#include "hext/NegateTest.h"

#include <algorithm>
#include <utility>

namespace hext {

NegateTest::NegateTest(std::unique_ptr<ValueTest> test) noexcept
: test_(std::move(test))  // noexcept
{
}

NegateTest::~NegateTest() = default;
NegateTest::NegateTest(NegateTest&& other) = default;

NegateTest::NegateTest(const NegateTest& other)
: test_(other.test_ ? other.test_->clone() : nullptr)
{
}

NegateTest& NegateTest::operator=(NegateTest&& other) = default;

NegateTest& NegateTest::operator=(const NegateTest& other)
{
  using std::swap;
  NegateTest tmp(other);
  swap(*this, tmp);
  return *this;
}

bool NegateTest::test(const char * subject) const
{
  if( this->test_ )
    return !this->test_->test(subject);
  else
    return subject == nullptr;
}

} // namespace hext

<commit_msg>NegateTest: do not name parameters in default generated methods to hide warning -Wunused-parameter<commit_after>#include "hext/NegateTest.h"

#include <algorithm>
#include <utility>

namespace hext {

NegateTest::NegateTest(std::unique_ptr<ValueTest> test) noexcept
: test_(std::move(test))  // noexcept
{
}

NegateTest::~NegateTest() = default;
NegateTest::NegateTest(NegateTest&&) = default;

NegateTest::NegateTest(const NegateTest& other)
: test_(other.test_ ? other.test_->clone() : nullptr)
{
}

NegateTest& NegateTest::operator=(NegateTest&&) = default;

NegateTest& NegateTest::operator=(const NegateTest& other)
{
  using std::swap;
  NegateTest tmp(other);
  swap(*this, tmp);
  return *this;
}

bool NegateTest::test(const char * subject) const
{
  if( this->test_ )
    return !this->test_->test(subject);
  else
    return subject == nullptr;
}

} // namespace hext

<|endoftext|>


<commit_before>/*
    pluginloader.cpp - Kopete Plugin Loader

    Copyright (c) 2002 by Duncan Mac-Vicar Prett       <duncan@kde.org>

    Portions of this code based in Noatun plugin code:
    Copyright (c) 2000-2002 The Noatun Developers

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

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

#include "pluginloader.h"

#include <qapplication.h>
#include <qdir.h>
#include <qfile.h>

#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <knotifyclient.h>
#include <kparts/componentfactory.h>
#include <ksimpleconfig.h>
#include <kstaticdeleter.h>
#include <kstddirs.h>
#include <kurl.h>

#include "kopeteplugin.h"

class KopeteLibraryInfo;

// Put the static deleter in its anonymous namespace
namespace
{
	KStaticDeleter<LibraryLoader> sd;
}

bool operator ==(const KopeteLibraryInfo &a, const KopeteLibraryInfo &b)
{
	// Feels like cheating, doesn't it?
	return a.specfile == b.specfile;
}

LibraryLoader* LibraryLoader::s_pluginLoader = 0L;

LibraryLoader* LibraryLoader::pluginLoader()
{
	if( !s_pluginLoader )
		sd.setObject( s_pluginLoader, new LibraryLoader() );

	return s_pluginLoader;
}

LibraryLoader::LibraryLoader()
: QObject( qApp )
{
}

LibraryLoader::~LibraryLoader()
{
	QDictIterator<KopetePlugin> i( mLibHash );
	while( i.current() )
	{
		// Remove causes the iterator to auto-increment, so
		// only increment explicitly when not removing
		if( getInfo( i.currentKey() ).type != "protocol" )
			remove( i.current() );
		else
			++i;
	}
	i.toFirst();
	while( i.current() )
		remove( i.current() );
}

QPtrList<KopetePlugin> LibraryLoader::plugins() const
{
	QPtrList<KopetePlugin> list;
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
		list.append( i.current() );

	return list;
}

QValueList<KopeteLibraryInfo> LibraryLoader::loaded() const
{
	QValueList<KopeteLibraryInfo> items;

	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( mLibHash[ i.currentKey() ] )
			items.append( getInfo( i.currentKey() ) );
	}

	return items;
}

bool LibraryLoader::loadAll()
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	QStringList modules = config->readListEntry("Modules");

	// Session management...
/*
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("sm"))
			continue;
		loadPlugin( *i );
	}
*/
	// load all the protocols in the first
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("protocol"))
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug() << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	// load all misc plugins
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("other"))
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug() << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	return true;
}

KopeteLibraryInfo LibraryLoader::getInfo(const QString &spec) const
{
	QMap<QString, KopeteLibraryInfo>::iterator cached = m_cachedInfo.find(spec);
	if (cached != m_cachedInfo.end() )
		return *cached;

	KopeteLibraryInfo info;
	QString specPath = ( spec[ 0 ] == '/' ) ? spec : KGlobal::dirs()->findResource( "appdata", spec );
	if( !QFile::exists( specPath ) )
		return info;

	KSimpleConfig file( specPath );
	if( spec.find( '/' ) >= 0 )
		info.specfile = KURL( spec ).fileName();
	else
		info.specfile = spec;

	info.filename = file.readEntry( "Filename" );
	info.author   = file.readEntry( "Author" );
	info.site     = file.readEntry( "Site" );
	info.email    = file.readEntry( "Email" );
	info.type     = file.readEntry( "Type" );
	info.name     = file.readEntry( "Name" );
	info.comment  = file.readEntry( "Comment" );
	info.license  = file.readEntry( "License" );
	info.icon     = file.readEntry( "Icon" );

	m_cachedInfo[ spec ] = info;
	return info;
}

bool LibraryLoader::isLoaded( const QString &spec ) const
{
	KopetePlugin *p = mLibHash[ spec ];
	return p;
}

void LibraryLoader::setModules(const QStringList &mods)
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	config->writeEntry("Modules", mods);
	KGlobal::config()->sync();
}

QValueList<KopeteLibraryInfo> LibraryLoader::available() const
{
	QValueList<KopeteLibraryInfo> items;
	QStringList files=KGlobal::dirs()->findAllResources("appdata", "*.plugin", false, true);
	for (QStringList::Iterator i=files.begin(); i!=files.end(); ++i)
		items.append(getInfo(*i));

	return items;
}

bool LibraryLoader::loadPlugin( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
	{
		KopeteLibraryInfo info = getInfo( spec );
		if( info.specfile != spec )
			return false;

		// Get the library loader instance
		KLibLoader *loader = KLibLoader::self();

		KLibrary *lib = loader->library( QFile::encodeName( info.filename) );
		if( !lib )
		{
			kdDebug() << "LibraryLoader::loadPlugin: Error while loading plugin: " << loader->lastErrorMessage() << endl;
			return false;
		}
		plugin = KParts::ComponentFactory::createInstanceFromFactory<KopetePlugin> ( lib->factory(), this );
		mLibHash.insert( spec, plugin );

		connect( plugin, SIGNAL( destroyed( QObject * ) ),
			SLOT( slotPluginDestroyed( QObject * ) ) );

		// Automatically load the i18n catalogue for the plugin
		KGlobal::locale()->insertCatalogue( info.filename );

		plugin->init();

		m_addressBookFields.insert( plugin, plugin->addressBookFields() );

		kdDebug() << "LibraryLoader::loadPlugin: Successfully loaded plugin '" << spec << "'."<< endl;
		emit pluginLoaded( plugin );
		return true;
	}
	else
	{
		kdDebug() << "LibraryLoader::loadPlugin: Plugin '" << spec << "' is already loaded!" << endl;
		return false;
	}
}

bool LibraryLoader::remove( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
		return false;

	remove( plugin );
	return true;
}

bool LibraryLoader::remove( KopetePlugin *p )
{
	if( !p )
		return false;

	// Added by Duncan 20/01/2002
	// We need to call unload function for the plugin
	p->unload();
	delete p;

	return false;
}

void LibraryLoader::slotPluginDestroyed( QObject *o )
{
	m_addressBookFields.remove( static_cast<KopetePlugin *>( o ) );

	QDictIterator<KopetePlugin> it( mLibHash );
	for( ; it.current() && it.current() == o; ++it )
	{
		mLibHash.remove( it.currentKey() );
		break;
	}

	// FIXME: Most likely most data structures here leak and are bound
	// to cause crashes. Find and identify those.
}

QStringList LibraryLoader::addressBookFields( KopetePlugin *p ) const
{
	if( m_addressBookFields.contains( p ) )
		return m_addressBookFields[ p ];
	else
		return QStringList();
}

KopetePlugin * LibraryLoader::searchByName(const QString &name)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (getInfo(i.currentKey()).name==name)
			return (*i);
	}
	return 0L;
}

QString LibraryLoader::pluginIcon( const QString &pluginId ) const
{
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( i.currentKey() == pluginId );
			return getInfo( i.currentKey() ).icon;
	}

	return QString::null;
}

#include <pluginloader.moc>

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>adding debug while removing plugins could be handy later when a certain plugin crashes<commit_after>/*
    pluginloader.cpp - Kopete Plugin Loader

    Copyright (c) 2002 by Duncan Mac-Vicar Prett       <duncan@kde.org>

    Portions of this code based in Noatun plugin code:
    Copyright (c) 2000-2002 The Noatun Developers

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

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

#include "pluginloader.h"

#include <qapplication.h>
#include <qdir.h>
#include <qfile.h>

#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <knotifyclient.h>
#include <kparts/componentfactory.h>
#include <ksimpleconfig.h>
#include <kstaticdeleter.h>
#include <kstddirs.h>
#include <kurl.h>

#include "kopeteplugin.h"

class KopeteLibraryInfo;

// Put the static deleter in its anonymous namespace
namespace
{
	KStaticDeleter<LibraryLoader> sd;
}

bool operator ==(const KopeteLibraryInfo &a, const KopeteLibraryInfo &b)
{
	// Feels like cheating, doesn't it?
	return a.specfile == b.specfile;
}

LibraryLoader* LibraryLoader::s_pluginLoader = 0L;

LibraryLoader* LibraryLoader::pluginLoader()
{
	if( !s_pluginLoader )
		sd.setObject( s_pluginLoader, new LibraryLoader() );

	return s_pluginLoader;
}

LibraryLoader::LibraryLoader()
: QObject( qApp )
{
}

LibraryLoader::~LibraryLoader()
{
	QDictIterator<KopetePlugin> i( mLibHash );
	while( i.current() )
	{
		// Remove causes the iterator to auto-increment, so
		// only increment explicitly when not removing
		if( getInfo( i.currentKey() ).type != "protocol" )
		{
			kdDebug() << "LibraryLoader::~LibraryLoader(): removing plugin: " << getInfo( i.currentKey() ).name << endl;
			remove( i.current() );
		}
		else
			++i;
	}
	i.toFirst();
	while( i.current() )
	{
		kdDebug() << "LibraryLoader::~LibraryLoader(): removing protocol: " << getInfo( i.currentKey() ).name << endl;
		remove( i.current() );
	}

	kdDebug() << "LibraryLoader::~LibraryLoader(): all plugins removed" << endl;
}

QPtrList<KopetePlugin> LibraryLoader::plugins() const
{
	QPtrList<KopetePlugin> list;
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
		list.append( i.current() );

	return list;
}

QValueList<KopeteLibraryInfo> LibraryLoader::loaded() const
{
	QValueList<KopeteLibraryInfo> items;

	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( mLibHash[ i.currentKey() ] )
			items.append( getInfo( i.currentKey() ) );
	}

	return items;
}

bool LibraryLoader::loadAll()
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	QStringList modules = config->readListEntry("Modules");

	// Session management...
/*
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("sm"))
			continue;
		loadPlugin( *i );
	}
*/
	// load all the protocols in the first
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("protocol"))
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug() << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	// load all misc plugins
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("other"))
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug() << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	return true;
}

KopeteLibraryInfo LibraryLoader::getInfo(const QString &spec) const
{
	QMap<QString, KopeteLibraryInfo>::iterator cached = m_cachedInfo.find(spec);
	if (cached != m_cachedInfo.end() )
		return *cached;

	KopeteLibraryInfo info;
	QString specPath = ( spec[ 0 ] == '/' ) ? spec : KGlobal::dirs()->findResource( "appdata", spec );
	if( !QFile::exists( specPath ) )
		return info;

	KSimpleConfig file( specPath );
	if( spec.find( '/' ) >= 0 )
		info.specfile = KURL( spec ).fileName();
	else
		info.specfile = spec;

	info.filename = file.readEntry( "Filename" );
	info.author   = file.readEntry( "Author" );
	info.site     = file.readEntry( "Site" );
	info.email    = file.readEntry( "Email" );
	info.type     = file.readEntry( "Type" );
	info.name     = file.readEntry( "Name" );
	info.comment  = file.readEntry( "Comment" );
	info.license  = file.readEntry( "License" );
	info.icon     = file.readEntry( "Icon" );

	m_cachedInfo[ spec ] = info;
	return info;
}

bool LibraryLoader::isLoaded( const QString &spec ) const
{
	KopetePlugin *p = mLibHash[ spec ];
	return p;
}

void LibraryLoader::setModules(const QStringList &mods)
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	config->writeEntry("Modules", mods);
	KGlobal::config()->sync();
}

QValueList<KopeteLibraryInfo> LibraryLoader::available() const
{
	QValueList<KopeteLibraryInfo> items;
	QStringList files=KGlobal::dirs()->findAllResources("appdata", "*.plugin", false, true);
	for (QStringList::Iterator i=files.begin(); i!=files.end(); ++i)
		items.append(getInfo(*i));

	return items;
}

bool LibraryLoader::loadPlugin( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
	{
		KopeteLibraryInfo info = getInfo( spec );
		if( info.specfile != spec )
			return false;

		// Get the library loader instance
		KLibLoader *loader = KLibLoader::self();

		KLibrary *lib = loader->library( QFile::encodeName( info.filename) );
		if( !lib )
		{
			kdDebug() << "LibraryLoader::loadPlugin: Error while loading plugin: " << loader->lastErrorMessage() << endl;
			return false;
		}
		plugin = KParts::ComponentFactory::createInstanceFromFactory<KopetePlugin> ( lib->factory(), this );
		mLibHash.insert( spec, plugin );

		connect( plugin, SIGNAL( destroyed( QObject * ) ),
			SLOT( slotPluginDestroyed( QObject * ) ) );

		// Automatically load the i18n catalogue for the plugin
		KGlobal::locale()->insertCatalogue( info.filename );

		plugin->init();

		m_addressBookFields.insert( plugin, plugin->addressBookFields() );

		kdDebug() << "LibraryLoader::loadPlugin: Successfully loaded plugin '" << spec << "'."<< endl;
		emit pluginLoaded( plugin );
		return true;
	}
	else
	{
		kdDebug() << "LibraryLoader::loadPlugin: Plugin '" << spec << "' is already loaded!" << endl;
		return false;
	}
}

bool LibraryLoader::remove( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
		return false;

	remove( plugin );
	return true;
}

bool LibraryLoader::remove( KopetePlugin *p )
{
	if( !p )
		return false;

	// Added by Duncan 20/01/2002
	// We need to call unload function for the plugin
	p->unload();
	delete p;

	return false;
}

void LibraryLoader::slotPluginDestroyed( QObject *o )
{
	m_addressBookFields.remove( static_cast<KopetePlugin *>( o ) );

	QDictIterator<KopetePlugin> it( mLibHash );
	for( ; it.current() && it.current() == o; ++it )
	{
		mLibHash.remove( it.currentKey() );
		break;
	}

	// FIXME: Most likely most data structures here leak and are bound
	// to cause crashes. Find and identify those.
}

QStringList LibraryLoader::addressBookFields( KopetePlugin *p ) const
{
	if( m_addressBookFields.contains( p ) )
		return m_addressBookFields[ p ];
	else
		return QStringList();
}

KopetePlugin * LibraryLoader::searchByName(const QString &name)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (getInfo(i.currentKey()).name==name)
			return (*i);
	}
	return 0L;
}

QString LibraryLoader::pluginIcon( const QString &pluginId ) const
{
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( i.currentKey() == pluginId );
			return getInfo( i.currentKey() ).icon;
	}

	return QString::null;
}

#include <pluginloader.moc>

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>/*
 * Summary: C++ interface for memcached server
 *
 * Copy: See Copyright for the status of this software.
 *
 * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
 *          Patrick Galbraith <patg@patg.net>
 */

/**
 * @file memcached.hpp
 * @brief Libmemcached C++ interface
 */

#ifndef LIBMEMCACHEDPP_H
#define LIBMEMCACHEDPP_H

#include <libmemcached/memcached.h>

#include <string.h>

#include <string>
#include <vector>
#include <map>

namespace memcache
{

/**
 * This is the core memcached library (if later, other objects
 * are needed, they will be created from this class).
 */
class Memcache
{
public:

  Memcache()
    :
      memc(),
      result()
  {
    memcached_create(&memc);
  }

  Memcache(memcached_st *clone)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, clone);
  }

  Memcache(const Memcache &rhs)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
  }

  ~Memcache()
  {
    memcached_free(&memc);
  }

  /**
   * Get the internal memcached_st *
   */
  memcached_st &getImpl()
  {
    return memc;
  }

  /**
   * Get the internal memcached_st *
   */
  const memcached_st &getImpl() const
  {
    return memc;
  }

  /**
   * Return an error string for the given return structure.
   *
   * @param[in] rc a memcached_return structure
   * @return error string corresponding to given return code in the library.
   */
  const std::string getError(memcached_return rc) const
  {
    /* first parameter to strerror is unused */
    return memcached_strerror(NULL, rc);
  }

  /**
   * Fetches an individual value from the server.
   *
   * @param[in] key key of object to fetch
   * @param[out] ret_val store returned object in this vector
   * @return true on success; false on failure
   */
  bool fetch(std::string &key,
             std::vector<char> &ret_val)
  {
    char ret_key[MEMCACHED_MAX_KEY];
    size_t value_length= 0;
    size_t key_length= 0;
    memcached_return rc;
    uint32_t flags= 0;
    char *value= memcached_fetch(&memc, ret_key, &key_length,
                                 &value_length, &flags, &rc);
    if (value && ret_val.empty())
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
      key.assign(ret_key);
      return true;
    }
    return false;
  }

  std::vector<char> &get(const std::string &key,
                         std::vector<char> &ret_val)
  {
    uint32_t flags= 0;
    memcached_return rc;
    size_t value_length= 0;

    if (key.empty())
    {
      return ret_val;
    }
    char *value= memcached_get(&memc, key.c_str(), key.length(),
                               &value_length, &flags, &rc);
    if (value != NULL && ret_val.empty())
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
    }
    return ret_val;
  }

  std::vector<char> &getByKey(const std::string &master_key,
                              const std::string &key,
                              std::vector<char> &ret_val)
  {
    uint32_t flags= 0;
    memcached_return rc;
    size_t value_length= 0;

    if (master_key.empty() || key.empty())
    {
      return ret_val;
    }
    char *value= memcached_get_by_key(&memc,
                                      master_key.c_str(), master_key.length(),
                                      key.c_str(), key.length(),
                                      &value_length, &flags, &rc);
    if (value)
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
    }
    return ret_val;
  }

  bool mget(std::vector<std::string> &keys)
  {
    std::vector<const char *> real_keys;
    std::vector<size_t> key_len;
    /*
     * Construct an array which will contain the length
     * of each of the strings in the input vector. Also, to
     * interface with the memcached C API, we need to convert
     * the vector of std::string's to a vector of char *.
     */
    real_keys.reserve(keys.size());
    key_len.reserve(keys.size());

    std::vector<std::string>::iterator it= keys.begin();

    while (it != keys.end())
    {
      real_keys.push_back(const_cast<char *>((*it).c_str()));
      key_len.push_back((*it).length());
      ++it;
    }

    /*
     * If the std::vector of keys is empty then we cannot
     * call memcached_mget as we will get undefined behavior.
     */
    if (! real_keys.empty())
    {
      memcached_return rc= memcached_mget(&memc, &real_keys[0], &key_len[0],
                                          real_keys.size());
      return (rc == MEMCACHED_SUCCESS);
    }

    return false;
  }

  bool set(const std::string &key,
           const std::vector<char> &value,
           time_t expiration,
           uint32_t flags)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_set(&memc,
                                       key.c_str(), key.length(),
                                       &value[0], value.size(),
                                       expiration, flags);
    return (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
  }

  bool setAll(std::vector<std::string> &keys,
              std::vector< std::vector<char> *> &values,
              time_t expiration,
              uint32_t flags)
  {
    if (keys.size() != values.size())
    {
      return false;
    }
    bool retval= true;
    std::vector<std::string>::iterator key_it= keys.begin();
    std::vector< std::vector<char> *>::iterator val_it= values.begin();
    while (key_it != keys.end())
    {
      retval= set((*key_it), *(*val_it), expiration, flags);
      if (retval == false)
      {
        return retval;
      }
      ++key_it;
      ++val_it;
    }
    return retval;
  }

  bool setAll(std::map<const std::string, std::vector<char> > key_value_map,
              time_t expiration,
              uint32_t flags)
  {
    if (key_value_map.empty())
    {
      return false;
    }
    bool retval= true;
    std::map<const std::string, std::vector<char> >::iterator it=
      key_value_map.begin();
    while (it != key_value_map.end())
    {
      retval= set(it->first, it->second, expiration, flags);
      if (retval == false)
      {
        return false;
      }
      ++it;
    }
    return true;
  }

  bool setByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value,
                time_t expiration,
                uint32_t flags)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(), key.length(),
                                              &value[0], value.size(),
                                              expiration,
                                              flags);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool increment(const std::string &key, unsigned int offset, uint64_t *value)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool decrement(const std::string &key, unsigned int offset, uint64_t *value)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_decrement(&memc, key.c_str(),
                                             key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
                                       &value[0], value.size(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool addByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_add_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              &value[0],
                                              value.size(),
                                              0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
                                           &value[0], value.size(),
                                           0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replaceByKey(const std::string &master_key,
                    const std::string &key,
                    const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_replace_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  &value[0],
                                                  value.size(),
                                                  0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
                                           &value[0], value.size(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prependByKey(const std::string &master_key,
                    const std::string &key,
                    const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_prepend_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  &value[0],
                                                  value.size(),
                                                  0,
                                                  0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_append(&memc,
                                          key.c_str(),
                                          key.length(),
                                          &value[0],
                                          value.size(),
                                          0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool appendByKey(const std::string &master_key,
                   const std::string &key,
                   const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_append_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 &value[0],
                                                 value.size(),
                                                 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas(const std::string &key,
           const std::vector<char> &value,
           uint64_t cas_arg)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
                                       &value[0], value.size(),
                                       0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool casByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value,
                uint64_t cas_arg)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_cas_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              &value[0],
                                              value.size(),
                                              0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool remove(const std::string &key)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool removeByKey(const std::string &master_key,
                   const std::string &key)
  {
    if (master_key.empty() || key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_delete_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool flush(time_t expiration)
  {
    memcached_return rc= memcached_flush(&memc, expiration);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool fetchExecute(memcached_execute_function *callback,
                    void *context,
                    unsigned int num_of_callbacks)
  {
    memcached_return rc= memcached_fetch_execute(&memc,
                                                 callback,
                                                 context,
                                                 num_of_callbacks);
    return (rc == MEMCACHED_SUCCESS);
  }

  /**
   * Get the library version string.
   * @return std::string containing a copy of the library version string.
   */
  const std::string libVersion() const
  {
    const char *ver= memcached_lib_version();
    const std::string version(ver);
    return version;
  }

private:

  memcached_st memc;
  memcached_result_st result;
};

}

#endif /* LIBMEMCACHEDPP_H */
<commit_msg>Corrected setAll methods to take std::map parameter by reference instead of by value.<commit_after>/*
 * Summary: C++ interface for memcached server
 *
 * Copy: See Copyright for the status of this software.
 *
 * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
 *          Patrick Galbraith <patg@patg.net>
 */

/**
 * @file memcached.hpp
 * @brief Libmemcached C++ interface
 */

#ifndef LIBMEMCACHEDPP_H
#define LIBMEMCACHEDPP_H

#include <libmemcached/memcached.h>

#include <string.h>

#include <string>
#include <vector>
#include <map>

namespace memcache
{

/**
 * This is the core memcached library (if later, other objects
 * are needed, they will be created from this class).
 */
class Memcache
{
public:

  Memcache()
    :
      memc(),
      result()
  {
    memcached_create(&memc);
  }

  Memcache(memcached_st *clone)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, clone);
  }

  Memcache(const Memcache &rhs)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, const_cast<memcached_st *>(&rhs.getImpl()));
  }

  ~Memcache()
  {
    memcached_free(&memc);
  }

  /**
   * Get the internal memcached_st *
   */
  memcached_st &getImpl()
  {
    return memc;
  }

  /**
   * Get the internal memcached_st *
   */
  const memcached_st &getImpl() const
  {
    return memc;
  }

  /**
   * Return an error string for the given return structure.
   *
   * @param[in] rc a memcached_return structure
   * @return error string corresponding to given return code in the library.
   */
  const std::string getError(memcached_return rc) const
  {
    /* first parameter to strerror is unused */
    return memcached_strerror(NULL, rc);
  }

  /**
   * Fetches an individual value from the server.
   *
   * @param[in] key key of object to fetch
   * @param[out] ret_val store returned object in this vector
   * @return true on success; false on failure
   */
  bool fetch(std::string &key,
             std::vector<char> &ret_val)
  {
    char ret_key[MEMCACHED_MAX_KEY];
    size_t value_length= 0;
    size_t key_length= 0;
    memcached_return rc;
    uint32_t flags= 0;
    char *value= memcached_fetch(&memc, ret_key, &key_length,
                                 &value_length, &flags, &rc);
    if (value && ret_val.empty())
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
      key.assign(ret_key);
      return true;
    }
    return false;
  }

  std::vector<char> &get(const std::string &key,
                         std::vector<char> &ret_val)
  {
    uint32_t flags= 0;
    memcached_return rc;
    size_t value_length= 0;

    if (key.empty())
    {
      return ret_val;
    }
    char *value= memcached_get(&memc, key.c_str(), key.length(),
                               &value_length, &flags, &rc);
    if (value != NULL && ret_val.empty())
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
    }
    return ret_val;
  }

  std::vector<char> &getByKey(const std::string &master_key,
                              const std::string &key,
                              std::vector<char> &ret_val)
  {
    uint32_t flags= 0;
    memcached_return rc;
    size_t value_length= 0;

    if (master_key.empty() || key.empty())
    {
      return ret_val;
    }
    char *value= memcached_get_by_key(&memc,
                                      master_key.c_str(), master_key.length(),
                                      key.c_str(), key.length(),
                                      &value_length, &flags, &rc);
    if (value)
    {
      ret_val.reserve(value_length);
      ret_val.assign(value, value + value_length);
    }
    return ret_val;
  }

  bool mget(std::vector<std::string> &keys)
  {
    std::vector<const char *> real_keys;
    std::vector<size_t> key_len;
    /*
     * Construct an array which will contain the length
     * of each of the strings in the input vector. Also, to
     * interface with the memcached C API, we need to convert
     * the vector of std::string's to a vector of char *.
     */
    real_keys.reserve(keys.size());
    key_len.reserve(keys.size());

    std::vector<std::string>::iterator it= keys.begin();

    while (it != keys.end())
    {
      real_keys.push_back(const_cast<char *>((*it).c_str()));
      key_len.push_back((*it).length());
      ++it;
    }

    /*
     * If the std::vector of keys is empty then we cannot
     * call memcached_mget as we will get undefined behavior.
     */
    if (! real_keys.empty())
    {
      memcached_return rc= memcached_mget(&memc, &real_keys[0], &key_len[0],
                                          real_keys.size());
      return (rc == MEMCACHED_SUCCESS);
    }

    return false;
  }

  bool set(const std::string &key,
           const std::vector<char> &value,
           time_t expiration,
           uint32_t flags)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_set(&memc,
                                       key.c_str(), key.length(),
                                       &value[0], value.size(),
                                       expiration, flags);
    return (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
  }

  bool setAll(std::vector<std::string> &keys,
              std::vector< std::vector<char> *> &values,
              time_t expiration,
              uint32_t flags)
  {
    if (keys.size() != values.size())
    {
      return false;
    }
    bool retval= true;
    std::vector<std::string>::iterator key_it= keys.begin();
    std::vector< std::vector<char> *>::iterator val_it= values.begin();
    while (key_it != keys.end())
    {
      retval= set((*key_it), *(*val_it), expiration, flags);
      if (retval == false)
      {
        return retval;
      }
      ++key_it;
      ++val_it;
    }
    return retval;
  }

  bool setAll(std::map<const std::string, std::vector<char> > &key_value_map,
              time_t expiration,
              uint32_t flags)
  {
    if (key_value_map.empty())
    {
      return false;
    }
    bool retval= true;
    std::map<const std::string, std::vector<char> >::iterator it=
      key_value_map.begin();
    while (it != key_value_map.end())
    {
      retval= set(it->first, it->second, expiration, flags);
      if (retval == false)
      {
        return false;
      }
      ++it;
    }
    return true;
  }

  bool setByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value,
                time_t expiration,
                uint32_t flags)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(), key.length(),
                                              &value[0], value.size(),
                                              expiration,
                                              flags);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool increment(const std::string &key, unsigned int offset, uint64_t *value)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool decrement(const std::string &key, unsigned int offset, uint64_t *value)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_decrement(&memc, key.c_str(),
                                             key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
                                       &value[0], value.size(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool addByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_add_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              &value[0],
                                              value.size(),
                                              0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
                                           &value[0], value.size(),
                                           0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replaceByKey(const std::string &master_key,
                    const std::string &key,
                    const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_replace_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  &value[0],
                                                  value.size(),
                                                  0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
                                           &value[0], value.size(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prependByKey(const std::string &master_key,
                    const std::string &key,
                    const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_prepend_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  &value[0],
                                                  value.size(),
                                                  0,
                                                  0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append(const std::string &key, const std::vector<char> &value)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_append(&memc,
                                          key.c_str(),
                                          key.length(),
                                          &value[0],
                                          value.size(),
                                          0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool appendByKey(const std::string &master_key,
                   const std::string &key,
                   const std::vector<char> &value)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_append_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 &value[0],
                                                 value.size(),
                                                 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas(const std::string &key,
           const std::vector<char> &value,
           uint64_t cas_arg)
  {
    if (key.empty() || value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
                                       &value[0], value.size(),
                                       0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool casByKey(const std::string &master_key,
                const std::string &key,
                const std::vector<char> &value,
                uint64_t cas_arg)
  {
    if (master_key.empty() ||
        key.empty() ||
        value.empty())
    {
      return false;
    }
    memcached_return rc= memcached_cas_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              &value[0],
                                              value.size(),
                                              0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool remove(const std::string &key)
  {
    if (key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool removeByKey(const std::string &master_key,
                   const std::string &key)
  {
    if (master_key.empty() || key.empty())
    {
      return false;
    }
    memcached_return rc= memcached_delete_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool flush(time_t expiration)
  {
    memcached_return rc= memcached_flush(&memc, expiration);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool fetchExecute(memcached_execute_function *callback,
                    void *context,
                    unsigned int num_of_callbacks)
  {
    memcached_return rc= memcached_fetch_execute(&memc,
                                                 callback,
                                                 context,
                                                 num_of_callbacks);
    return (rc == MEMCACHED_SUCCESS);
  }

  /**
   * Get the library version string.
   * @return std::string containing a copy of the library version string.
   */
  const std::string libVersion() const
  {
    const char *ver= memcached_lib_version();
    const std::string version(ver);
    return version;
  }

private:

  memcached_st memc;
  memcached_result_st result;
};

}

#endif /* LIBMEMCACHEDPP_H */
<|endoftext|>


<commit_before>/**
 ** \file object/list-class.cc
 ** \brief Creation of the URBI object list.
 */

#include <boost/assign.hpp>
#include <boost/bind.hpp>

#include <libport/foreach.hh>
#include <libport/ufloat.hh>

#include <kernel/userver.hh>
#include <object/code-class.hh>
#include <object/float-class.hh>
#include <object/list-class.hh>
#include <object/atom.hh>
#include <object/object.hh>
#include <object/primitives.hh>

#include <runner/runner.hh>
#include <runner/interpreter.hh>

using namespace boost::assign;

namespace object
{
  rObject list_class;

  List::List()
  {
    proto_add(list_class);
  }

  List::List(const value_type& value)
    : content_(value)
  {
    proto_add(list_class);
  }

  List::List(rList model)
    : content_(model->content_)
  {
    proto_add(list_class);
  }

  const List::value_type& List::value_get() const
  {
    return content_;
  }

  List::value_type& List::value_get()
  {
    return content_;
  }

#define CHECK_NON_EMPTY(Name)                                           \
  if (content_.empty ())                                                \
    throw PrimitiveError						\
      (Name, "operation cannot be applied onto empty list")

  rList List::tail()
  {
    CHECK_NON_EMPTY("tail");
    value_type res = content_;
    res.pop_front();
    return new List(res);
  }

  rObject List::operator[](rFloat idx)
  {
    unsigned i = idx->to_int(SYMBOL(nth));
    if (i >= content_.size())
      throw PrimitiveError("nth", "invalid index");
    return content_[i];
  }

  rFloat List::size()
  {
    return new Float(content_.size());
  }

  rList List::remove_by_id(rObject elt)
  {
    value_type::iterator it = content_.begin();
    while (it != content_.end())
      if (*it == elt)
        it = content_.erase(it);
      else
        ++it;
    return this;
  }

  rList List::operator+=(rList rhs)
  {
    // Copy the list to make a += a work
    value_type other = rhs->value_get();
    foreach (const rObject& o, other)
      content_.push_back(o);
    return this;
  }

  rList List::operator+(rList rhs)
  {
    rList res = new List(this);
    *res += rhs;
    return res;
  }

  /// Binary predicate used to sort lists.
  static bool
  compareListItems (runner::Runner& r, rObject a, rObject b)
  {
    return is_true(urbi_call(r, a, SYMBOL(LT), b), SYMBOL(sort));
  }

  rList List::sort(runner::Runner& r)
  {
    std::list<rObject> s;
    foreach(const rObject& o, content_)
      s.push_back(o);
    s.sort(boost::bind(compareListItems, boost::ref(r), _1, _2));

    List::value_type res;
    foreach(const rObject& o, s)
      res.push_back(o);
    return new List(res);
  }

  void
  List::each(runner::Runner& r, rObject f)
  {
    // Beware of iterations that modify the list in place: make a
    // copy.
    foreach (const rObject& o, value_type(content_))
      r.apply(f, SYMBOL(each), list_of (f) (o));
  }

  void
  List::each_and(runner::Runner& r, rObject f)
  {
    scheduler::jobs_type jobs;
    // Beware of iterations that modify the list in place: make a
    // copy.
    rforeach (const rObject& o, value_type(content_))
    {
      scheduler::rJob job =
        new runner::Interpreter(dynamic_cast<runner::Interpreter&>(r),
                                f, SYMBOL(each), list_of(o));
      r.link(job);
      job->start_job();
      jobs.push_back(job);
    }

    r.yield_until_terminated(jobs);
  }

#define BOUNCE(Name, Ret, Arg, Check)                           \
  IF(Ret, rObject, rList) List::Name(WHEN(Arg, rObject arg))    \
  {                                                             \
    WHEN(Check, CHECK_NON_EMPTY(#Name));                        \
    WHEN(Ret, return) content_.Name(WHEN(Arg, arg));            \
    return this;                                                \
  }

  BOUNCE(back,       true,  false, true );
  BOUNCE(clear,      false, false, false);
  BOUNCE(front,      true,  false, true );
  BOUNCE(pop_back,   false, false, true );
  BOUNCE(pop_front,  false, false, true );
  BOUNCE(push_back,  false, true,  false);
  BOUNCE(push_front, false, true,  false);

#undef BOUNCE

  void List::initialize(CxxObject::Binder<List>& bind)
  {
    bind(SYMBOL(back),           &List::back        );
    bind(SYMBOL(clear),          &List::clear       );
    bind(SYMBOL(each),           &List::each        );
    bind(SYMBOL(each_AMPERSAND), &List::each_and    );
    bind(SYMBOL(front),          &List::front       );
    bind(SYMBOL(PLUS),           &List::operator+   );
    bind(SYMBOL(PLUS_EQ),        &List::operator+=  );
    bind(SYMBOL(nth),            &List::operator[]  );
    bind(SYMBOL(push_back),      &List::push_back   );
    bind(SYMBOL(push_front),     &List::push_front  );
    bind(SYMBOL(pop_back),       &List::pop_back    );
    bind(SYMBOL(pop_front),      &List::pop_front   );
    bind(SYMBOL(removeById),     &List::remove_by_id);
    bind(SYMBOL(size),           &List::size        );
    bind(SYMBOL(sort),           &List::sort        );
    bind(SYMBOL(tail),           &List::tail        );
  }

  std::string List::type_name_get() const
  {
    return type_name;
  }

  bool List::list_added =
    CxxObject::add<List>("List", list_class);
  const std::string List::type_name = "List";

} // namespace object
<commit_msg>Create the copy before passing it to rforeach.<commit_after>/**
 ** \file object/list-class.cc
 ** \brief Creation of the URBI object list.
 */

#include <boost/assign.hpp>
#include <boost/bind.hpp>

#include <libport/foreach.hh>
#include <libport/ufloat.hh>

#include <kernel/userver.hh>
#include <object/code-class.hh>
#include <object/float-class.hh>
#include <object/list-class.hh>
#include <object/atom.hh>
#include <object/object.hh>
#include <object/primitives.hh>

#include <runner/runner.hh>
#include <runner/interpreter.hh>

using namespace boost::assign;

namespace object
{
  rObject list_class;

  List::List()
  {
    proto_add(list_class);
  }

  List::List(const value_type& value)
    : content_(value)
  {
    proto_add(list_class);
  }

  List::List(rList model)
    : content_(model->content_)
  {
    proto_add(list_class);
  }

  const List::value_type& List::value_get() const
  {
    return content_;
  }

  List::value_type& List::value_get()
  {
    return content_;
  }

#define CHECK_NON_EMPTY(Name)                                           \
  if (content_.empty ())                                                \
    throw PrimitiveError						\
      (Name, "operation cannot be applied onto empty list")

  rList List::tail()
  {
    CHECK_NON_EMPTY("tail");
    value_type res = content_;
    res.pop_front();
    return new List(res);
  }

  rObject List::operator[](rFloat idx)
  {
    unsigned i = idx->to_int(SYMBOL(nth));
    if (i >= content_.size())
      throw PrimitiveError("nth", "invalid index");
    return content_[i];
  }

  rFloat List::size()
  {
    return new Float(content_.size());
  }

  rList List::remove_by_id(rObject elt)
  {
    value_type::iterator it = content_.begin();
    while (it != content_.end())
      if (*it == elt)
        it = content_.erase(it);
      else
        ++it;
    return this;
  }

  rList List::operator+=(rList rhs)
  {
    // Copy the list to make a += a work
    value_type other = rhs->value_get();
    foreach (const rObject& o, other)
      content_.push_back(o);
    return this;
  }

  rList List::operator+(rList rhs)
  {
    rList res = new List(this);
    *res += rhs;
    return res;
  }

  /// Binary predicate used to sort lists.
  static bool
  compareListItems (runner::Runner& r, rObject a, rObject b)
  {
    return is_true(urbi_call(r, a, SYMBOL(LT), b), SYMBOL(sort));
  }

  rList List::sort(runner::Runner& r)
  {
    std::list<rObject> s;
    foreach(const rObject& o, content_)
      s.push_back(o);
    s.sort(boost::bind(compareListItems, boost::ref(r), _1, _2));

    List::value_type res;
    foreach(const rObject& o, s)
      res.push_back(o);
    return new List(res);
  }

  void
  List::each(runner::Runner& r, rObject f)
  {
    // Beware of iterations that modify the list in place: make a
    // copy.
    foreach (const rObject& o, value_type(content_))
      r.apply(f, SYMBOL(each), list_of (f) (o));
  }

  void
  List::each_and(runner::Runner& r, rObject f)
  {
    scheduler::jobs_type jobs;
    // Beware of iterations that modify the list in place: make a
    // copy.
    value_type l(content_);
    rforeach (const rObject& o, l)
    {
      scheduler::rJob job =
        new runner::Interpreter(dynamic_cast<runner::Interpreter&>(r),
                                f, SYMBOL(each), list_of(o));
      r.link(job);
      job->start_job();
      jobs.push_back(job);
    }

    r.yield_until_terminated(jobs);
  }

#define BOUNCE(Name, Ret, Arg, Check)                           \
  IF(Ret, rObject, rList) List::Name(WHEN(Arg, rObject arg))    \
  {                                                             \
    WHEN(Check, CHECK_NON_EMPTY(#Name));                        \
    WHEN(Ret, return) content_.Name(WHEN(Arg, arg));            \
    return this;                                                \
  }

  BOUNCE(back,       true,  false, true );
  BOUNCE(clear,      false, false, false);
  BOUNCE(front,      true,  false, true );
  BOUNCE(pop_back,   false, false, true );
  BOUNCE(pop_front,  false, false, true );
  BOUNCE(push_back,  false, true,  false);
  BOUNCE(push_front, false, true,  false);

#undef BOUNCE

  void List::initialize(CxxObject::Binder<List>& bind)
  {
    bind(SYMBOL(back),           &List::back        );
    bind(SYMBOL(clear),          &List::clear       );
    bind(SYMBOL(each),           &List::each        );
    bind(SYMBOL(each_AMPERSAND), &List::each_and    );
    bind(SYMBOL(front),          &List::front       );
    bind(SYMBOL(PLUS),           &List::operator+   );
    bind(SYMBOL(PLUS_EQ),        &List::operator+=  );
    bind(SYMBOL(nth),            &List::operator[]  );
    bind(SYMBOL(push_back),      &List::push_back   );
    bind(SYMBOL(push_front),     &List::push_front  );
    bind(SYMBOL(pop_back),       &List::pop_back    );
    bind(SYMBOL(pop_front),      &List::pop_front   );
    bind(SYMBOL(removeById),     &List::remove_by_id);
    bind(SYMBOL(size),           &List::size        );
    bind(SYMBOL(sort),           &List::sort        );
    bind(SYMBOL(tail),           &List::tail        );
  }

  std::string List::type_name_get() const
  {
    return type_name;
  }

  bool List::list_added =
    CxxObject::add<List>("List", list_class);
  const std::string List::type_name = "List";

} // namespace object
<|endoftext|>