RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
RDValue.h
Go to the documentation of this file.
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
44namespace RDKit {
45// Common Casts (POD Casts are implementation dependent)
46// string casts
47template <>
50 return *v.ptrCast<std::string>();
51 }
52 throw std::bad_any_cast();
53}
54
55template <>
58 return *v.ptrCast<std::string>();
59 }
60 throw std::bad_any_cast();
61}
62
63// Special Vecor Casts
64template <>
65inline std::vector<double> rdvalue_cast<std::vector<double>>(RDValue_cast_t v) {
66 if (rdvalue_is<std::vector<double>>(v)) {
67 return *v.ptrCast<std::vector<double>>();
68 }
69 throw std::bad_any_cast();
70}
71
72template <>
73inline std::vector<double> &rdvalue_cast<std::vector<double> &>(
75 if (rdvalue_is<std::vector<double>>(v)) {
76 return *v.ptrCast<std::vector<double>>();
77 }
78 throw std::bad_any_cast();
79}
80
81template <>
82inline std::vector<float> rdvalue_cast<std::vector<float>>(RDValue_cast_t v) {
83 if (rdvalue_is<std::vector<float>>(v)) {
84 return *v.ptrCast<std::vector<float>>();
85 }
86 throw std::bad_any_cast();
87}
88
89template <>
90inline std::vector<float> &rdvalue_cast<std::vector<float> &>(
92 if (rdvalue_is<std::vector<float>>(v)) {
93 return *v.ptrCast<std::vector<float>>();
94 }
95 throw std::bad_any_cast();
96}
97
98template <>
99inline std::vector<std::string> rdvalue_cast<std::vector<std::string>>(
100 RDValue_cast_t v) {
101 if (rdvalue_is<std::vector<std::string>>(v)) {
102 return *v.ptrCast<std::vector<std::string>>();
103 }
104 throw std::bad_any_cast();
105}
106
107template <>
108inline std::vector<std::string> &rdvalue_cast<std::vector<std::string> &>(
109 RDValue_cast_t v) {
110 if (rdvalue_is<std::vector<std::string>>(v)) {
111 return *v.ptrCast<std::vector<std::string>>();
112 }
113 throw std::bad_any_cast();
114}
115
116template <>
117inline std::vector<int> rdvalue_cast<std::vector<int>>(RDValue_cast_t v) {
118 if (rdvalue_is<std::vector<int>>(v)) {
119 return *v.ptrCast<std::vector<int>>();
120 }
121 throw std::bad_any_cast();
122}
123
124template <>
125inline std::vector<int> &rdvalue_cast<std::vector<int> &>(RDValue_cast_t v) {
126 if (rdvalue_is<std::vector<int>>(v)) {
127 return *v.ptrCast<std::vector<int>>();
128 }
129 throw std::bad_any_cast();
130}
131
132template <>
133inline std::vector<unsigned int> rdvalue_cast<std::vector<unsigned int>>(
134 RDValue_cast_t v) {
135 if (rdvalue_is<std::vector<unsigned int>>(v)) {
136 return *v.ptrCast<std::vector<unsigned int>>();
137 }
138 throw std::bad_any_cast();
139}
140
141template <>
142inline std::vector<unsigned int> &rdvalue_cast<std::vector<unsigned int> &>(
143 RDValue_cast_t v) {
144 if (rdvalue_is<std::vector<unsigned int>>(v)) {
145 return *v.ptrCast<std::vector<unsigned int>>();
146 }
147 throw std::bad_any_cast();
148}
149
150// Get boost any
151template <>
153 if (rdvalue_is<std::any>(v)) {
154 return *v.ptrCast<std::any>();
155 }
156 throw std::bad_any_cast();
157}
158
159template <>
161 if (rdvalue_is<std::any>(v)) {
162 return *v.ptrCast<std::any>();
163 }
164 throw std::bad_any_cast();
165}
166
167template <>
169 if (rdvalue_is<std::any>(v)) {
170 return *v.ptrCast<std::any>();
171 }
172 throw std::bad_any_cast();
173}
174
175/////////////////////////////////////////////////////////////////////////////////////
176// lexical casts...
177template <class T>
178std::string vectToString(RDValue val) {
179 const std::vector<T> &tv = rdvalue_cast<std::vector<T> &>(val);
180 std::ostringstream sstr;
181 sstr.imbue(std::locale("C"));
182 sstr << std::setprecision(17);
183 sstr << "[";
184 if (!tv.empty()) {
185 std::copy(tv.begin(), tv.end() - 1, std::ostream_iterator<T>(sstr, ","));
186 sstr << tv.back();
187 }
188 sstr << "]";
189 return sstr.str();
190}
191
192inline bool rdvalue_tostring(RDValue_cast_t val, std::string &res) {
193 switch (val.getTag()) {
195 res = rdvalue_cast<std::string>(val);
196 break;
198 res = boost::lexical_cast<std::string>(rdvalue_cast<int>(val));
199 break;
201 Utils::LocaleSwitcher ls; // for lexical cast...
202 res = boost::lexical_cast<std::string>(rdvalue_cast<double>(val));
203 break;
204 }
206 res = boost::lexical_cast<std::string>(rdvalue_cast<unsigned int>(val));
207 break;
208#ifdef RDVALUE_HASBOOL
210 res = boost::lexical_cast<std::string>(rdvalue_cast<bool>(val));
211 break;
212#endif
213 case RDTypeTag::FloatTag: {
214 Utils::LocaleSwitcher ls; // for lexical cast...
215 res = boost::lexical_cast<std::string>(rdvalue_cast<float>(val));
216 break;
217 }
219 // vectToString uses std::imbue for locale
220 res = vectToString<double>(val);
221 break;
222 }
224 // vectToString uses std::imbue for locale
225 res = vectToString<float>(val);
226 break;
227 }
229 res = vectToString<int>(val);
230 break;
233 break;
235 res = vectToString<std::string>(val);
236 break;
237 case RDTypeTag::AnyTag: {
238 Utils::LocaleSwitcher ls; // for lexical cast...
239 try {
240 res = std::any_cast<std::string>(rdvalue_cast<std::any &>(val));
241 } catch (const std::bad_any_cast &) {
242 auto &rdtype = rdvalue_cast<std::any &>(val).type();
243 if (rdtype == typeid(long)) {
244 res = boost::lexical_cast<std::string>(
245 std::any_cast<long>(rdvalue_cast<std::any &>(val)));
246 } else if (rdtype == typeid(int64_t)) {
247 res = boost::lexical_cast<std::string>(
248 std::any_cast<int64_t>(rdvalue_cast<std::any &>(val)));
249 } else if (rdtype == typeid(uint64_t)) {
250 res = boost::lexical_cast<std::string>(
251 std::any_cast<uint64_t>(rdvalue_cast<std::any &>(val)));
252 } else if (rdtype == typeid(unsigned long)) {
253 res = boost::lexical_cast<std::string>(
254 std::any_cast<unsigned long>(rdvalue_cast<std::any &>(val)));
255 } else {
256 throw;
257 return false;
258 }
259 }
260 break;
261 }
262 default:
263 res = "";
264 }
265 return true;
266}
267
268// from_rdvalue -> converts string values to appropriate types
269template <class T>
270typename boost::enable_if<boost::is_arithmetic<T>, T>::type from_rdvalue(
271 RDValue_cast_t arg) {
272 T res;
273 if (arg.getTag() == RDTypeTag::StringTag) {
275 try {
276 res = rdvalue_cast<T>(arg);
277 } catch (const std::bad_any_cast &exc) {
278 try {
279 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 boost::trim_right(val);
283 res = boost::lexical_cast<T>(val);
284 } catch (...) {
285 throw exc;
286 }
287 }
288 } else {
289 res = rdvalue_cast<T>(arg);
290 }
291 return res;
292}
293
294template <class T>
295typename boost::disable_if<boost::is_arithmetic<T>, T>::type from_rdvalue(
296 RDValue_cast_t arg) {
297 return rdvalue_cast<T>(arg);
298}
299} // namespace RDKit
300#endif
static const boost::uint64_t UnsignedIntTag
static const boost::uint64_t StringTag
static const boost::uint64_t VecStringTag
static const boost::uint64_t VecIntTag
static const boost::uint64_t FloatTag
static const boost::uint64_t VecUnsignedIntTag
static const boost::uint64_t DoubleTag
static const boost::uint64_t IntTag
static const boost::uint64_t AnyTag
static const boost::uint64_t VecFloatTag
static const boost::uint64_t VecDoubleTag
static const boost::uint64_t BoolTag
Std stuff.
std::string rdvalue_cast< std::string >(RDValue_cast_t v)
Definition RDValue.h:48
bool rdvalue_is(const RDValue_cast_t)
std::string vectToString(RDValue val)
Definition RDValue.h:178
std::any rdvalue_cast< std::any >(RDValue_cast_t v)
Definition RDValue.h:152
bool rdvalue_tostring(RDValue_cast_t val, std::string &res)
Definition RDValue.h:192
const std::any & rdvalue_cast< const std::any & >(RDValue_cast_t v)
Definition RDValue.h:168
std::any & rdvalue_cast< std::any & >(RDValue_cast_t v)
Definition RDValue.h:160
T rdvalue_cast(RDValue_cast_t v)
std::string & rdvalue_cast< std::string & >(RDValue_cast_t v)
Definition RDValue.h:56
RDValue RDValue_cast_t
boost::enable_if< boost::is_arithmetic< T >, T >::type from_rdvalue(RDValue_cast_t arg)
Definition RDValue.h:270
boost::uint64_t getTag() const