mirror of https://github.com/SeanOMik/libki.git
pclass: Implement casters between primitives and json object
This commit is contained in:
parent
20f74ee004
commit
def6549bcb
|
@ -5,6 +5,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
set(RAPIDXML_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/third_party)
|
set(RAPIDXML_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/third_party)
|
||||||
add_library(RapidXML INTERFACE)
|
add_library(RapidXML INTERFACE)
|
||||||
target_include_directories(RapidXML INTERFACE ${RAPIDXML_INCLUDE_DIR})
|
target_include_directories(RapidXML INTERFACE ${RAPIDXML_INCLUDE_DIR})
|
||||||
|
set(JSON_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/third_party)
|
||||||
|
add_library(JSON INTERFACE)
|
||||||
|
target_include_directories(JSON INTERFACE ${JSON_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
@ -19,7 +22,7 @@ target_include_directories(${PROJECT_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${PROJECT_SOURCE_DIR}/include
|
${PROJECT_SOURCE_DIR}/include
|
||||||
)
|
)
|
||||||
target_link_libraries(${PROJECT_NAME} RapidXML ${ZLIB_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} RapidXML JSON ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
add_subdirectory("src/dml")
|
add_subdirectory("src/dml")
|
||||||
add_subdirectory("src/pclass")
|
add_subdirectory("src/pclass")
|
||||||
|
|
|
@ -0,0 +1,337 @@
|
||||||
|
#pragma once
|
||||||
|
#include <type_traits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <json.hpp>
|
||||||
|
#include "ki/pclass/Value.h"
|
||||||
|
#include "ki/pclass/types/EnumType.h"
|
||||||
|
|
||||||
|
namespace ki
|
||||||
|
{
|
||||||
|
namespace pclass
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A utility to call ValueCaster::declare<SrcT, DestT> with
|
||||||
|
* bi<N> and bui<N> as the destination type.
|
||||||
|
*
|
||||||
|
* N is automatically decremented until it reaches 0.
|
||||||
|
*/
|
||||||
|
template <typename T, int N = 7>
|
||||||
|
struct bit_integer_declarer
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
bit_integer_declarer<T, N - 1>::declare();
|
||||||
|
ValueCaster::declare<T, bi<N>>();
|
||||||
|
ValueCaster::declare<T, bui<N>>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialization for bit_integer_declarer.
|
||||||
|
* Stop decrementing N when it reaches 0.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
struct bit_integer_declarer<T, 0>
|
||||||
|
{
|
||||||
|
static void declare() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether a type can be assigned to a
|
||||||
|
* nlohmann::json object.
|
||||||
|
*/
|
||||||
|
template <typename SrcT, typename Enable = void>
|
||||||
|
struct is_json_assignable : std::false_type {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All fundamental types can be assigned to a json object.
|
||||||
|
*/
|
||||||
|
template <typename SrcT>
|
||||||
|
struct is_json_assignable<
|
||||||
|
SrcT,
|
||||||
|
typename std::enable_if<std::is_fundamental<SrcT>::value>::type
|
||||||
|
> : std::true_type {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* std::string can be assigned to a json object.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct is_json_assignable<std::string> : std::true_type {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value_caster specialization for the generic case of casting
|
||||||
|
* any json-assignable value to a json object.
|
||||||
|
*/
|
||||||
|
template <typename SrcT>
|
||||||
|
struct value_caster<
|
||||||
|
SrcT, nlohmann::json,
|
||||||
|
typename std::enable_if<is_json_assignable<SrcT>::value>::type
|
||||||
|
>
|
||||||
|
: value_caster_impl<SrcT, nlohmann::json>
|
||||||
|
{
|
||||||
|
Value cast(const Value &value) const override
|
||||||
|
{
|
||||||
|
const nlohmann::json j = value.get<SrcT>();
|
||||||
|
return Value::make_value<nlohmann::json>(j);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value_caster specialization for casting bi<N> and bui<N>
|
||||||
|
* to a json object.
|
||||||
|
*/
|
||||||
|
template <int N, bool Unsigned>
|
||||||
|
struct value_caster<
|
||||||
|
BitInteger<N, Unsigned>, nlohmann::json
|
||||||
|
>
|
||||||
|
: value_caster_impl<BitInteger<N, Unsigned>, nlohmann::json>
|
||||||
|
{
|
||||||
|
using type = typename std::conditional<
|
||||||
|
Unsigned,
|
||||||
|
typename bits<N>::uint_type,
|
||||||
|
typename bits<N>::int_type
|
||||||
|
>::type;
|
||||||
|
|
||||||
|
Value cast(const Value &value) const override
|
||||||
|
{
|
||||||
|
const nlohmann::json j = static_cast<type>(
|
||||||
|
value.get<BitInteger<N, Unsigned>>()
|
||||||
|
);
|
||||||
|
return Value::make_value<nlohmann::json>(j);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value_caster specialization for casting enums to a json object.
|
||||||
|
*/
|
||||||
|
template <typename SrcT>
|
||||||
|
struct value_caster<
|
||||||
|
SrcT, nlohmann::json,
|
||||||
|
typename std::enable_if<std::is_enum<SrcT>::value>::type
|
||||||
|
>
|
||||||
|
: value_caster_impl<SrcT, nlohmann::json>
|
||||||
|
{
|
||||||
|
using underlying_type = typename std::underlying_type<SrcT>::type;
|
||||||
|
|
||||||
|
Value cast(const Value &value) const override
|
||||||
|
{
|
||||||
|
const auto underlying_value =
|
||||||
|
static_cast<underlying_type>(value.get<SrcT>());
|
||||||
|
const nlohmann::json j = underlying_value;
|
||||||
|
return Value::make_value<nlohmann::json>(j);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value_caster specialization for casting enums to bit integer types.
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
typename SrcT,
|
||||||
|
int N, bool Unsigned
|
||||||
|
>
|
||||||
|
struct value_caster<
|
||||||
|
SrcT, BitInteger<N, Unsigned>,
|
||||||
|
typename std::enable_if<std::is_enum<SrcT>::value>::type
|
||||||
|
>
|
||||||
|
: value_caster_impl<SrcT, nlohmann::json>
|
||||||
|
{
|
||||||
|
using underlying_type = typename std::underlying_type<SrcT>::type;
|
||||||
|
|
||||||
|
Value cast(const Value &value) const override
|
||||||
|
{
|
||||||
|
const auto underlying_value =
|
||||||
|
static_cast<underlying_type>(value.get<SrcT>());
|
||||||
|
const auto bit_value = BitInteger<N, Unsigned>(underlying_value);
|
||||||
|
return Value::make_value<BitInteger<N, Unsigned>>(bit_value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct string_cast_t
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writing a int8_t or uint8_t value to a stream will
|
||||||
|
* write a ASCII character, rather than an integer, so
|
||||||
|
* we cast to int16_t/uint16_t before writing.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct string_cast_t<int8_t>
|
||||||
|
{
|
||||||
|
using type = int16_t;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct string_cast_t<uint8_t>
|
||||||
|
{
|
||||||
|
using type = uint16_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enums should be written as 32-bit integers.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
struct string_cast_t<
|
||||||
|
T,
|
||||||
|
typename std::enable_if<std::is_enum<T>::value>::type
|
||||||
|
>
|
||||||
|
{
|
||||||
|
using type = enum_value_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caster implementation for casting any type to string
|
||||||
|
* via std::ostringstream.
|
||||||
|
*/
|
||||||
|
template <typename SrcT>
|
||||||
|
struct value_caster<SrcT, std::string>
|
||||||
|
: value_caster_impl<SrcT, std::string>
|
||||||
|
{
|
||||||
|
Value cast(const Value &value) const override
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
auto casted_value = static_cast<
|
||||||
|
typename string_cast_t<SrcT>::type
|
||||||
|
>(value.get<SrcT>());
|
||||||
|
oss << casted_value;
|
||||||
|
return Value::make_value<std::string>(oss.str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class used by TypeSystem to declare casters for each
|
||||||
|
* primitive type.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct caster_declarer
|
||||||
|
{
|
||||||
|
static void declare() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* caster_declarer specialization for all integral types.
|
||||||
|
* Integers can cast to other integer types, as well as floating point
|
||||||
|
* integers, std::string and nlohmann::json.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
struct caster_declarer<
|
||||||
|
T,
|
||||||
|
typename std::enable_if<is_integral<T>::value>::type
|
||||||
|
>
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
ValueCaster::declare<T, bool>();
|
||||||
|
bit_integer_declarer<T>::declare();
|
||||||
|
ValueCaster::declare<T, int8_t>();
|
||||||
|
ValueCaster::declare<T, int16_t>();
|
||||||
|
ValueCaster::declare<T, bi<24>>();
|
||||||
|
ValueCaster::declare<T, int32_t>();
|
||||||
|
ValueCaster::declare<T, int64_t>();
|
||||||
|
ValueCaster::declare<T, uint8_t>();
|
||||||
|
ValueCaster::declare<T, uint16_t>();
|
||||||
|
ValueCaster::declare<T, bui<24>>();
|
||||||
|
ValueCaster::declare<T, uint32_t>();
|
||||||
|
ValueCaster::declare<T, uint64_t>();
|
||||||
|
ValueCaster::declare<T, float>();
|
||||||
|
ValueCaster::declare<T, double>();
|
||||||
|
ValueCaster::declare<T, std::string>();
|
||||||
|
ValueCaster::declare<T, nlohmann::json>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* caster_declarer specialization for all floating point types.
|
||||||
|
* Floating point integers can cast to all integer types, as well as
|
||||||
|
* std::string and nlohmann::json.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
struct caster_declarer<
|
||||||
|
T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type
|
||||||
|
>
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
ValueCaster::declare<T, bool>();
|
||||||
|
bit_integer_declarer<T, 7>::declare();
|
||||||
|
ValueCaster::declare<T, int8_t>();
|
||||||
|
ValueCaster::declare<T, int16_t>();
|
||||||
|
ValueCaster::declare<T, bi<24>>();
|
||||||
|
ValueCaster::declare<T, int32_t>();
|
||||||
|
ValueCaster::declare<T, int64_t>();
|
||||||
|
ValueCaster::declare<T, uint8_t>();
|
||||||
|
ValueCaster::declare<T, uint16_t>();
|
||||||
|
ValueCaster::declare<T, bui<24>>();
|
||||||
|
ValueCaster::declare<T, uint32_t>();
|
||||||
|
ValueCaster::declare<T, uint64_t>();
|
||||||
|
ValueCaster::declare<T, float>();
|
||||||
|
ValueCaster::declare<T, double>();
|
||||||
|
ValueCaster::declare<T, std::string>();
|
||||||
|
ValueCaster::declare<T, nlohmann::json>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* caster_declarer specialization for enum types.
|
||||||
|
* Enums can be cast to any integer type, as well as std::string,
|
||||||
|
* and nlohmann::json.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
struct caster_declarer<
|
||||||
|
T,
|
||||||
|
typename std::enable_if<std::is_enum<T>::value>::type
|
||||||
|
>
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
ValueCaster::declare<T, bool>();
|
||||||
|
bit_integer_declarer<T, 7>::declare();
|
||||||
|
ValueCaster::declare<T, int8_t>();
|
||||||
|
ValueCaster::declare<T, int16_t>();
|
||||||
|
ValueCaster::declare<T, bi<24>>();
|
||||||
|
ValueCaster::declare<T, int32_t>();
|
||||||
|
ValueCaster::declare<T, int64_t>();
|
||||||
|
ValueCaster::declare<T, uint8_t>();
|
||||||
|
ValueCaster::declare<T, uint16_t>();
|
||||||
|
ValueCaster::declare<T, bui<24>>();
|
||||||
|
ValueCaster::declare<T, uint32_t>();
|
||||||
|
ValueCaster::declare<T, uint64_t>();
|
||||||
|
ValueCaster::declare<T, std::string>();
|
||||||
|
ValueCaster::declare<T, nlohmann::json>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* caster_declarer specialization for string.
|
||||||
|
* Strings can be cast to UTF-16 strings, and json objects.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct caster_declarer<std::string>
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
// TODO: Casting string to u16string
|
||||||
|
ValueCaster::declare<std::string, nlohmann::json>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* caster_declarer specialization for UTF-16 strings.
|
||||||
|
* UTF-16 strings can be cast to strings, and json objects.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct caster_declarer<std::u16string>
|
||||||
|
{
|
||||||
|
static void declare()
|
||||||
|
{
|
||||||
|
// TODO: Casting u16string to string
|
||||||
|
ValueCaster::declare<std::u16string, nlohmann::json>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,12 @@ namespace pclass
|
||||||
return ValueT(prop.m_value);
|
return ValueT(prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const StaticProperty<ValueT> &prop)
|
||||||
|
{
|
||||||
|
// Return a reference to the property's value
|
||||||
|
return Value::make_reference<ValueT>(prop.m_value);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -80,6 +86,8 @@ namespace pclass
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using nonpointer_type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
static ValueT construct(const Type &type)
|
static ValueT construct(const Type &type)
|
||||||
{
|
{
|
||||||
// The default value of pointers is null
|
// The default value of pointers is null
|
||||||
|
@ -93,6 +101,11 @@ namespace pclass
|
||||||
return prop.m_value;
|
return prop.m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const StaticProperty<ValueT> &prop)
|
||||||
|
{
|
||||||
|
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -140,6 +153,8 @@ namespace pclass
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using nonpointer_type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
static ValueT construct(const Type &type)
|
static ValueT construct(const Type &type)
|
||||||
{
|
{
|
||||||
// The default value of pointers is null
|
// The default value of pointers is null
|
||||||
|
@ -153,6 +168,11 @@ namespace pclass
|
||||||
return prop.m_value;
|
return prop.m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const StaticProperty<ValueT> &prop)
|
||||||
|
{
|
||||||
|
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does derive from PropertyClass, and we have a pointer to an instance
|
// ValueT does derive from PropertyClass, and we have a pointer to an instance
|
||||||
|
@ -216,6 +236,11 @@ namespace pclass
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const StaticProperty<ValueT> &prop)
|
||||||
|
{
|
||||||
|
return Value::make_reference<ValueT>(prop.m_value);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does derive from PropertyClass, and we have an instance of ValueT,
|
// ValueT does derive from PropertyClass, and we have an instance of ValueT,
|
||||||
|
@ -313,6 +338,11 @@ namespace pclass
|
||||||
return value_object_helper<ValueT>::copy(prop);
|
return value_object_helper<ValueT>::copy(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const StaticProperty<ValueT> &prop)
|
||||||
|
{
|
||||||
|
return value_object_helper<ValueT>::get_value(prop);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
return value_object_helper<ValueT>::get_object(prop);
|
return value_object_helper<ValueT>::get_object(prop);
|
||||||
|
@ -381,7 +411,7 @@ namespace pclass
|
||||||
|
|
||||||
Value get_value() const override
|
Value get_value() const override
|
||||||
{
|
{
|
||||||
return Value::make_reference(m_value);
|
return value_helper<ValueT>::get_value(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PropertyClass *get_object() const override
|
const PropertyClass *get_object() const override
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "ki/pclass/types/PrimitiveType.h"
|
#include "ki/pclass/types/PrimitiveType.h"
|
||||||
#include "ki/pclass/types/ClassType.h"
|
#include "ki/pclass/types/ClassType.h"
|
||||||
#include "ki/pclass/types/EnumType.h"
|
#include "ki/pclass/types/EnumType.h"
|
||||||
|
#include "ki/pclass/Casters.h"
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -30,6 +31,7 @@ namespace pclass
|
||||||
template <typename ValueT>
|
template <typename ValueT>
|
||||||
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
||||||
{
|
{
|
||||||
|
detail::caster_declarer<ValueT>::declare();
|
||||||
auto *type = new PrimitiveType<ValueT>(name, *this);
|
auto *type = new PrimitiveType<ValueT>(name, *this);
|
||||||
define_type(std::unique_ptr<Type>(
|
define_type(std::unique_ptr<Type>(
|
||||||
dynamic_cast<Type *>(type)
|
dynamic_cast<Type *>(type)
|
||||||
|
@ -50,9 +52,12 @@ namespace pclass
|
||||||
return define_class<ClassT>(name, &base_class);
|
return define_class<ClassT>(name, &base_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnumType &define_enum(const std::string &name);
|
||||||
|
|
||||||
template <typename EnumT>
|
template <typename EnumT>
|
||||||
CppEnumType<EnumT> &define_enum(const std::string &name)
|
CppEnumType<EnumT> &define_enum(const std::string &name)
|
||||||
{
|
{
|
||||||
|
detail::caster_declarer<EnumT>::declare();
|
||||||
auto *type = new CppEnumType<EnumT>(name, *this);
|
auto *type = new CppEnumType<EnumT>(name, *this);
|
||||||
define_type(std::unique_ptr<Type>(
|
define_type(std::unique_ptr<Type>(
|
||||||
dynamic_cast<Type *>(type)
|
dynamic_cast<Type *>(type)
|
||||||
|
@ -83,6 +88,8 @@ namespace pclass
|
||||||
ClassType<ClassT> &define_class(
|
ClassType<ClassT> &define_class(
|
||||||
const std::string &name, const Type *base_class)
|
const std::string &name, const Type *base_class)
|
||||||
{
|
{
|
||||||
|
detail::caster_declarer<ClassT>::declare();
|
||||||
|
|
||||||
// If the caller does not specify a base class, automatically make
|
// If the caller does not specify a base class, automatically make
|
||||||
// ki::pclass::PropertyClass the base class (if it has been defined)
|
// ki::pclass::PropertyClass the base class (if it has been defined)
|
||||||
if (base_class == nullptr && has_type("class PropertyClass"))
|
if (base_class == nullptr && has_type("class PropertyClass"))
|
||||||
|
|
|
@ -15,7 +15,10 @@ namespace pclass
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename SrcT, typename DestT>
|
template <
|
||||||
|
typename SrcT, typename DestT,
|
||||||
|
typename SrcEnable = void, typename DestEnable = void
|
||||||
|
>
|
||||||
struct value_caster;
|
struct value_caster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +163,7 @@ namespace pclass
|
||||||
* A static lookup used to find appropriate casters at runtime.
|
* A static lookup used to find appropriate casters at runtime.
|
||||||
* Contains SrcT -> Caster elements.
|
* Contains SrcT -> Caster elements.
|
||||||
*/
|
*/
|
||||||
static std::unordered_map<std::size_t, ValueCaster *> s_caster_lookup;
|
static std::unordered_map<std::size_t, ValueCaster *> *s_caster_lookup;
|
||||||
|
|
||||||
const std::type_info *m_src_type;
|
const std::type_info *m_src_type;
|
||||||
std::unordered_map<std::size_t, detail::value_caster_base *> m_casts;
|
std::unordered_map<std::size_t, detail::value_caster_base *> m_casts;
|
||||||
|
@ -175,11 +178,14 @@ namespace pclass
|
||||||
template <typename SrcT>
|
template <typename SrcT>
|
||||||
static ValueCaster &get()
|
static ValueCaster &get()
|
||||||
{
|
{
|
||||||
|
if (!s_caster_lookup)
|
||||||
|
s_caster_lookup = new std::unordered_map<std::size_t, ValueCaster *>();
|
||||||
|
|
||||||
const auto &src_type = typeid(SrcT);
|
const auto &src_type = typeid(SrcT);
|
||||||
const auto src_type_hash = src_type.hash_code();
|
const auto src_type_hash = src_type.hash_code();
|
||||||
if (s_caster_lookup.find(src_type_hash) == s_caster_lookup.end())
|
if (s_caster_lookup->find(src_type_hash) == s_caster_lookup->end())
|
||||||
s_caster_lookup[src_type_hash] = new ValueCaster(src_type);
|
(*s_caster_lookup)[src_type_hash] = new ValueCaster(src_type);
|
||||||
return *s_caster_lookup[src_type_hash];
|
return *s_caster_lookup->at(src_type_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SrcT, typename DestT>
|
template <typename SrcT, typename DestT>
|
||||||
|
@ -388,7 +394,10 @@ namespace pclass
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
*/
|
*/
|
||||||
template <typename SrcT, typename DestT>
|
template <
|
||||||
|
typename SrcT, typename DestT,
|
||||||
|
typename SrcEnable, typename DestEnable
|
||||||
|
>
|
||||||
struct value_caster : value_caster_impl<SrcT, DestT>
|
struct value_caster : value_caster_impl<SrcT, DestT>
|
||||||
{
|
{
|
||||||
Value cast(const Value &value) const override
|
Value cast(const Value &value) const override
|
||||||
|
|
|
@ -34,6 +34,14 @@ namespace pclass
|
||||||
return ValueT(prop.at(index));
|
return ValueT(prop.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= prop.size())
|
||||||
|
throw runtime_error("Index out of bounds.");
|
||||||
|
return Value::make_reference(prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -82,6 +90,14 @@ namespace pclass
|
||||||
return prop.at(index);
|
return prop.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= prop.size())
|
||||||
|
throw runtime_error("Index out of bounds.");
|
||||||
|
return Value::make_reference(*prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -126,6 +142,14 @@ namespace pclass
|
||||||
return prop.at(index);
|
return prop.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= prop.size())
|
||||||
|
throw runtime_error("Index out of bounds.");
|
||||||
|
return Value::make_reference(*prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
|
@ -185,6 +209,14 @@ namespace pclass
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= prop.size())
|
||||||
|
throw runtime_error("Index out of bounds.");
|
||||||
|
return Value::make_reference(prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
|
@ -300,6 +332,12 @@ namespace pclass
|
||||||
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value get_value(const VectorProperty<ValueT> &prop,
|
||||||
|
const int index)
|
||||||
|
{
|
||||||
|
return vector_value_object_helper<ValueT>::get_value(prop, index);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop,
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
std::unique_ptr<PropertyClass> &object, const int index)
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +402,7 @@ namespace pclass
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= this->size())
|
if (index < 0 || index >= this->size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
return Value::make_reference(this->at(index));
|
return vector_value_helper<ValueT>::get_value(*this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PropertyClass *get_object(const int index) const override
|
const PropertyClass *get_object(const int index) const override
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
|
@ -7,6 +8,9 @@ namespace pclass
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* primitive_type_helper specialization for string types.
|
||||||
|
*/
|
||||||
template <
|
template <
|
||||||
typename _Elem,
|
typename _Elem,
|
||||||
typename _Traits,
|
typename _Traits,
|
||||||
|
|
|
@ -13,8 +13,8 @@ namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
{
|
{
|
||||||
template <int N>
|
template <int N = 7>
|
||||||
void define_bit_integer_primitive(pclass::TypeSystem &type_system)
|
void define_bit_integer_primitive(TypeSystem &type_system)
|
||||||
{
|
{
|
||||||
define_bit_integer_primitive<N - 1>(type_system);
|
define_bit_integer_primitive<N - 1>(type_system);
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ namespace pclass
|
||||||
type_system.define_primitive<bui<N>>(oss.str());
|
type_system.define_primitive<bui<N>>(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialization for define_bit_integer_primitive.
|
||||||
|
* Stop decrementing N when it reaches 0.
|
||||||
|
*/
|
||||||
template <>
|
template <>
|
||||||
void define_bit_integer_primitive<0>(TypeSystem &type_system) {}
|
void define_bit_integer_primitive<0>(TypeSystem &type_system) {}
|
||||||
|
|
||||||
|
@ -58,7 +62,7 @@ namespace pclass
|
||||||
define_primitive<uint64_t>("gid");
|
define_primitive<uint64_t>("gid");
|
||||||
|
|
||||||
// Define bit-integer types
|
// Define bit-integer types
|
||||||
define_bit_integer_primitive<7>(*this);
|
define_bit_integer_primitive(*this);
|
||||||
define_primitive<bi<24>>("s24");
|
define_primitive<bi<24>>("s24");
|
||||||
define_primitive<bui<24>>("u24");
|
define_primitive<bui<24>>("u24");
|
||||||
|
|
||||||
|
@ -118,6 +122,15 @@ namespace pclass
|
||||||
return *it->second;
|
return *it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnumType &TypeSystem::define_enum(const std::string& name)
|
||||||
|
{
|
||||||
|
auto *type = new EnumType(name, *this);
|
||||||
|
define_type(std::unique_ptr<Type>(
|
||||||
|
dynamic_cast<Type *>(type)
|
||||||
|
));
|
||||||
|
return *type;
|
||||||
|
}
|
||||||
|
|
||||||
void TypeSystem::define_type(std::unique_ptr<Type> type)
|
void TypeSystem::define_type(std::unique_ptr<Type> type)
|
||||||
{
|
{
|
||||||
// Does a type with this name already exist?
|
// Does a type with this name already exist?
|
||||||
|
|
|
@ -4,6 +4,9 @@ namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
{
|
{
|
||||||
|
// Initialize the static lookup map
|
||||||
|
std::unordered_map<std::size_t, ValueCaster *> *ValueCaster::s_caster_lookup = nullptr;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
Value value_caster_base::cast(const Value &v) const
|
Value value_caster_base::cast(const Value &v) const
|
||||||
|
@ -109,8 +112,5 @@ namespace pclass
|
||||||
m_deallocator.deallocate(m_value_ptr);
|
m_deallocator.deallocate(m_value_ptr);
|
||||||
m_value_ptr = nullptr;
|
m_value_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the static lookup map
|
|
||||||
std::unordered_map<std::size_t, ValueCaster *> ValueCaster::s_caster_lookup = {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue