RDValue-taggedunion.h
Go to the documentation of this file.
// Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Novartis Institutes for BioMedical Research Inc.
// nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include <RDGeneral/export.h>
#ifndef RDKIT_RDVALUE_TAGGED_UNION_H
#define RDKIT_RDVALUE_TAGGED_UNION_H
#include <cassert>
#include "Invariant.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <RDGeneral/BoostStartInclude.h>
#include <cstdint>
#include <boost/any.hpp>
#include <boost/utility.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <RDGeneral/BoostEndInclude.h>
#include "LocaleSwitcher.h"
#define RDVALUE_HASBOOL
namespace RDKit {
// RDValue does not dynamically create POD types (kind of like
// cdiggins::any) However, it doesn't use RTTI type info
// directly, it uses a companion short valued type
// to determine what to do.
// For unregistered types, it falls back to boost::any.
// The Size of an RDAny is (sizeof(double) + sizeof(short) == 10 bytes
// (aligned to actually 16 so hard to pass as value type)
//
// For the sake of compatibility, errors throw boost::bad_any_cast
//
// Examples:
//
// RDAny v(2.);
// v = 1;
// std::vector<double> d;
// v == d;
// v.asDoubleVect().push_back(4.)
// rdany_cast<std::vector<double>(v).push_back(4.)
//
// Falls back to boost::any for non registered types
// v = boost::shared_ptr<ROMol>(new ROMol(m));
//
// RDValue does not manange memory of non-pod data
// this must be done externally (string, Any, vector...)
// Tagged union
namespace RDTypeTag {
const short EmptyTag = 0;
const short IntTag = 1;
const short DoubleTag = 2;
const short StringTag = 3;
const short FloatTag = 4;
const short BoolTag = 5;
const short UnsignedIntTag = 6;
const short AnyTag = 7;
const short VecDoubleTag = 8;
const short VecFloatTag = 9;
const short VecIntTag = 10;
const short VecUnsignedIntTag = 11;
const short VecStringTag = 12;
template <class T>
inline short GetTag() {
return AnyTag;
}
template <>
inline short GetTag<double>() {
return DoubleTag;
}
template <>
inline short GetTag<float>() {
return FloatTag;
}
template <>
inline short GetTag<int>() {
return IntTag;
}
template <>
inline short GetTag<unsigned int>() {
return UnsignedIntTag;
}
template <>
inline short GetTag<bool>() {
return BoolTag;
}
template <>
inline short GetTag<std::string>() {
return StringTag;
}
template <>
inline short GetTag<std::vector<double>>() {
return VecDoubleTag;
}
template <>
inline short GetTag<std::vector<float>>() {
return VecFloatTag;
}
template <>
inline short GetTag<std::vector<int>>() {
return VecIntTag;
}
template <>
inline short GetTag<std::vector<unsigned int>>() {
return VecUnsignedIntTag;
}
template <>
inline short GetTag<std::vector<std::string>>() {
return VecStringTag;
}
template <>
inline short GetTag<boost::any>() {
return AnyTag;
}
namespace detail {
union Value {
double d;
float f;
int i;
unsigned u;
bool b;
std::string *s;
boost::any *a;
std::vector<double> *vd;
std::vector<float> *vf;
std::vector<int> *vi;
std::vector<unsigned int> *vu;
std::vector<std::string> *vs;
inline Value() {}
inline Value(double v) : d(v) {}
inline Value(float v) : f(v) {}
inline Value(int v) : i(v) {}
inline Value(unsigned int v) : u(v) {}
inline Value(bool v) : b(v) {}
inline Value(std::string *v) : s(v) {}
inline Value(boost::any *v) : a(v) {}
inline Value(std::vector<double> *v) : vd(v) {}
inline Value(std::vector<float> *v) : vf(v) {}
inline Value(std::vector<int> *v) : vi(v) {}
inline Value(std::vector<unsigned int> *v) : vu(v) {}
inline Value(std::vector<std::string> *v) : vs(v) {}
};
template <class T>
inline T *valuePtrCast(Value value) {
return boost::any_cast<T *>(*value.a);
}
template <>
inline boost::any *valuePtrCast<boost::any>(Value value) {
return value.a;
}
template <>
inline std::string *valuePtrCast<std::string>(Value value) {
return value.s;
}
template <>
inline std::vector<double> *valuePtrCast<std::vector<double>>(Value value) {
return value.vd;
}
template <>
inline std::vector<float> *valuePtrCast<std::vector<float>>(Value value) {
return value.vf;
}
template <>
inline std::vector<int> *valuePtrCast<std::vector<int>>(Value value) {
return value.vi;
}
template <>
inline std::vector<unsigned int> *valuePtrCast<std::vector<unsigned int>>(
Value value) {
return value.vu;
}
template <>
inline std::vector<std::string> *valuePtrCast<std::vector<std::string>>(
Value value) {
return value.vs;
}
} // namespace detail
} // namespace RDTypeTag
struct RDValue {
RDTypeTag::detail::Value value;
short type;
short reserved_tag = 0; // 16 bit alignment
inline RDValue() : value(0.0), type(RDTypeTag::EmptyTag) {}
// Pod Style (Direct storage)
inline RDValue(double v) : value(v), type(RDTypeTag::DoubleTag) {}
inline RDValue(float v) : value(v), type(RDTypeTag::FloatTag) {}
inline RDValue(int v) : value(v), type(RDTypeTag::IntTag) {}
inline RDValue(unsigned v) : value(v), type(RDTypeTag::UnsignedIntTag) {}
inline RDValue(bool v) : value(v), type(RDTypeTag::BoolTag) {}
inline RDValue(boost::any *v) : value(v), type(RDTypeTag::AnyTag) {}
// Copies passed in pointers
inline RDValue(const boost::any &v)
: value(new boost::any(v)), type(RDTypeTag::AnyTag) {}
inline RDValue(const std::string &v)
: value(new std::string(v)), type(RDTypeTag::StringTag){};
template <class T>
inline RDValue(const T &v)
: value(new boost::any(v)), type(RDTypeTag::AnyTag) {}
inline RDValue(const std::vector<double> &v)
: value(new std::vector<double>(v)), type(RDTypeTag::VecDoubleTag) {}
inline RDValue(const std::vector<float> &v)
: value(new std::vector<float>(v)), type(RDTypeTag::VecFloatTag) {}
inline RDValue(const std::vector<int> &v)
: value(new std::vector<int>(v)), type(RDTypeTag::VecIntTag) {}
inline RDValue(const std::vector<unsigned int> &v)
: value(new std::vector<unsigned int>(v)),
type(RDTypeTag::VecUnsignedIntTag) {}
inline RDValue(const std::vector<std::string> &v)
: value(new std::vector<std::string>(v)), type(RDTypeTag::VecStringTag) {}
short getTag() const { return type; }
// ptrCast - unsafe, use rdvalue_cast instead.
template <class T>
inline T *ptrCast() const {
return RDTypeTag::detail::valuePtrCast<T>(value);
}
// RDValue doesn't have an explicit destructor, it must
// be wrapped in a container.
// The idea is that POD types don't need to be destroyed
// and this allows the container optimization possibilities.
void destroy() {
switch (type) {
case RDTypeTag::StringTag:
delete value.s;
break;
case RDTypeTag::AnyTag:
delete value.a;
break;
case RDTypeTag::VecDoubleTag:
delete value.vd;
break;
case RDTypeTag::VecFloatTag:
delete value.vf;
break;
case RDTypeTag::VecIntTag:
delete value.vi;
break;
case RDTypeTag::VecUnsignedIntTag:
delete value.vu;
break;
case RDTypeTag::VecStringTag:
delete value.vs;
break;
default:
break;
}
type = RDTypeTag::EmptyTag;
}
static // Given a type and an RDAnyValue - delete the appropriate structure
inline void
cleanup_rdvalue(RDValue &rdvalue) {
rdvalue.destroy();
}
};
/////////////////////////////////////////////////////////////////////////////////////
// Given two RDValue::Values - copy the appropriate structure
// RDValue doesn't have a copy constructor, the default
// copy act's like a move for better value semantics.
// Containers may need to copy though.
inline void copy_rdvalue(RDValue &dest, const RDValue &src) {
if (&dest == &src) // don't copy over yourself
return;
dest.destroy();
dest.type = src.type;
switch (src.type) {
case RDTypeTag::StringTag:
dest.value.s = new std::string(*src.value.s);
break;
case RDTypeTag::AnyTag:
dest.value.a = new boost::any(*src.value.a);
break;
case RDTypeTag::VecDoubleTag:
dest.value.vd = new std::vector<double>(*src.value.vd);
break;
case RDTypeTag::VecFloatTag:
dest.value.vf = new std::vector<float>(*src.value.vf);
break;
case RDTypeTag::VecIntTag:
dest.value.vi = new std::vector<int>(*src.value.vi);
break;
case RDTypeTag::VecUnsignedIntTag:
dest.value.vu = new std::vector<unsigned int>(*src.value.vu);
break;
case RDTypeTag::VecStringTag:
dest.value.vs = new std::vector<std::string>(*src.value.vs);
break;
default:
dest = src;
}
}
#ifdef RDK_32BIT_BUILD
// avoid register pressure and spilling on 32 bit systems
typedef const RDValue &RDValue_cast_t;
#else
typedef RDValue RDValue_cast_t;
#endif
/////////////////////////////////////////////////////////////////////////////////////
// rdvalue_is<T>
template <class T>
inline bool rdvalue_is(RDValue_cast_t v) {
const short tag =
RDTypeTag::GetTag<typename boost::remove_reference<T>::type>();
if (v.getTag() == tag) return true;
// If we are an Any tag, check the any type info
if (v.getTag() == RDTypeTag::AnyTag) {
return v.value.a->type() == typeid(T);
}
return false;
}
/////////////////////////////////////////////////////////////////////////////////////
// rdvalue_cast<T>
//
// POD types do not support reference semantics. Other types do.
// rdvalue_cast<const std::vector<double> &>(RDValue); // ok
// rdvalue_cast<const float &>(RDValue); // bad_any_cast
// Get stuff stored in boost any
template <class T>
inline T rdvalue_cast(RDValue_cast_t v) {
// Disable reference and pointer casts to POD data.
BOOST_STATIC_ASSERT(!(
(boost::is_pointer<T>::value &&
(boost::is_integral<typename boost::remove_pointer<T>::type>::value ||
boost::is_floating_point<
typename boost::remove_pointer<T>::type>::value)) ||
(boost::is_reference<T>::value &&
(boost::is_integral<typename boost::remove_reference<T>::type>::value ||
boost::is_floating_point<
typename boost::remove_reference<T>::type>::value))));
if (rdvalue_is<boost::any>(v)) {
return boost::any_cast<T>(*v.ptrCast<boost::any>());
}
throw boost::bad_any_cast();
}
// POD casts
template <>
inline double rdvalue_cast<double>(RDValue_cast_t v) {
if (rdvalue_is<double>(v)) return v.value.d;
throw boost::bad_any_cast();
}
template <>
inline float rdvalue_cast<float>(RDValue_cast_t v) {
if (rdvalue_is<float>(v)) return v.value.f;
throw boost::bad_any_cast();
}
template <>
inline int rdvalue_cast<int>(RDValue_cast_t v) {
if (rdvalue_is<int>(v)) return v.value.i;
throw boost::bad_any_cast();
}
template <>
inline unsigned int rdvalue_cast<unsigned int>(RDValue_cast_t v) {
if (rdvalue_is<unsigned int>(v)) return v.value.u;
throw boost::bad_any_cast();
}
template <>
inline bool rdvalue_cast<bool>(RDValue_cast_t v) {
if (rdvalue_is<bool>(v)) return v.value.b;
throw boost::bad_any_cast();
}
} // namespace RDKit
#endif
RDKit::RDValue::ptrCast
T * ptrCast() const
Definition: RDValue-taggedunion.h:257
RDKit::RDValue::RDValue
RDValue(const std::string &v)
Definition: RDValue-taggedunion.h:235
RDKit::RDTypeTag::detail::Value::Value
Value(boost::any *v)
Definition: RDValue-taggedunion.h:171
RDKit::RDTypeTag::detail::Value::vs
std::vector< std::string > * vs
Definition: RDValue-taggedunion.h:162
RDKit::RDTypeTag::GetTag< float >
boost::uint64_t GetTag< float >()
Definition: RDValue-doublemagic.h:122
RDKit::RDTypeTag::detail::Value::vd
std::vector< double > * vd
Definition: RDValue-taggedunion.h:158
RDKit::RDValue::getTag
short getTag() const
Definition: RDValue-taggedunion.h:253
RDKit::RDValue::RDValue
RDValue(unsigned v)
Definition: RDValue-taggedunion.h:227
RDKit::rdvalue_cast< bool >
bool rdvalue_cast< bool >(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:471
RDKit::RDTypeTag::GetTag< int >
boost::uint64_t GetTag< int >()
Definition: RDValue-doublemagic.h:126
RDKit::rdvalue_is< double >
bool rdvalue_is< double >(const RDValue_cast_t)
Definition: RDValue-doublemagic.h:386
RDKit::RDValue::RDValue
RDValue(float v)
Definition: RDValue-taggedunion.h:225
RDKit::RDValue_cast_t
RDValue RDValue_cast_t
Definition: RDValue-doublemagic.h:417
RDKit::RDValue::RDValue
RDValue(const std::vector< unsigned int > &v)
Definition: RDValue-taggedunion.h:247
RDKit::RDTypeTag::FloatTag
static const boost::uint64_t FloatTag
Definition: RDValue-doublemagic.h:97
BoostStartInclude.h
RDKit::RDTypeTag::UnsignedIntTag
static const boost::uint64_t UnsignedIntTag
Definition: RDValue-doublemagic.h:99
RDKit::RDValue::reserved_tag
short reserved_tag
Definition: RDValue-taggedunion.h:220
RDKit::RDTypeTag::GetTag< bool >
boost::uint64_t GetTag< bool >()
Definition: RDValue-doublemagic.h:134
RDKit::RDValue
Definition: RDValue-doublemagic.h:167
RDKit::RDTypeTag::detail::Value
Definition: RDValue-taggedunion.h:150
RDKit::RDTypeTag::detail::Value::Value
Value(std::vector< std::string > *v)
Definition: RDValue-taggedunion.h:176
RDKit::RDTypeTag::detail::Value::Value
Value(std::vector< float > *v)
Definition: RDValue-taggedunion.h:173
RDKit::RDTypeTag::DoubleTag
static const boost::uint64_t DoubleTag
Definition: RDValue-doublemagic.h:96
RDKit::RDTypeTag::detail::Value::Value
Value(std::vector< int > *v)
Definition: RDValue-taggedunion.h:174
RDKit::RDTypeTag::detail::Value::Value
Value()
Definition: RDValue-taggedunion.h:164
RDKit::RDTypeTag::VecDoubleTag
static const boost::uint64_t VecDoubleTag
Definition: RDValue-doublemagic.h:105
RDKit::RDTypeTag::VecUnsignedIntTag
static const boost::uint64_t VecUnsignedIntTag
Definition: RDValue-doublemagic.h:108
RDKit::RDTypeTag::detail::Value::Value
Value(std::vector< unsigned int > *v)
Definition: RDValue-taggedunion.h:175
RDKit::RDValue::RDValue
RDValue(const std::vector< float > &v)
Definition: RDValue-taggedunion.h:243
boost
Definition: RDLog.h:21
RDKit::RDValue::RDValue
RDValue(int v)
Definition: RDValue-taggedunion.h:226
RDKit::RDValue::RDValue
RDValue(const T &v)
Definition: RDValue-taggedunion.h:238
RDKit::rdvalue_cast< int >
int rdvalue_cast< int >(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:458
RDKit::RDTypeTag::detail::Value::s
std::string * s
Definition: RDValue-taggedunion.h:156
BoostEndInclude.h
RDKit::rdvalue_cast
T rdvalue_cast(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:420
RDKit::RDValue::RDValue
RDValue()
Definition: RDValue-taggedunion.h:222
RDKit::RDValue::destroy
void destroy()
Definition: RDValue-taggedunion.h:265
RDKit::RDValue::RDValue
RDValue(const std::vector< std::string > &v)
Definition: RDValue-taggedunion.h:250
RDKit::rdvalue_cast< unsigned int >
unsigned int rdvalue_cast< unsigned int >(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:464
RDKit::RDTypeTag::VecFloatTag
static const boost::uint64_t VecFloatTag
Definition: RDValue-doublemagic.h:106
RDKit::RDTypeTag::EmptyTag
const short EmptyTag
Definition: RDValue-taggedunion.h:83
RDKit::RDValue::type
short type
Definition: RDValue-taggedunion.h:219
RDKit::RDTypeTag::AnyTag
static const boost::uint64_t AnyTag
Definition: RDValue-doublemagic.h:110
RDKit::RDTypeTag::IntTag
static const boost::uint64_t IntTag
Definition: RDValue-doublemagic.h:98
LocaleSwitcher.h
RDKit::RDValue::RDValue
RDValue(bool v)
Definition: RDValue-taggedunion.h:228
RDKit::RDTypeTag::GetTag< unsigned int >
boost::uint64_t GetTag< unsigned int >()
Definition: RDValue-doublemagic.h:130
RDKit::RDTypeTag::detail::Value::b
bool b
Definition: RDValue-taggedunion.h:155
RDKit::RDTypeTag::detail::Value::d
double d
Definition: RDValue-taggedunion.h:151
RDKit::RDTypeTag::GetTag
boost::uint64_t GetTag()
Definition: RDValue-doublemagic.h:114
RDKit::RDValue::cleanup_rdvalue
static void cleanup_rdvalue(RDValue &rdvalue)
Definition: RDValue-taggedunion.h:296
Invariant.h
RDKit::RDTypeTag::detail::Value::Value
Value(int v)
Definition: RDValue-taggedunion.h:167
RDKit::RDTypeTag::detail::Value::vf
std::vector< float > * vf
Definition: RDValue-taggedunion.h:159
RDKit::RDTypeTag::detail::Value::Value
Value(bool v)
Definition: RDValue-taggedunion.h:169
RDKit::RDTypeTag::VecIntTag
static const boost::uint64_t VecIntTag
Definition: RDValue-doublemagic.h:107
RDKit::RDTypeTag::detail::Value::vu
std::vector< unsigned int > * vu
Definition: RDValue-taggedunion.h:161
RDKit::RDTypeTag::StringTag
static const boost::uint64_t StringTag
Definition: RDValue-doublemagic.h:104
RDKit::RDTypeTag::detail::Value::a
boost::any * a
Definition: RDValue-taggedunion.h:157
RDKit::RDTypeTag::detail::Value::u
unsigned u
Definition: RDValue-taggedunion.h:154
RDKit::RDTypeTag::detail::Value::f
float f
Definition: RDValue-taggedunion.h:152
RDKit
Std stuff.
Definition: Atom.h:30
RDKit::RDTypeTag::detail::Value::Value
Value(float v)
Definition: RDValue-taggedunion.h:166
RDKit::RDTypeTag::GetTag< double >
boost::uint64_t GetTag< double >()
Definition: RDValue-doublemagic.h:118
RDKit::RDTypeTag::BoolTag
static const boost::uint64_t BoolTag
Definition: RDValue-doublemagic.h:100
RDKit::RDValue::RDValue
RDValue(double v)
Definition: RDValue-taggedunion.h:224
RDKit::RDTypeTag::detail::Value::Value
Value(double v)
Definition: RDValue-taggedunion.h:165
RDKit::rdvalue_cast< double >
double rdvalue_cast< double >(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:440
RDKit::RDValue::RDValue
RDValue(const boost::any &v)
Definition: RDValue-taggedunion.h:233
RDKit::rdvalue_is
bool rdvalue_is(const RDValue_cast_t)
Definition: RDValue-doublemagic.h:372
RDKit::RDTypeTag::detail::valuePtrCast
T * valuePtrCast(Value value)
Definition: RDValue-taggedunion.h:180
RDKit::RDTypeTag::detail::Value::i
int i
Definition: RDValue-taggedunion.h:153
RDKit::RDTypeTag::VecStringTag
static const boost::uint64_t VecStringTag
Definition: RDValue-doublemagic.h:109
RDKit::RDTypeTag::detail::Value::Value
Value(std::string *v)
Definition: RDValue-taggedunion.h:170
RDKit::rdvalue_cast< float >
float rdvalue_cast< float >(RDValue_cast_t v)
Definition: RDValue-doublemagic.h:446
RDKit::RDTypeTag::detail::Value::Value
Value(unsigned int v)
Definition: RDValue-taggedunion.h:168
RDKit::RDValue::RDValue
RDValue(const std::vector< double > &v)
Definition: RDValue-taggedunion.h:241
RDKit::RDTypeTag::detail::Value::Value
Value(std::vector< double > *v)
Definition: RDValue-taggedunion.h:172
RDKit::RDValue::RDValue
RDValue(const std::vector< int > &v)
Definition: RDValue-taggedunion.h:245
RDKit::copy_rdvalue
void copy_rdvalue(RDValue &dest, const RDValue &src)
Definition: RDValue-doublemagic.h:339
RDKit::RDTypeTag::detail::Value::vi
std::vector< int > * vi
Definition: RDValue-taggedunion.h:160
RDKit::RDValue::RDValue
RDValue(boost::any *v)
Definition: RDValue-taggedunion.h:230
RDKit::RDValue::value
RDTypeTag::detail::Value value
Definition: RDValue-taggedunion.h:218
export.h