Dict.h
Go to the documentation of this file.
//
// Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
/*! \file Dict.h
\brief Defines the Dict class
*/
#include <RDGeneral/export.h>
#ifndef __RD_DICT_H__
#define __RD_DICT_H__
#include <map>
#include <string>
#include <vector>
#include "RDValue.h"
#include "Exceptions.h"
#include <RDGeneral/BoostStartInclude.h>
#include <boost/lexical_cast.hpp>
#include <RDGeneral/BoostEndInclude.h>
namespace RDKit {
typedef std::vector<std::string> STR_VECT;
//! \brief The \c Dict class can be used to store objects of arbitrary
//! type keyed by \c strings.
//!
//! The actual storage is done using \c RDValue objects.
//!
class RDKIT_RDGENERAL_EXPORT Dict {
public:
struct Pair {
std::string key;
RDValue val;
Pair() : key(), val() {}
explicit Pair(std::string s) : key(std::move(s)), val() {}
Pair(std::string s, const RDValue &v) : key(std::move(s)), val(v) {}
};
typedef std::vector<Pair> DataType;
Dict() : _data(), _hasNonPodData(false){};
Dict(const Dict &other) : _data(other._data) {
_hasNonPodData = other._hasNonPodData;
if (other._hasNonPodData) { // other has non pod data, need to copy
std::vector<Pair> data(other._data.size());
_data.swap(data);
for (size_t i = 0; i < _data.size(); ++i) {
_data[i].key = other._data[i].key;
copy_rdvalue(_data[i].val, other._data[i].val);
}
}
}
~Dict() {
reset(); // to clear pointers if necessary
}
void update(const Dict &other, bool preserveExisting = false) {
if (!preserveExisting) {
*this = other;
} else {
if (other._hasNonPodData) _hasNonPodData = true;
for (size_t i = 0; i < other._data.size(); ++i) {
const Pair &pair = other._data[i];
Pair *target = 0;
for (size_t i = 0; i < _data.size(); ++i) {
if (_data[i].key == pair.key) {
target = &_data[i];
break;
}
}
if (!target) {
// need to create blank entry and copy
_data.push_back(Pair(pair.key));
copy_rdvalue(_data.back().val, pair.val);
} else {
// just copy
copy_rdvalue(target->val, pair.val);
}
}
}
}
Dict &operator=(const Dict &other) {
if (this == &other) return *this;
if (_hasNonPodData) reset();
if (other._hasNonPodData) {
std::vector<Pair> data(other._data.size());
_data.swap(data);
for (size_t i = 0; i < _data.size(); ++i) {
_data[i].key = other._data[i].key;
copy_rdvalue(_data[i].val, other._data[i].val);
}
} else {
_data = other._data;
}
_hasNonPodData = other._hasNonPodData;
return *this;
};
//----------------------------------------------------------
//! \brief Access to the underlying non-POD containment flag
//! This is meant to be used only in bulk updates of _data.
bool &getNonPODStatus() { return _hasNonPodData; }
//----------------------------------------------------------
//! \brief Access to the underlying data.
const DataType &getData() const { return _data; }
DataType &getData() { return _data; }
//----------------------------------------------------------
//! \brief Returns whether or not the dictionary contains a particular
//! key.
bool hasVal(const std::string &what) const {
for (const auto &data : _data) {
if (data.key == what) return true;
}
return false;
};
//----------------------------------------------------------
//! Returns the set of keys in the dictionary
/*!
\return a \c STR_VECT
*/
STR_VECT keys() const {
STR_VECT res;
DataType::const_iterator item;
for (item = _data.begin(); item != _data.end(); item++) {
res.push_back(item->key);
}
return res;
}
//----------------------------------------------------------
//! \brief Gets the value associated with a particular key
/*!
\param what the key to lookup
\param res a reference used to return the result
<B>Notes:</b>
- If \c res is a \c std::string, every effort will be made
to convert the specified element to a string using the
\c boost::lexical_cast machinery.
- If the dictionary does not contain the key \c what,
a KeyErrorException will be thrown.
*/
template <typename T>
void getVal(const std::string &what, T &res) const {
res = getVal<T>(what);
};
//! \overload
template <typename T>
T getVal(const std::string &what) const {
for (auto &data : _data) {
if (data.key == what) {
return from_rdvalue<T>(data.val);
}
}
throw KeyErrorException(what);
}
//! \overload
void getVal(const std::string &what, std::string &res) const;
//----------------------------------------------------------
//! \brief Potentially gets the value associated with a particular key
//! returns true on success/false on failure.
/*!
\param what the key to lookup
\param res a reference used to return the result
<B>Notes:</b>
- If \c res is a \c std::string, every effort will be made
to convert the specified element to a string using the
\c boost::lexical_cast machinery.
- If the dictionary does not contain the key \c what,
a KeyErrorException will be thrown.
*/
template <typename T>
bool getValIfPresent(const std::string &what, T &res) const {
for (const auto &data : _data) {
if (data.key == what) {
res = from_rdvalue<T>(data.val);
return true;
}
}
return false;
};
//! \overload
bool getValIfPresent(const std::string &what, std::string &res) const;
//----------------------------------------------------------
//! \brief Sets the value associated with a key
/*!
\param what the key to set
\param val the value to store
<b>Notes:</b>
- If \c val is a <tt>const char *</tt>, it will be converted
to a \c std::string for storage.
- If the dictionary already contains the key \c what,
the value will be replaced.
*/
template <typename T>
void setVal(const std::string &what, T &val) {
_hasNonPodData = true;
for (auto &&data : _data) {
if (data.key == what) {
RDValue::cleanup_rdvalue(data.val);
data.val = val;
return;
}
}
_data.push_back(Pair(what, val));
};
template <typename T>
void setPODVal(const std::string &what, T val) {
// don't change the hasNonPodData status
for (auto &&data : _data) {
if (data.key == what) {
RDValue::cleanup_rdvalue(data.val);
data.val = val;
return;
}
}
_data.push_back(Pair(what, val));
};
void setVal(const std::string &what, bool val) { setPODVal(what, val); }
void setVal(const std::string &what, double val) { setPODVal(what, val); }
void setVal(const std::string &what, float val) { setPODVal(what, val); }
void setVal(const std::string &what, int val) { setPODVal(what, val); }
void setVal(const std::string &what, unsigned int val) {
setPODVal(what, val);
}
//! \overload
void setVal(const std::string &what, const char *val) {
std::string h(val);
setVal(what, h);
}
//----------------------------------------------------------
//! \brief Clears the value associated with a particular key,
//! removing the key from the dictionary.
/*!
\param what the key to clear
<b>Notes:</b>
- If the dictionary does not contain the key \c what,
a KeyErrorException will be thrown.
*/
void clearVal(const std::string &what) {
for (DataType::iterator it = _data.begin(); it < _data.end(); ++it) {
if (it->key == what) {
if (_hasNonPodData) {
RDValue::cleanup_rdvalue(it->val);
}
_data.erase(it);
return;
}
}
throw KeyErrorException(what);
};
//----------------------------------------------------------
//! \brief Clears all keys (and values) from the dictionary.
//!
void reset() {
if (_hasNonPodData) {
for (auto &&data : _data) {
RDValue::cleanup_rdvalue(data.val);
}
}
DataType data;
_data.swap(data);
};
//----------------------------------------------------------
//! Converts a \c RDAny to type \c T
/*!
\param arg a \c RDAny reference
\returns the converted object of type \c T
*/
/*
template <typename T>
T fromany(const RDAny &arg) const {
return from_rdany<T>(arg);
}
*/
//----------------------------------------------------------
//! Converts an instance of type \c T to \c RDAny
/*!
\param arg the object to be converted
\returns a \c RDAny instance
*/
/*
template <typename T>
RDAny toany(T arg) const {
return RDAny(arg);
};
*/
private:
DataType _data; //!< the actual dictionary
bool _hasNonPodData; // if true, need a deep copy
// (copy_rdvalue)
};
template <>
RDKIT_RDGENERAL_EXPORT std::string Dict::getVal<std::string>(
const std::string &what) const;
} // namespace RDKit
#endif
RDKit::Dict::setVal
void setVal(const std::string &what, bool val)
Definition: Dict.h:246
RDKit::Dict
The Dict class can be used to store objects of arbitrary type keyed by strings.
Definition: Dict.h:36
RDKit::Dict::update
void update(const Dict &other, bool preserveExisting=false)
Definition: Dict.h:67
RDKit::Dict::setVal
void setVal(const std::string &what, unsigned int val)
Definition: Dict.h:254
RDKit::Dict::Pair::key
std::string key
Definition: Dict.h:39
RDKit::Dict::setVal
void setVal(const std::string &what, double val)
Definition: Dict.h:248
RDKit::Dict::DataType
std::vector< Pair > DataType
Definition: Dict.h:47
RDKit::Dict::setVal
void setVal(const std::string &what, const char *val)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Dict.h:259
BoostStartInclude.h
RDKit::Dict::Dict
Dict(const Dict &other)
Definition: Dict.h:51
RDKit::RDValue
Definition: RDValue-doublemagic.h:167
RDKit::Dict::setVal
void setVal(const std::string &what, float val)
Definition: Dict.h:250
RDKit::Dict::~Dict
~Dict()
Definition: Dict.h:63
KeyErrorException
Class to allow us to throw a KeyError from C++ and have it make it back to Python.
Definition: Exceptions.h:49
RDKit::Dict::getNonPODStatus
bool & getNonPODStatus()
Access to the underlying non-POD containment flag This is meant to be used only in bulk updates of _d...
Definition: Dict.h:115
RDKit::Dict::hasVal
bool hasVal(const std::string &what) const
Returns whether or not the dictionary contains a particular key.
Definition: Dict.h:126
RDKit::STR_VECT
std::vector< std::string > STR_VECT
Definition: Dict.h:29
RDKit::RDValue::cleanup_rdvalue
static void cleanup_rdvalue(RDValue v)
Definition: RDValue-doublemagic.h:331
RDKit::Dict::getValIfPresent
bool getValIfPresent(const std::string &what, T &res) const
Potentially gets the value associated with a particular key returns true on success/false on failure.
Definition: Dict.h:194
BoostEndInclude.h
RDKit::Dict::Pair::val
RDValue val
Definition: Dict.h:40
RDKit::Dict::setVal
void setVal(const std::string &what, T &val)
Sets the value associated with a key.
Definition: Dict.h:221
RDKit::Dict::getVal
void getVal(const std::string &what, T &res) const
Gets the value associated with a particular key.
Definition: Dict.h:161
RDKit::Dict::Pair::Pair
Pair()
Definition: Dict.h:42
RDKit::Dict::clearVal
void clearVal(const std::string &what)
Clears the value associated with a particular key, removing the key from the dictionary.
Definition: Dict.h:275
RDKit::Dict::reset
void reset()
Clears all keys (and values) from the dictionary.
Definition: Dict.h:291
RDKit::Dict::setPODVal
void setPODVal(const std::string &what, T val)
Definition: Dict.h:234
RDKit::Dict::Pair::Pair
Pair(std::string s, const RDValue &v)
Definition: Dict.h:44
RDKit::Dict::keys
STR_VECT keys() const
Returns the set of keys in the dictionary.
Definition: Dict.h:138
RDKit::Dict::Dict
Dict()
Definition: Dict.h:49
RDKit::Dict::operator=
Dict & operator=(const Dict &other)
Definition: Dict.h:94
RDKit::Dict::Pair::Pair
Pair(std::string s)
Definition: Dict.h:43
RDKit
Std stuff.
Definition: Atom.h:30
RDKit::Dict::getVal
T getVal(const std::string &what) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Dict.h:166
RDValue.h
RDKit::Dict::Pair
Definition: Dict.h:38
RDKIT_RDGENERAL_EXPORT
#define RDKIT_RDGENERAL_EXPORT
Definition: export.h:502
RDKit::Dict::getData
const DataType & getData() const
Access to the underlying data.
Definition: Dict.h:119
RDKit::Dict::getData
DataType & getData()
Definition: Dict.h:120
RDKit::copy_rdvalue
void copy_rdvalue(RDValue &dest, const RDValue &src)
Definition: RDValue-doublemagic.h:339
RDKit::Dict::setVal
void setVal(const std::string &what, int val)
Definition: Dict.h:252
Exceptions.h
export.h