/src/rdkit/Code/RDGeneral/RDValue.h
Line | Count | Source |
1 | | // Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc. |
2 | | // All rights reserved. |
3 | | // |
4 | | // Redistribution and use in source and binary forms, with or without |
5 | | // modification, are permitted provided that the following conditions are |
6 | | // met: |
7 | | // |
8 | | // * Redistributions of source code must retain the above copyright |
9 | | // notice, this list of conditions and the following disclaimer. |
10 | | // * Redistributions in binary form must reproduce the above |
11 | | // copyright notice, this list of conditions and the following |
12 | | // disclaimer in the documentation and/or other materials provided |
13 | | // with the distribution. |
14 | | // * Neither the name of Novartis Institutes for BioMedical Research Inc. |
15 | | // nor the names of its contributors may be used to endorse or promote |
16 | | // products derived from this software without specific prior written |
17 | | // permission. |
18 | | // |
19 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | | // |
31 | | #include <RDGeneral/export.h> |
32 | | #ifndef RDKIT_RDVALUE_H |
33 | | #define RDKIT_RDVALUE_H |
34 | | |
35 | | // #define UNSAFE_RDVALUE |
36 | | #ifdef UNSAFE_RDVALUE |
37 | | #include "RDValue-doublemagic.h" |
38 | | #else |
39 | | #include "RDValue-taggedunion.h" |
40 | | #endif |
41 | | |
42 | | #include <boost/algorithm/string.hpp> |
43 | | |
44 | | namespace RDKit { |
45 | | // Common Casts (POD Casts are implementation dependent) |
46 | | // string casts |
47 | | template <> |
48 | 98.5k | inline std::string rdvalue_cast<std::string>(RDValue_cast_t v) { |
49 | 98.5k | if (rdvalue_is<std::string>(v)) { |
50 | 98.5k | return *v.ptrCast<std::string>(); |
51 | 98.5k | } |
52 | 0 | throw std::bad_any_cast(); |
53 | 98.5k | } |
54 | | |
55 | | template <> |
56 | 0 | inline std::string &rdvalue_cast<std::string &>(RDValue_cast_t v) { |
57 | 0 | if (rdvalue_is<std::string>(v)) { |
58 | 0 | return *v.ptrCast<std::string>(); |
59 | 0 | } |
60 | 0 | throw std::bad_any_cast(); |
61 | 0 | } |
62 | | |
63 | | // Special Vecor Casts |
64 | | template <> |
65 | 0 | inline std::vector<double> rdvalue_cast<std::vector<double>>(RDValue_cast_t v) { |
66 | 0 | if (rdvalue_is<std::vector<double>>(v)) { |
67 | 0 | return *v.ptrCast<std::vector<double>>(); |
68 | 0 | } |
69 | 0 | throw std::bad_any_cast(); |
70 | 0 | } |
71 | | |
72 | | template <> |
73 | | inline std::vector<double> &rdvalue_cast<std::vector<double> &>( |
74 | 0 | RDValue_cast_t v) { |
75 | 0 | if (rdvalue_is<std::vector<double>>(v)) { |
76 | 0 | return *v.ptrCast<std::vector<double>>(); |
77 | 0 | } |
78 | 0 | throw std::bad_any_cast(); |
79 | 0 | } |
80 | | |
81 | | template <> |
82 | 0 | inline std::vector<float> rdvalue_cast<std::vector<float>>(RDValue_cast_t v) { |
83 | 0 | if (rdvalue_is<std::vector<float>>(v)) { |
84 | 0 | return *v.ptrCast<std::vector<float>>(); |
85 | 0 | } |
86 | 0 | throw std::bad_any_cast(); |
87 | 0 | } |
88 | | |
89 | | template <> |
90 | | inline std::vector<float> &rdvalue_cast<std::vector<float> &>( |
91 | 0 | RDValue_cast_t v) { |
92 | 0 | if (rdvalue_is<std::vector<float>>(v)) { |
93 | 0 | return *v.ptrCast<std::vector<float>>(); |
94 | 0 | } |
95 | 0 | throw std::bad_any_cast(); |
96 | 0 | } |
97 | | |
98 | | template <> |
99 | | inline std::vector<std::string> rdvalue_cast<std::vector<std::string>>( |
100 | 3.92M | RDValue_cast_t v) { |
101 | 3.92M | if (rdvalue_is<std::vector<std::string>>(v)) { |
102 | 3.92M | return *v.ptrCast<std::vector<std::string>>(); |
103 | 3.92M | } |
104 | 0 | throw std::bad_any_cast(); |
105 | 3.92M | } |
106 | | |
107 | | template <> |
108 | | inline std::vector<std::string> &rdvalue_cast<std::vector<std::string> &>( |
109 | 0 | RDValue_cast_t v) { |
110 | 0 | if (rdvalue_is<std::vector<std::string>>(v)) { |
111 | 0 | return *v.ptrCast<std::vector<std::string>>(); |
112 | 0 | } |
113 | 0 | throw std::bad_any_cast(); |
114 | 0 | } |
115 | | |
116 | | template <> |
117 | 134k | inline std::vector<int> rdvalue_cast<std::vector<int>>(RDValue_cast_t v) { |
118 | 134k | if (rdvalue_is<std::vector<int>>(v)) { |
119 | 134k | return *v.ptrCast<std::vector<int>>(); |
120 | 134k | } |
121 | 0 | throw std::bad_any_cast(); |
122 | 134k | } |
123 | | |
124 | | template <> |
125 | 0 | inline std::vector<int> &rdvalue_cast<std::vector<int> &>(RDValue_cast_t v) { |
126 | 0 | if (rdvalue_is<std::vector<int>>(v)) { |
127 | 0 | return *v.ptrCast<std::vector<int>>(); |
128 | 0 | } |
129 | 0 | throw std::bad_any_cast(); |
130 | 0 | } |
131 | | |
132 | | template <> |
133 | | inline std::vector<unsigned int> rdvalue_cast<std::vector<unsigned int>>( |
134 | 16.4k | RDValue_cast_t v) { |
135 | 16.4k | if (rdvalue_is<std::vector<unsigned int>>(v)) { |
136 | 16.4k | return *v.ptrCast<std::vector<unsigned int>>(); |
137 | 16.4k | } |
138 | 0 | throw std::bad_any_cast(); |
139 | 16.4k | } |
140 | | |
141 | | template <> |
142 | | inline std::vector<unsigned int> &rdvalue_cast<std::vector<unsigned int> &>( |
143 | 0 | RDValue_cast_t v) { |
144 | 0 | if (rdvalue_is<std::vector<unsigned int>>(v)) { |
145 | 0 | return *v.ptrCast<std::vector<unsigned int>>(); |
146 | 0 | } |
147 | 0 | throw std::bad_any_cast(); |
148 | 0 | } |
149 | | |
150 | | // Get boost any |
151 | | template <> |
152 | 0 | inline std::any rdvalue_cast<std::any>(RDValue_cast_t v) { |
153 | 0 | if (rdvalue_is<std::any>(v)) { |
154 | 0 | return *v.ptrCast<std::any>(); |
155 | 0 | } |
156 | 0 | throw std::bad_any_cast(); |
157 | 0 | } |
158 | | |
159 | | template <> |
160 | 0 | inline std::any &rdvalue_cast<std::any &>(RDValue_cast_t v) { |
161 | 0 | if (rdvalue_is<std::any>(v)) { |
162 | 0 | return *v.ptrCast<std::any>(); |
163 | 0 | } |
164 | 0 | throw std::bad_any_cast(); |
165 | 0 | } |
166 | | |
167 | | template <> |
168 | 0 | inline const std::any &rdvalue_cast<const std::any &>(RDValue_cast_t v) { |
169 | 0 | if (rdvalue_is<std::any>(v)) { |
170 | 0 | return *v.ptrCast<std::any>(); |
171 | 0 | } |
172 | 0 | throw std::bad_any_cast(); |
173 | 0 | } |
174 | | |
175 | | ///////////////////////////////////////////////////////////////////////////////////// |
176 | | // lexical casts... |
177 | | template <class T> |
178 | 0 | std::string vectToString(RDValue val) { |
179 | 0 | const std::vector<T> &tv = rdvalue_cast<std::vector<T> &>(val); |
180 | 0 | std::ostringstream sstr; |
181 | 0 | sstr.imbue(std::locale("C")); |
182 | 0 | sstr << std::setprecision(17); |
183 | 0 | sstr << "["; |
184 | 0 | if (!tv.empty()) { |
185 | 0 | std::copy(tv.begin(), tv.end() - 1, std::ostream_iterator<T>(sstr, ",")); |
186 | 0 | sstr << tv.back(); |
187 | 0 | } |
188 | 0 | sstr << "]"; |
189 | 0 | return sstr.str(); |
190 | 0 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > RDKit::vectToString<double>(RDKit::RDValue) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > RDKit::vectToString<float>(RDKit::RDValue) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > RDKit::vectToString<int>(RDKit::RDValue) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > RDKit::vectToString<unsigned int>(RDKit::RDValue) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > RDKit::vectToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(RDKit::RDValue) |
191 | | |
192 | 98.5k | inline bool rdvalue_tostring(RDValue_cast_t val, std::string &res) { |
193 | 98.5k | switch (val.getTag()) { |
194 | 98.5k | case RDTypeTag::StringTag: |
195 | 98.5k | res = rdvalue_cast<std::string>(val); |
196 | 98.5k | break; |
197 | 0 | case RDTypeTag::IntTag: |
198 | 0 | res = boost::lexical_cast<std::string>(rdvalue_cast<int>(val)); |
199 | 0 | break; |
200 | 0 | case RDTypeTag::DoubleTag: { |
201 | 0 | Utils::LocaleSwitcher ls; // for lexical cast... |
202 | 0 | res = boost::lexical_cast<std::string>(rdvalue_cast<double>(val)); |
203 | 0 | break; |
204 | 0 | } |
205 | 0 | case RDTypeTag::UnsignedIntTag: |
206 | 0 | res = boost::lexical_cast<std::string>(rdvalue_cast<unsigned int>(val)); |
207 | 0 | break; |
208 | 0 | #ifdef RDVALUE_HASBOOL |
209 | 0 | case RDTypeTag::BoolTag: |
210 | 0 | res = boost::lexical_cast<std::string>(rdvalue_cast<bool>(val)); |
211 | 0 | break; |
212 | 0 | #endif |
213 | 0 | case RDTypeTag::FloatTag: { |
214 | 0 | Utils::LocaleSwitcher ls; // for lexical cast... |
215 | 0 | res = boost::lexical_cast<std::string>(rdvalue_cast<float>(val)); |
216 | 0 | break; |
217 | 0 | } |
218 | 0 | case RDTypeTag::VecDoubleTag: { |
219 | | // vectToString uses std::imbue for locale |
220 | 0 | res = vectToString<double>(val); |
221 | 0 | break; |
222 | 0 | } |
223 | 0 | case RDTypeTag::VecFloatTag: { |
224 | | // vectToString uses std::imbue for locale |
225 | 0 | res = vectToString<float>(val); |
226 | 0 | break; |
227 | 0 | } |
228 | 0 | case RDTypeTag::VecIntTag: |
229 | 0 | res = vectToString<int>(val); |
230 | 0 | break; |
231 | 0 | case RDTypeTag::VecUnsignedIntTag: |
232 | 0 | res = vectToString<unsigned int>(val); |
233 | 0 | break; |
234 | 0 | case RDTypeTag::VecStringTag: |
235 | 0 | res = vectToString<std::string>(val); |
236 | 0 | break; |
237 | 0 | case RDTypeTag::AnyTag: { |
238 | 0 | Utils::LocaleSwitcher ls; // for lexical cast... |
239 | 0 | try { |
240 | 0 | res = std::any_cast<std::string>(rdvalue_cast<std::any &>(val)); |
241 | 0 | } catch (const std::bad_any_cast &) { |
242 | 0 | auto &rdtype = rdvalue_cast<std::any &>(val).type(); |
243 | 0 | if (rdtype == typeid(long)) { |
244 | 0 | res = boost::lexical_cast<std::string>( |
245 | 0 | std::any_cast<long>(rdvalue_cast<std::any &>(val))); |
246 | 0 | } else if (rdtype == typeid(int64_t)) { |
247 | 0 | res = boost::lexical_cast<std::string>( |
248 | 0 | std::any_cast<int64_t>(rdvalue_cast<std::any &>(val))); |
249 | 0 | } else if (rdtype == typeid(uint64_t)) { |
250 | 0 | res = boost::lexical_cast<std::string>( |
251 | 0 | std::any_cast<uint64_t>(rdvalue_cast<std::any &>(val))); |
252 | 0 | } else if (rdtype == typeid(unsigned long)) { |
253 | 0 | res = boost::lexical_cast<std::string>( |
254 | 0 | std::any_cast<unsigned long>(rdvalue_cast<std::any &>(val))); |
255 | 0 | } else { |
256 | 0 | throw; |
257 | 0 | return false; |
258 | 0 | } |
259 | 0 | } |
260 | 0 | break; |
261 | 0 | } |
262 | 0 | default: |
263 | 0 | res = ""; |
264 | 98.5k | } |
265 | 98.5k | return true; |
266 | 98.5k | } |
267 | | |
268 | | // from_rdvalue -> converts string values to appropriate types |
269 | | template <class T> |
270 | | typename boost::enable_if<boost::is_arithmetic<T>, T>::type from_rdvalue( |
271 | 31.6M | RDValue_cast_t arg) { |
272 | 31.6M | T res; |
273 | 31.6M | if (arg.getTag() == RDTypeTag::StringTag) { |
274 | 6 | Utils::LocaleSwitcher ls; |
275 | 6 | try { |
276 | 6 | res = rdvalue_cast<T>(arg); |
277 | 6 | } catch (const std::bad_any_cast &exc) { |
278 | 6 | try { |
279 | 6 | std::string val = rdvalue_cast<std::string>(arg); |
280 | | // trim only the right characters, this mimics how SD values |
281 | | // work on read, they will be trimmed by the MolFile parser |
282 | 6 | boost::trim_right(val); |
283 | 6 | res = boost::lexical_cast<T>(val); |
284 | 6 | } catch (...) { |
285 | 0 | throw exc; |
286 | 0 | } |
287 | 6 | } |
288 | 31.6M | } else { |
289 | 31.6M | res = rdvalue_cast<T>(arg); |
290 | 31.6M | } |
291 | 31.6M | return res; |
292 | 31.6M | } boost::enable_if<boost::is_arithmetic<int>, int>::type RDKit::from_rdvalue<int>(RDKit::RDValue) Line | Count | Source | 271 | 180k | RDValue_cast_t arg) { | 272 | 180k | T res; | 273 | 180k | if (arg.getTag() == RDTypeTag::StringTag) { | 274 | 6 | Utils::LocaleSwitcher ls; | 275 | 6 | try { | 276 | 6 | res = rdvalue_cast<T>(arg); | 277 | 6 | } catch (const std::bad_any_cast &exc) { | 278 | 6 | try { | 279 | 6 | std::string val = rdvalue_cast<std::string>(arg); | 280 | | // trim only the right characters, this mimics how SD values | 281 | | // work on read, they will be trimmed by the MolFile parser | 282 | 6 | boost::trim_right(val); | 283 | 6 | res = boost::lexical_cast<T>(val); | 284 | 6 | } catch (...) { | 285 | 0 | throw exc; | 286 | 0 | } | 287 | 6 | } | 288 | 180k | } else { | 289 | 180k | res = rdvalue_cast<T>(arg); | 290 | 180k | } | 291 | 180k | return res; | 292 | 180k | } |
Unexecuted instantiation: boost::enable_if<boost::is_arithmetic<short>, short>::type RDKit::from_rdvalue<short>(RDKit::RDValue) Unexecuted instantiation: boost::enable_if<boost::is_arithmetic<signed char>, signed char>::type RDKit::from_rdvalue<signed char>(RDKit::RDValue) boost::enable_if<boost::is_arithmetic<unsigned int>, unsigned int>::type RDKit::from_rdvalue<unsigned int>(RDKit::RDValue) Line | Count | Source | 271 | 31.4M | RDValue_cast_t arg) { | 272 | 31.4M | T res; | 273 | 31.4M | if (arg.getTag() == RDTypeTag::StringTag) { | 274 | 0 | Utils::LocaleSwitcher ls; | 275 | 0 | try { | 276 | 0 | res = rdvalue_cast<T>(arg); | 277 | 0 | } catch (const std::bad_any_cast &exc) { | 278 | 0 | try { | 279 | 0 | std::string val = rdvalue_cast<std::string>(arg); | 280 | | // trim only the right characters, this mimics how SD values | 281 | | // work on read, they will be trimmed by the MolFile parser | 282 | 0 | boost::trim_right(val); | 283 | 0 | res = boost::lexical_cast<T>(val); | 284 | 0 | } catch (...) { | 285 | 0 | throw exc; | 286 | 0 | } | 287 | 0 | } | 288 | 31.4M | } else { | 289 | 31.4M | res = rdvalue_cast<T>(arg); | 290 | 31.4M | } | 291 | 31.4M | return res; | 292 | 31.4M | } |
boost::enable_if<boost::is_arithmetic<bool>, bool>::type RDKit::from_rdvalue<bool>(RDKit::RDValue) Line | Count | Source | 271 | 43 | RDValue_cast_t arg) { | 272 | 43 | T res; | 273 | 43 | if (arg.getTag() == RDTypeTag::StringTag) { | 274 | 0 | Utils::LocaleSwitcher ls; | 275 | 0 | try { | 276 | 0 | res = rdvalue_cast<T>(arg); | 277 | 0 | } catch (const std::bad_any_cast &exc) { | 278 | 0 | try { | 279 | 0 | std::string val = rdvalue_cast<std::string>(arg); | 280 | | // trim only the right characters, this mimics how SD values | 281 | | // work on read, they will be trimmed by the MolFile parser | 282 | 0 | boost::trim_right(val); | 283 | 0 | res = boost::lexical_cast<T>(val); | 284 | 0 | } catch (...) { | 285 | 0 | throw exc; | 286 | 0 | } | 287 | 0 | } | 288 | 43 | } else { | 289 | 43 | res = rdvalue_cast<T>(arg); | 290 | 43 | } | 291 | 43 | return res; | 292 | 43 | } |
Unexecuted instantiation: boost::enable_if<boost::is_arithmetic<float>, float>::type RDKit::from_rdvalue<float>(RDKit::RDValue) Unexecuted instantiation: boost::enable_if<boost::is_arithmetic<double>, double>::type RDKit::from_rdvalue<double>(RDKit::RDValue) Unexecuted instantiation: boost::enable_if<boost::is_arithmetic<unsigned long>, unsigned long>::type RDKit::from_rdvalue<unsigned long>(RDKit::RDValue) |
293 | | |
294 | | template <class T> |
295 | | typename boost::disable_if<boost::is_arithmetic<T>, T>::type from_rdvalue( |
296 | 4.07M | RDValue_cast_t arg) { |
297 | 4.07M | return rdvalue_cast<T>(arg); |
298 | 4.07M | } boost::disable_if<boost::is_arithmetic<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >::type RDKit::from_rdvalue<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(RDKit::RDValue) Line | Count | Source | 296 | 3.92M | RDValue_cast_t arg) { | 297 | 3.92M | return rdvalue_cast<T>(arg); | 298 | 3.92M | } |
Unexecuted instantiation: boost::disable_if<boost::is_arithmetic<ExplicitBitVect const&>, ExplicitBitVect const&>::type RDKit::from_rdvalue<ExplicitBitVect const&>(RDKit::RDValue) boost::disable_if<boost::is_arithmetic<std::__1::vector<int, std::__1::allocator<int> > >, std::__1::vector<int, std::__1::allocator<int> > >::type RDKit::from_rdvalue<std::__1::vector<int, std::__1::allocator<int> > >(RDKit::RDValue) Line | Count | Source | 296 | 134k | RDValue_cast_t arg) { | 297 | 134k | return rdvalue_cast<T>(arg); | 298 | 134k | } |
boost::disable_if<boost::is_arithmetic<std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > >, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > >::type RDKit::from_rdvalue<std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > >(RDKit::RDValue) Line | Count | Source | 296 | 16.4k | RDValue_cast_t arg) { | 297 | 16.4k | return rdvalue_cast<T>(arg); | 298 | 16.4k | } |
|
299 | | } // namespace RDKit |
300 | | #endif |