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