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 
42 namespace RDKit {
43 // Common Casts (POD Casts are implementation dependent)
44 // string casts
45 template <>
46 inline 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 
53 template <>
54 inline 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
62 template <>
63 inline 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 
70 template <>
71 inline std::vector<double> &rdvalue_cast<std::vector<double> &>(
72  RDValue_cast_t v) {
73  if (rdvalue_is<std::vector<double>>(v)) {
74  return *v.ptrCast<std::vector<double>>();
75  }
76  throw boost::bad_any_cast();
77 }
78 
79 template <>
80 inline 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 
87 template <>
88 inline std::vector<float> &rdvalue_cast<std::vector<float> &>(
89  RDValue_cast_t v) {
90  if (rdvalue_is<std::vector<float>>(v)) {
91  return *v.ptrCast<std::vector<float>>();
92  }
93  throw boost::bad_any_cast();
94 }
95 
96 template <>
97 inline std::vector<std::string> rdvalue_cast<std::vector<std::string>>(
98  RDValue_cast_t v) {
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 
105 template <>
106 inline 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 
114 template <>
115 inline 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 
122 template <>
123 inline 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 
130 template <>
131 inline 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 
139 template <>
140 inline 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
149 template <>
150 inline 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 
157 template <>
158 inline 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 
165 template <>
166 inline 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...
175 template <class T>
176 std::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 
187 inline bool rdvalue_tostring(RDValue_cast_t val, std::string &res) {
188  switch (val.getTag()) {
190  res = rdvalue_cast<std::string>(val);
191  break;
192  case RDTypeTag::IntTag:
193  res = boost::lexical_cast<std::string>(rdvalue_cast<int>(val));
194  break;
195  case RDTypeTag::DoubleTag: {
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
204  case RDTypeTag::BoolTag:
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  }
218  case RDTypeTag::VecFloatTag: {
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
258 template <class T>
259 typename 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 
279 template <class T>
280 typename 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:18
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
boost::enable_if< boost::is_arithmetic< T >, T >::type from_rdvalue(RDValue_cast_t arg)
Definition: RDValue.h:259
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::uint64_t getTag() const