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