RDKit
Open-source cheminformatics and machine learning.
Dict.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10 /*! \file Dict.h
11 
12  \brief Defines the Dict class
13 
14 */
15 #include <RDGeneral/export.h>
16 #ifndef __RD_DICT_H__
17 #define __RD_DICT_H__
18 
19 #include <map>
20 #include <string>
21 #include <vector>
22 #include "RDValue.h"
23 #include "Exceptions.h"
25 #include <boost/lexical_cast.hpp>
27 
28 namespace RDKit {
29 typedef std::vector<std::string> STR_VECT;
30 
31 //! \brief The \c Dict class can be used to store objects of arbitrary
32 //! type keyed by \c strings.
33 //!
34 //! The actual storage is done using \c RDValue objects.
35 //!
37  public:
38  struct Pair {
39  std::string key;
41 
42  Pair() : key(), val() {}
43  Pair(const std::string &s) : key(s), val() {}
44  Pair(const std::string &s, const RDValue &v) : key(s), val(v) {}
45  };
46 
47  typedef std::vector<Pair> DataType;
48 
49  Dict() : _data(), _hasNonPodData(false){};
50 
51  Dict(const Dict &other) : _data(other._data) {
52  _hasNonPodData = other._hasNonPodData;
53  if (other._hasNonPodData) { // other has non pod data, need to copy
54  std::vector<Pair> data(other._data.size());
55  _data.swap(data);
56  for (size_t i = 0; i < _data.size(); ++i) {
57  _data[i].key = other._data[i].key;
58  copy_rdvalue(_data[i].val, other._data[i].val);
59  }
60  }
61  }
62 
63  ~Dict() {
64  reset(); // to clear pointers if necessary
65  }
66 
67  void update(const Dict &other, bool preserveExisting = false) {
68  if (!preserveExisting) {
69  *this = other;
70  } else {
71  if (other._hasNonPodData) _hasNonPodData = true;
72  for (size_t i = 0; i < other._data.size(); ++i) {
73  const Pair &pair = other._data[i];
74  Pair *target = 0;
75  for (size_t i = 0; i < _data.size(); ++i) {
76  if (_data[i].key == pair.key) {
77  target = &_data[i];
78  break;
79  }
80  }
81 
82  if (!target) {
83  // need to create blank entry and copy
84  _data.push_back(Pair(pair.key));
85  copy_rdvalue(_data.back().val, pair.val);
86  } else {
87  // just copy
88  copy_rdvalue(target->val, pair.val);
89  }
90  }
91  }
92  }
93 
94  Dict &operator=(const Dict &other) {
95  if (this == &other) return *this;
96  if (_hasNonPodData) reset();
97 
98  if (other._hasNonPodData) {
99  std::vector<Pair> data(other._data.size());
100  _data.swap(data);
101  for (size_t i = 0; i < _data.size(); ++i) {
102  _data[i].key = other._data[i].key;
103  copy_rdvalue(_data[i].val, other._data[i].val);
104  }
105  } else {
106  _data = other._data;
107  }
108  _hasNonPodData = other._hasNonPodData;
109  return *this;
110  };
111 
112  //----------------------------------------------------------
113  //! \brief Access to the underlying data.
114  const DataType &getData() const { return _data; }
115  DataType &getData() { return _data; }
116 
117  //----------------------------------------------------------
118 
119  //! \brief Returns whether or not the dictionary contains a particular
120  //! key.
121  bool hasVal(const std::string &what) const {
122  for (size_t i = 0; i < _data.size(); ++i) {
123  if (_data[i].key == what) return true;
124  }
125  return false;
126  };
127 
128  //----------------------------------------------------------
129  //! Returns the set of keys in the dictionary
130  /*!
131  \return a \c STR_VECT
132  */
133  STR_VECT keys() const {
134  STR_VECT res;
135  DataType::const_iterator item;
136  for (item = _data.begin(); item != _data.end(); item++) {
137  res.push_back(item->key);
138  }
139  return res;
140  }
141 
142  //----------------------------------------------------------
143  //! \brief Gets the value associated with a particular key
144  /*!
145  \param what the key to lookup
146  \param res a reference used to return the result
147 
148  <B>Notes:</b>
149  - If \c res is a \c std::string, every effort will be made
150  to convert the specified element to a string using the
151  \c boost::lexical_cast machinery.
152  - If the dictionary does not contain the key \c what,
153  a KeyErrorException will be thrown.
154  */
155  template <typename T>
156  void getVal(const std::string &what, T &res) const {
157  res = getVal<T>(what);
158  };
159  //! \overload
160  template <typename T>
161  T getVal(const std::string &what) const {
162  for (size_t i = 0; i < _data.size(); ++i) {
163  if (_data[i].key == what) {
164  return from_rdvalue<T>(_data[i].val);
165  }
166  }
167  throw KeyErrorException(what);
168  }
169 
170  //! \overload
171  void getVal(const std::string &what, std::string &res) const;
172 
173  //----------------------------------------------------------
174  //! \brief Potentially gets the value associated with a particular key
175  //! returns true on success/false on failure.
176  /*!
177  \param what the key to lookup
178  \param res a reference used to return the result
179 
180  <B>Notes:</b>
181  - If \c res is a \c std::string, every effort will be made
182  to convert the specified element to a string using the
183  \c boost::lexical_cast machinery.
184  - If the dictionary does not contain the key \c what,
185  a KeyErrorException will be thrown.
186  */
187 
188  template <typename T>
189  bool getValIfPresent(const std::string &what, T &res) const {
190  for (size_t i = 0; i < _data.size(); ++i) {
191  if (_data[i].key == what) {
192  res = from_rdvalue<T>(_data[i].val);
193  return true;
194  }
195  }
196  return false;
197  };
198 
199  //! \overload
200  bool getValIfPresent(const std::string &what, std::string &res) const;
201 
202  //----------------------------------------------------------
203  //! \brief Sets the value associated with a key
204  /*!
205 
206  \param what the key to set
207  \param val the value to store
208 
209  <b>Notes:</b>
210  - If \c val is a <tt>const char *</tt>, it will be converted
211  to a \c std::string for storage.
212  - If the dictionary already contains the key \c what,
213  the value will be replaced.
214  */
215  template <typename T>
216  void setVal(const std::string &what, T &val) {
217  _hasNonPodData = true;
218  for (size_t i = 0; i < _data.size(); ++i) {
219  if (_data[i].key == what) {
220  RDValue::cleanup_rdvalue(_data[i].val);
221  _data[i].val = val;
222  return;
223  }
224  }
225  _data.push_back(Pair(what, val));
226  };
227 
228  template <typename T>
229  void setPODVal(const std::string &what, T val) {
230  // don't change the hasNonPodData status
231  for (size_t i = 0; i < _data.size(); ++i) {
232  if (_data[i].key == what) {
233  RDValue::cleanup_rdvalue(_data[i].val);
234  _data[i].val = val;
235  return;
236  }
237  }
238  _data.push_back(Pair(what, val));
239  };
240 
241  void setVal(const std::string &what, bool val) { setPODVal(what, val); }
242 
243  void setVal(const std::string &what, double val) { setPODVal(what, val); }
244 
245  void setVal(const std::string &what, float val) { setPODVal(what, val); }
246 
247  void setVal(const std::string &what, int val) { setPODVal(what, val); }
248 
249  void setVal(const std::string &what, unsigned int val) {
250  setPODVal(what, val);
251  }
252 
253  //! \overload
254  void setVal(const std::string &what, const char *val) {
255  std::string h(val);
256  setVal(what, h);
257  }
258 
259  //----------------------------------------------------------
260  //! \brief Clears the value associated with a particular key,
261  //! removing the key from the dictionary.
262  /*!
263 
264  \param what the key to clear
265 
266  <b>Notes:</b>
267  - If the dictionary does not contain the key \c what,
268  a KeyErrorException will be thrown.
269  */
270  void clearVal(const std::string &what) {
271  for (DataType::iterator it = _data.begin(); it < _data.end(); ++it) {
272  if (it->key == what) {
273  if (_hasNonPodData) {
274  RDValue::cleanup_rdvalue(it->val);
275  }
276  _data.erase(it);
277  return;
278  }
279  }
280  throw KeyErrorException(what);
281  };
282 
283  //----------------------------------------------------------
284  //! \brief Clears all keys (and values) from the dictionary.
285  //!
286  void reset() {
287  if (_hasNonPodData) {
288  for (size_t i = 0; i < _data.size(); ++i) {
289  RDValue::cleanup_rdvalue(_data[i].val);
290  }
291  }
292  DataType data;
293  _data.swap(data);
294  };
295 
296  //----------------------------------------------------------
297  //! Converts a \c RDAny to type \c T
298  /*!
299  \param arg a \c RDAny reference
300 
301  \returns the converted object of type \c T
302  */
303  /*
304  template <typename T>
305  T fromany(const RDAny &arg) const {
306  return from_rdany<T>(arg);
307  }
308  */
309  //----------------------------------------------------------
310  //! Converts an instance of type \c T to \c RDAny
311  /*!
312  \param arg the object to be converted
313 
314  \returns a \c RDAny instance
315  */
316  /*
317  template <typename T>
318  RDAny toany(T arg) const {
319  return RDAny(arg);
320  };
321  */
322  private:
323  DataType _data; //!< the actual dictionary
324  bool _hasNonPodData; // if true, need a deep copy
325  // (copy_rdvalue)
326 };
327 }
328 #endif
void setVal(const std::string &what, T &val)
Sets the value associated with a key.
Definition: Dict.h:216
void copy_rdvalue(RDValue &dest, const RDValue &src)
#define RDKIT_RDGENERAL_EXPORT
Definition: export.h:489
void setVal(const std::string &what, int val)
Definition: Dict.h:247
std::vector< Pair > DataType
Definition: Dict.h:47
Pair(const std::string &s)
Definition: Dict.h:43
Dict()
Definition: Dict.h:49
void setVal(const std::string &what, float val)
Definition: Dict.h:245
const DataType & getData() const
Access to the underlying data.
Definition: Dict.h:114
void setVal(const std::string &what, bool val)
Definition: Dict.h:241
RDValue val
Definition: Dict.h:40
void setVal(const std::string &what, double val)
Definition: Dict.h:243
Pair(const std::string &s, const RDValue &v)
Definition: Dict.h:44
static void cleanup_rdvalue(RDValue v)
void setVal(const std::string &what, const char *val)
Definition: Dict.h:254
void setVal(const std::string &what, unsigned int val)
Definition: Dict.h:249
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:189
bool hasVal(const std::string &what) const
Returns whether or not the dictionary contains a particular key.
Definition: Dict.h:121
void getVal(const std::string &what, T &res) const
Gets the value associated with a particular key.
Definition: Dict.h:156
void clearVal(const std::string &what)
Clears the value associated with a particular key, removing the key from the dictionary.
Definition: Dict.h:270
std::string key
Definition: Dict.h:39
Dict(const Dict &other)
Definition: Dict.h:51
Std stuff.
Definition: Atom.h:30
STR_VECT keys() const
Returns the set of keys in the dictionary.
Definition: Dict.h:133
Dict & operator=(const Dict &other)
Definition: Dict.h:94
T getVal(const std::string &what) const
Definition: Dict.h:161
void setPODVal(const std::string &what, T val)
Definition: Dict.h:229
void update(const Dict &other, bool preserveExisting=false)
Definition: Dict.h:67
void reset()
Clears all keys (and values) from the dictionary.
Definition: Dict.h:286
DataType & getData()
Definition: Dict.h:115
~Dict()
Definition: Dict.h:63
The Dict class can be used to store objects of arbitrary type keyed by strings.
Definition: Dict.h:36
std::vector< std::string > STR_VECT
Definition: Dict.h:29
Class to allow us to throw a KeyError from C++ and have it make it back to Python.
Definition: Exceptions.h:49