RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
Dict.h
Go to the documentation of this file.
1//
2// Copyright (C) 2003-2021 Greg Landrum and other RDKit contributors
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_012020
17#define RD_DICT_H_012020
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
28namespace RDKit {
29typedef 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 explicit Pair(std::string s) : key(std::move(s)), val() {}
44 Pair(std::string s, const RDValue &v) : key(std::move(s)), val(v) {}
45 };
46
47 typedef std::vector<Pair> DataType;
48
49 Dict() {}
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(Dict &&other) noexcept = default;
64
66 reset(); // to clear pointers if necessary
67 }
68
69 void update(const Dict &other, bool preserveExisting = false) {
70 if (!preserveExisting) {
71 *this = other;
72 } else {
73 if (other._hasNonPodData) {
74 _hasNonPodData = true;
75 }
76 for (const auto &opair : other._data) {
77 Pair *target = nullptr;
78 for (auto &dpair : _data) {
79 if (dpair.key == opair.key) {
80 target = &dpair;
81 break;
82 }
83 }
84
85 if (!target) {
86 // need to create blank entry and copy
87 _data.push_back(Pair(opair.key));
88 copy_rdvalue(_data.back().val, opair.val);
89 } else {
90 // just copy
91 copy_rdvalue(target->val, opair.val);
92 }
93 }
94 }
95 }
96
97 Dict &operator=(const Dict &other) {
98 if (this == &other) {
99 return *this;
100 }
101 if (_hasNonPodData) {
102 reset();
103 }
104
105 if (other._hasNonPodData) {
106 std::vector<Pair> data(other._data.size());
107 _data.swap(data);
108 for (size_t i = 0; i < _data.size(); ++i) {
109 _data[i].key = other._data[i].key;
110 copy_rdvalue(_data[i].val, other._data[i].val);
111 }
112 } else {
113 _data = other._data;
114 }
115 _hasNonPodData = other._hasNonPodData;
116 return *this;
117 }
118
119 Dict &operator=(Dict &&other) noexcept {
120 if (this == &other) {
121 return *this;
122 }
123 if (_hasNonPodData) {
124 reset();
125 }
126 _hasNonPodData = other._hasNonPodData;
127 other._hasNonPodData = false;
128 _data = std::move(other._data);
129 return *this;
130 }
131
132 //----------------------------------------------------------
133 //! \brief Access to the underlying non-POD containment flag
134 //! This is meant to be used only in bulk updates of _data.
135 bool &getNonPODStatus() { return _hasNonPodData; }
136
137 //----------------------------------------------------------
138 //! \brief Access to the underlying data.
139 const DataType &getData() const { return _data; }
140 DataType &getData() { return _data; }
141
142 //----------------------------------------------------------
143
144 //! \brief Returns whether or not the dictionary contains a particular
145 //! key.
146 bool hasVal(const std::string &what) const {
147 for (const auto &data : _data) {
148 if (data.key == what) {
149 return true;
150 }
151 }
152 return false;
153 }
154
155 //----------------------------------------------------------
156 //! Returns the set of keys in the dictionary
157 /*!
158 \return a \c STR_VECT
159 */
160 STR_VECT keys() const {
161 STR_VECT res;
162 res.reserve(_data.size());
163 for (const auto &item : _data) {
164 res.push_back(item.key);
165 }
166 return res;
167 }
168
169 //----------------------------------------------------------
170 //! \brief Gets the value associated with a particular key
171 /*!
172 \param what the key to lookup
173 \param res a reference used to return the result
174
175 <b>Notes:</b>
176 - If \c res is a \c std::string, every effort will be made
177 to convert the specified element to a string using the
178 \c boost::lexical_cast machinery.
179 - If the dictionary does not contain the key \c what,
180 a KeyErrorException will be thrown.
181 */
182 template <typename T>
183 void getVal(const std::string &what, T &res) const {
184 res = getVal<T>(what);
185 }
186
187 //! \overload
188 template <typename T>
189 T getVal(const std::string &what) const {
190 for (auto &data : _data) {
191 if (data.key == what) {
192 return from_rdvalue<T>(data.val);
193 }
194 }
195 throw KeyErrorException(what);
196 }
197
198 //! \overload
199 void getVal(const std::string &what, std::string &res) const {
200 for (const auto &i : _data) {
201 if (i.key == what) {
202 rdvalue_tostring(i.val, res);
203 return;
204 }
205 }
206 throw KeyErrorException(what);
207 }
208
209 //----------------------------------------------------------
210 //! \brief Potentially gets the value associated with a particular key
211 //! returns true on success/false on failure.
212 /*!
213 \param what the key to lookup
214 \param res a reference used to return the result
215
216 <b>Notes:</b>
217 - If \c res is a \c std::string, every effort will be made
218 to convert the specified element to a string using the
219 \c boost::lexical_cast machinery.
220 - If the dictionary does not contain the key \c what,
221 a KeyErrorException will be thrown.
222 */
223 template <typename T>
224 bool getValIfPresent(const std::string &what, T &res) const {
225 for (const auto &data : _data) {
226 if (data.key == what) {
227 res = from_rdvalue<T>(data.val);
228 return true;
229 }
230 }
231 return false;
232 }
233
234 //! \overload
235 bool getValIfPresent(const std::string &what, std::string &res) const {
236 for (const auto &i : _data) {
237 if (i.key == what) {
238 rdvalue_tostring(i.val, res);
239 return true;
240 }
241 }
242 return false;
243 }
244
245 //----------------------------------------------------------
246 //! \brief Sets the value associated with a key
247 /*!
248
249 \param what the key to set
250 \param val the value to store
251
252 <b>Notes:</b>
253 - If \c val is a <tt>const char *</tt>, it will be converted
254 to a \c std::string for storage.
255 - If the dictionary already contains the key \c what,
256 the value will be replaced.
257 */
258 template <typename T>
259 void setVal(const std::string &what, T &val) {
260 static_assert(!std::is_same_v<T, std::string_view>,
261 "T cannot be string_view");
262 _hasNonPodData = true;
263 for (auto &&data : _data) {
264 if (data.key == what) {
265 RDValue::cleanup_rdvalue(data.val);
266 data.val = val;
267 return;
268 }
269 }
270 _data.push_back(Pair(what, val));
271 }
272
273 template <typename T>
274 void setPODVal(const std::string &what, T val) {
275 static_assert(!std::is_same_v<T, std::string_view>,
276 "T cannot be string_view");
277 // don't change the hasNonPodData status
278 for (auto &&data : _data) {
279 if (data.key == what) {
280 RDValue::cleanup_rdvalue(data.val);
281 data.val = val;
282 return;
283 }
284 }
285 _data.push_back(Pair(what, val));
286 }
287
288 void setVal(const std::string &what, bool val) { setPODVal(what, val); }
289
290 void setVal(const std::string &what, double val) { setPODVal(what, val); }
291
292 void setVal(const std::string &what, float val) { setPODVal(what, val); }
293
294 void setVal(const std::string &what, int val) { setPODVal(what, val); }
295
296 void setVal(const std::string &what, unsigned int val) {
297 setPODVal(what, val);
298 }
299
300 //! \overload
301 void setVal(const std::string &what, const char *val) {
302 std::string h(val);
303 setVal(what, h);
304 }
305
306 //----------------------------------------------------------
307 //! \brief Clears the value associated with a particular key,
308 //! removing the key from the dictionary.
309 /*!
310
311 \param what the key to clear
312
313 */
314 void clearVal(const std::string &what) {
315 for (DataType::iterator it = _data.begin(); it < _data.end(); ++it) {
316 if (it->key == what) {
317 if (_hasNonPodData) {
318 RDValue::cleanup_rdvalue(it->val);
319 }
320 _data.erase(it);
321 return;
322 }
323 }
324 }
325
326 //----------------------------------------------------------
327 //! \brief Clears all keys (and values) from the dictionary.
328 //!
329 void reset() {
330 if (_hasNonPodData) {
331 for (auto &&data : _data) {
332 RDValue::cleanup_rdvalue(data.val);
333 }
334 }
335 DataType data;
336 _data.swap(data);
337 }
338
339 private:
340 DataType _data{}; //!< the actual dictionary
341 bool _hasNonPodData{false}; // if true, need a deep copy
342 // (copy_rdvalue)
343};
344
345template <>
346inline std::string Dict::getVal<std::string>(const std::string &what) const {
347 std::string res;
348 getVal(what, res);
349 return res;
350}
351
352} // namespace RDKit
353#endif
Class to allow us to throw a KeyError from C++ and have it make it back to Python.
Definition Exceptions.h:56
The Dict class can be used to store objects of arbitrary type keyed by strings.
Definition Dict.h:36
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:301
const DataType & getData() const
Access to the underlying data.
Definition Dict.h:139
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:189
Dict(Dict &&other) noexcept=default
void reset()
Clears all keys (and values) from the dictionary.
Definition Dict.h:329
void setPODVal(const std::string &what, T val)
Definition Dict.h:274
Dict & operator=(const Dict &other)
Definition Dict.h:97
STR_VECT keys() const
Returns the set of keys in the dictionary.
Definition Dict.h:160
void setVal(const std::string &what, float val)
Definition Dict.h:292
void setVal(const std::string &what, double val)
Definition Dict.h:290
bool hasVal(const std::string &what) const
Returns whether or not the dictionary contains a particular key.
Definition Dict.h:146
void setVal(const std::string &what, bool val)
Definition Dict.h:288
void setVal(const std::string &what, unsigned int val)
Definition Dict.h:296
void getVal(const std::string &what, std::string &res) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition Dict.h:199
~Dict()
Definition Dict.h:65
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:135
std::vector< Pair > DataType
Definition Dict.h:47
Dict & operator=(Dict &&other) noexcept
Definition Dict.h:119
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:224
void update(const Dict &other, bool preserveExisting=false)
Definition Dict.h:69
void getVal(const std::string &what, T &res) const
Gets the value associated with a particular key.
Definition Dict.h:183
DataType & getData()
Definition Dict.h:140
Dict(const Dict &other)
Definition Dict.h:51
bool getValIfPresent(const std::string &what, std::string &res) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition Dict.h:235
void setVal(const std::string &what, int val)
Definition Dict.h:294
void clearVal(const std::string &what)
Clears the value associated with a particular key, removing the key from the dictionary.
Definition Dict.h:314
void setVal(const std::string &what, T &val)
Sets the value associated with a key.
Definition Dict.h:259
#define RDKIT_RDGENERAL_EXPORT
Definition export.h:401
Std stuff.
std::vector< std::string > STR_VECT
Definition Dict.h:29
bool rdvalue_is(const RDValue_cast_t)
bool rdvalue_tostring(RDValue_cast_t val, std::string &res)
Definition RDValue.h:190
void copy_rdvalue(RDValue &dest, const RDValue &src)
Pair(std::string s)
Definition Dict.h:43
std::string key
Definition Dict.h:39
Pair(std::string s, const RDValue &v)
Definition Dict.h:44
RDValue val
Definition Dict.h:40