Skip to content

Commit

Permalink
Add ValueRef Value type for dealing with references. #109
Browse files Browse the repository at this point in the history
  • Loading branch information
billyquith committed Feb 23, 2019
1 parent 04d2a9e commit c6d3521
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 58 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ set(SRC_HEADERS
include/ponder/detail/util.hpp
include/ponder/detail/valueimpl.hpp
include/ponder/detail/valueprovider.hpp
include/ponder/detail/valueref.hpp
include/ponder/detail/variant.hpp
include/ponder/detail/variant_recursive_wrapper.hpp
# Qt
Expand Down
123 changes: 123 additions & 0 deletions include/ponder/detail/valueref.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/****************************************************************************
**
** This file is part of the Ponder library, formerly CAMP.
**
** The MIT License (MIT)
**
** Copyright (C) 2009-2014 TEGESO/TEGESOFT and/or its subsidiary(-ies) and mother company.
** Copyright (C) 2015-2019 Nick Trout.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/

#pragma once
#ifndef PONDER_VALUE_REF_HPP
#define PONDER_VALUE_REF_HPP

#include <ponder/config.hpp>
#include <ponder/type.hpp>

namespace ponder {
namespace detail {

class ValueRef
{
public:

template <typename T>
static ValueRef make(T* p)
{
return ValueRef(p, Type<T>::info());
}

template <typename T>
static ValueRef make(T& p)
{
return ValueRef(&p, std::type_index(typeid(T)));
}

ValueRef(const ValueRef&) = default;

ValueRef& operator= (const ValueRef&) = delete;

bool operator< (const ValueRef& other) const
{
return m_type->less(m_ptr, other.m_ptr);
}

bool operator== (const ValueRef& other) const
{
return m_type->equal(m_ptr, other.m_ptr);
}

template <typename T>
T* getRef()
{
return static_cast<T*>(const_cast<void*>(m_ptr));
}

template <typename T>
const T* getRef() const
{
return static_cast<const T*>(m_ptr);
}

private:

struct IType
{
virtual ~IType() {}
virtual bool less(const void *a, const void *b) const = 0;
virtual bool equal(const void *a, const void *b) const = 0;
};

template <typename T>
struct Type final : public IType
{
static const IType* info()
{
static const Type<T> i;
return &i;
}

bool less(const void *a, const void *b) const final
{
return *static_cast<const T*>(a) < *static_cast<const T*>(b);
}
bool equal(const void *a, const void *b) const final
{
return *static_cast<const T*>(a) == *static_cast<const T*>(b);
}
};

ValueRef(void *p, const IType *t)
: m_ptr(p)
, m_type(t)
{}

const void * const m_ptr;
//std::type_index m_type;
const IType * const m_type;
};

} // detail
} // Ponder

#endif // PONDER_VALUE_REF_HPP
1 change: 1 addition & 0 deletions include/ponder/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ enum class ValueKind
String, ///< String types (`char*`, `ponder::String`)
Enum, ///< Enumerated types
Array, ///< Array types (`T[]`, `std::vector`, `std::list`)
Reference, ///< Reference types (`T*`, `const T*`, `T&`, `const T&`)
User ///< User-defined classes
};

Expand Down
5 changes: 3 additions & 2 deletions include/ponder/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,9 @@ class PONDER_API Value
private:

typedef mapbox::util::variant<
NoType, bool, long, double, ponder::String, EnumObject, UserObject
> Variant;
NoType, bool, long, double, ponder::String,
EnumObject, UserObject, detail::ValueRef
> Variant;

Variant m_value; // Stored value
ValueKind m_type; // Ponder type of the value
Expand Down
19 changes: 10 additions & 9 deletions include/ponder/value.inl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ template <typename T> struct IsUserType {
static constexpr bool value = std::is_class<RawType>::value
&& !std::is_same<RawType, Value>::value
&& !std::is_same<RawType, UserObject>::value
&& !std::is_same<RawType, detail::ValueRef>::value
&& !std::is_same<RawType, ponder::String>::value;
};

Expand Down Expand Up @@ -68,19 +69,19 @@ struct ValueTo<T*, typename std::enable_if<!hasStaticTypeDecl<T>()>::type>
{
static T* convert(const Value& value)
{
return static_cast<T*>(value.to<UserObject>().pointer());
return value.to<detail::ValueRef>().getRef<T>();
}
};

// Convert Values to references for basic types
template <typename T>
struct ValueTo<T&, typename std::enable_if<!hasStaticTypeDecl<T>()>::type>
{
static T convert(const Value& value)
{
return *static_cast<T*>(value.to<UserObject>().pointer());
}
};
//template <typename T>
//struct ValueTo<T&, typename std::enable_if<!hasStaticTypeDecl<T>()>::type>
//{
// static T convert(const Value& value)
// {
// return *static_cast<T*>(value.to<UserObject>().pointer());
// }
//};

} // namespace detail

Expand Down
84 changes: 50 additions & 34 deletions include/ponder/valuemapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <ponder/arraymapper.hpp>
#include <ponder/errors.hpp>
#include <ponder/detail/util.hpp>
#include <ponder/detail/valueref.hpp>

/**
* \namespace ponder_ext
Expand Down Expand Up @@ -149,6 +150,8 @@ struct ValueMapper
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::mapType<T>()));}
static T from(const ponder::EnumObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::mapType<T>()));}
static T from(const ponder::detail::ValueRef&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Reference, ponder::mapType<T>()));}
static T from(const ponder::UserObject& source)
{return source.get<T>();}
};
Expand All @@ -170,12 +173,12 @@ struct ValueMapper<T, typename std::enable_if<std::is_abstract<T>::value>::type>
template <typename T>
struct ValueMapper<T*, typename std::enable_if<!ponder::detail::hasStaticTypeDecl<T>()>::type>
{
static const ponder::ValueKind kind = ponder::ValueKind::User;
static const ponder::ValueKind kind = ponder::ValueKind::Reference;

static ponder::detail::ValueRef to(T* source) {return ponder::detail::ValueRef::make(source);}

static T* from(const ponder::detail::ValueRef& source) {return source.getRef<T>();}

static ponder::UserObject to(T* source) {return ponder::UserObject::makeRef(source);}

static T* from(const ponder::UserObject& source) {return static_cast<T*>(source.pointer());}

static T from(bool)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Boolean,ponder::mapType<T>()));}
static T from(long)
Expand All @@ -186,32 +189,34 @@ struct ValueMapper<T*, typename std::enable_if<!ponder::detail::hasStaticTypeDec
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::mapType<T>()));}
static T from(const ponder::EnumObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::mapType<T>()));}
static T from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::User, ponder::mapType<T>()));}
};

/**
* Specialization of ValueMapper for pointers to basic types
* - Used for pass by-reference parameters that are non-registered types.
*/
template <typename T>
struct ValueMapper<T&, typename std::enable_if<!ponder::detail::hasStaticTypeDecl<T>()>::type>
{
static const ponder::ValueKind kind = ponder::ValueKind::User;
static ponder::UserObject to(T& source) {return ponder::UserObject::makeRef(source);}
static T from(const ponder::UserObject& source) {return *static_cast<T*>(source.pointer());}
static T from(bool)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Boolean,ponder::mapType<T>()));}
static T from(long)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Integer,ponder::mapType<T>()));}
static T from(double)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Real, ponder::mapType<T>()));}
static T from(const ponder::String&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::mapType<T>()));}
static T from(const ponder::EnumObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::mapType<T>()));}
};
///**
// * Specialization of ValueMapper for pointers to basic types
// * - Used for pass by-reference parameters that are non-registered types.
// */
//template <typename T>
//struct ValueMapper<T&, typename std::enable_if<!ponder::detail::hasStaticTypeDecl<T>()>::type>
//{
// static const ponder::ValueKind kind = ponder::ValueKind::User;
//
// static ponder::UserObject to(T& source) {return ponder::UserObject::makeRef(source);}
//
// static T from(const ponder::UserObject& source) {return *static_cast<T*>(source.pointer());}
//
// static T from(bool)
// {PONDER_ERROR(ponder::BadType(ponder::ValueKind::Boolean,ponder::mapType<T>()));}
// static T from(long)
// {PONDER_ERROR(ponder::BadType(ponder::ValueKind::Integer,ponder::mapType<T>()));}
// static T from(double)
// {PONDER_ERROR(ponder::BadType(ponder::ValueKind::Real, ponder::mapType<T>()));}
// static T from(const ponder::String&)
// {PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::mapType<T>()));}
// static T from(const ponder::EnumObject&)
// {PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::mapType<T>()));}
//};

/**
* Specialization of ValueMapper for booleans
Expand All @@ -228,6 +233,7 @@ struct ValueMapper<bool>
static bool from(const ponder::String& source) {return ponder::detail::convert<bool>(source);}
static bool from(const ponder::EnumObject& source) {return source.value() != 0;}
static bool from(const ponder::UserObject& source) {return source.pointer() != nullptr;}
static bool from(const ponder::detail::ValueRef& source) {return source.getRef<bool>();}
};

/**
Expand All @@ -250,6 +256,7 @@ struct ValueMapper<T,
static T from(const ponder::EnumObject& source) {return static_cast<T>(source.value());}
static T from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::User, ponder::ValueKind::Integer));}
static T from(const ponder::detail::ValueRef& source) {return *source.getRef<T>();}
};

/*
Expand All @@ -272,6 +279,7 @@ struct ValueMapper<T,
static T from(const ponder::EnumObject& source) {return static_cast<T>(source.value());}
static T from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::User, ponder::ValueKind::Real));}
static T from(const ponder::detail::ValueRef& source) {return *source.getRef<T>();}
};

/**
Expand All @@ -295,6 +303,8 @@ struct ValueMapper<ponder::String>
{return ponder::String(source.name());}
static ponder::String from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::User, ponder::ValueKind::String));}
static ponder::String from(const ponder::detail::ValueRef& source)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Reference, ponder::ValueKind::String));}
};

template <>
Expand Down Expand Up @@ -378,6 +388,8 @@ struct ValueMapper<T, typename std::enable_if<std::is_enum<T>::value>::type>
{return static_cast<T>(source.value());}
static T from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::User, ponder::ValueKind::Enum));}
static T from(const ponder::detail::ValueRef& source)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Reference, ponder::ValueKind::Enum));}

// The string -> enum conversion involves a little more work:
// we try two different conversions (as a name and as a value)
Expand Down Expand Up @@ -410,16 +422,18 @@ struct ValueMapper<ponder::EnumObject>
static const ponder::EnumObject& to(const ponder::EnumObject& source) {return source;}
static const ponder::EnumObject& from(const ponder::EnumObject& source) {return source;}

static ponder::UserObject from(bool)
static ponder::EnumObject from(bool)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Boolean, ponder::ValueKind::Enum));}
static ponder::UserObject from(long)
static ponder::EnumObject from(long)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Integer, ponder::ValueKind::Enum));}
static ponder::UserObject from(double)
static ponder::EnumObject from(double)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Real, ponder::ValueKind::Enum));}
static ponder::UserObject from(const ponder::String&)
static ponder::EnumObject from(const ponder::String&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::ValueKind::Enum));}
static ponder::UserObject from(const ponder::UserObject&)
static ponder::EnumObject from(const ponder::UserObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::ValueKind::Enum));}
static ponder::EnumObject from(const ponder::detail::ValueRef& source)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Reference, ponder::ValueKind::Enum));}
};

/**
Expand Down Expand Up @@ -453,6 +467,8 @@ struct ValueMapper<ponder::UserObject>
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::String, ponder::ValueKind::User));}
static ponder::UserObject from(const ponder::EnumObject&)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Enum, ponder::ValueKind::User));}
static ponder::UserObject from(const ponder::detail::ValueRef& source)
{PONDER_ERROR(ponder::BadType(ponder::ValueKind::Reference, ponder::ValueKind::User));}
};

/**
Expand Down
11 changes: 6 additions & 5 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ static const char* c_typeNames[] =
{
"none", // ValueKind::None
"bool", // ValueKind::Boolean
"int", // ValueKind::Integer,
"real", // ValueKind::Real,
"string", // ValueKind::String,
"enum", // ValueKind::Enum,
"array", // ValueKind::Array,
"int", // ValueKind::Integer
"real", // ValueKind::Real
"string", // ValueKind::String
"enum", // ValueKind::Enum
"array", // ValueKind::Array
"reference",// ValueKind::Reference
"user", // ValueKind::User
};

Expand Down
Loading

0 comments on commit c6d3521

Please sign in to comment.