mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-24 05:18:36 +00:00
Promotes explicit specialisations to namespace scope.
This commit is contained in:
+14
-14
@@ -71,8 +71,8 @@ class Enum {
|
||||
result.emplace_back(std::string(start, size_t(d_ptr - start)));
|
||||
}
|
||||
|
||||
members_by_type_.emplace(std::make_pair(&typeid(Type), result));
|
||||
names_by_type_.emplace(std::make_pair(&typeid(Type), std::string(name)));
|
||||
members_by_type_.emplace(std::make_pair(std::type_index(typeid(Type)), result));
|
||||
names_by_type_.emplace(std::make_pair(std::type_index(typeid(Type)), std::string(name)));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -85,8 +85,8 @@ class Enum {
|
||||
/*!
|
||||
@returns the declared name of the enum with type_info @c type if it has been registered; the empty string otherwise.
|
||||
*/
|
||||
static const std::string &name(const std::type_info &type) {
|
||||
const auto entry = names_by_type_.find(&type);
|
||||
static const std::string &name(std::type_index type) {
|
||||
const auto entry = names_by_type_.find(type);
|
||||
if(entry == names_by_type_.end()) return empty_string_;
|
||||
return entry->second;
|
||||
}
|
||||
@@ -101,8 +101,8 @@ class Enum {
|
||||
/*!
|
||||
@returns the number of members of the enum with type_info @c type if it has been registered; @c std::string::npos otherwise.
|
||||
*/
|
||||
static size_t size(const std::type_info &type) {
|
||||
const auto entry = members_by_type_.find(&type);
|
||||
static size_t size(std::type_index type) {
|
||||
const auto entry = members_by_type_.find(type);
|
||||
if(entry == members_by_type_.end()) return std::string::npos;
|
||||
return entry->second.size();
|
||||
}
|
||||
@@ -117,8 +117,8 @@ class Enum {
|
||||
/*!
|
||||
@returns A @c std::string name for the enum value @c e from the enum with type_info @c type.
|
||||
*/
|
||||
static const std::string &to_string(const std::type_info &type, size_t e) {
|
||||
const auto entry = members_by_type_.find(&type);
|
||||
static const std::string &to_string(std::type_index type, size_t e) {
|
||||
const auto entry = members_by_type_.find(type);
|
||||
if(entry == members_by_type_.end()) return empty_string_;
|
||||
return entry->second[e];
|
||||
}
|
||||
@@ -126,8 +126,8 @@ class Enum {
|
||||
/*!
|
||||
@returns a vector naming the members of the enum with type_info @c type if it has been registered; an empty vector otherwise.
|
||||
*/
|
||||
static const std::vector<std::string> &all_values(const std::type_info &type) {
|
||||
const auto entry = members_by_type_.find(&type);
|
||||
static const std::vector<std::string> &all_values(std::type_index type) {
|
||||
const auto entry = members_by_type_.find(type);
|
||||
if(entry == members_by_type_.end()) return empty_vector_;
|
||||
return entry->second;
|
||||
}
|
||||
@@ -151,8 +151,8 @@ class Enum {
|
||||
@returns A value for the name @c str in the enum with type_info @c type , or @c std::string::npos if
|
||||
the name is not found.
|
||||
*/
|
||||
static size_t from_string(const std::type_info &type, const std::string &str) {
|
||||
const auto entry = members_by_type_.find(&type);
|
||||
static size_t from_string(std::type_index type, const std::string &str) {
|
||||
const auto entry = members_by_type_.find(type);
|
||||
if(entry == members_by_type_.end()) return std::string::npos;
|
||||
const auto iterator = std::find(entry->second.begin(), entry->second.end(), str);
|
||||
if(iterator == entry->second.end()) return std::string::npos;
|
||||
@@ -160,8 +160,8 @@ class Enum {
|
||||
}
|
||||
|
||||
private:
|
||||
static inline std::unordered_map<const std::type_info *, std::vector<std::string>> members_by_type_;
|
||||
static inline std::unordered_map<const std::type_info *, std::string> names_by_type_;
|
||||
static inline std::unordered_map<std::type_index, std::vector<std::string>> members_by_type_;
|
||||
static inline std::unordered_map<std::type_index, std::string> names_by_type_;
|
||||
static inline const std::string empty_string_;
|
||||
static inline const std::vector<std::string> empty_vector_;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Struct.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 13/03/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Struct.h"
|
||||
|
||||
template <> bool Reflection::set(Struct &target, const std::string &name, int value) {
|
||||
const auto target_type = target.type_of(name);
|
||||
if(!target_type) return false;
|
||||
|
||||
// No need to convert an int or a registered enum.
|
||||
if(*target_type == typeid(int) || !Reflection::Enum::name(*target_type).empty()) {
|
||||
target.set(name, &value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Promote to an int64_t.
|
||||
if(*target_type == typeid(int64_t)) {
|
||||
const auto int64 = int64_t(value);
|
||||
target.set(name, &int64);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <> bool Reflection::set(Struct &target, const std::string &name, const std::string &value) {
|
||||
const auto target_type = target.type_of(name);
|
||||
if(!target_type) return false;
|
||||
|
||||
if(Reflection::Enum::name(*target_type).empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto enum_value = Reflection::Enum::from_string(*target_type, value);
|
||||
if(enum_value == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int int_value = int(enum_value);
|
||||
target.set(name, &int_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <> bool Reflection::set(Struct &target, const std::string &name, const char *value) {
|
||||
const std::string string(value);
|
||||
return set<const std::string &>(target, name, string);
|
||||
}
|
||||
+28
-70
@@ -24,77 +24,35 @@ namespace Reflection {
|
||||
struct Struct {
|
||||
virtual std::vector<std::string> all_keys() = 0;
|
||||
virtual const std::type_info *type_of(const std::string &name) = 0;
|
||||
virtual void set_raw(const std::string &name, const void *value) = 0;
|
||||
virtual const void *get_raw(const std::string &name) = 0;
|
||||
virtual void set(const std::string &name, const void *value) = 0;
|
||||
virtual const void *get(const std::string &name) = 0;
|
||||
virtual ~Struct() {}
|
||||
|
||||
/*!
|
||||
Attempts to set the property @c name to @c value ; will perform limited type conversions.
|
||||
|
||||
@returns @c true if t
|
||||
*/
|
||||
template <typename Type> bool set(const std::string &name, Type value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Setting an int:
|
||||
|
||||
* to an int copies the int;
|
||||
* to an int64_t promotes the int; and
|
||||
* to a registered enum, copies the int.
|
||||
*/
|
||||
template <> bool set(const std::string &name, int value) {
|
||||
const auto target_type = type_of(name);
|
||||
if(!target_type) return false;
|
||||
|
||||
// No need to convert an int or a registered enum.
|
||||
if(*target_type == typeid(int) || !Reflection::Enum::name(*target_type).empty()) {
|
||||
set_raw(name, &value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Promote to an int64_t.
|
||||
if(*target_type == typeid(int64_t)) {
|
||||
const auto int64 = int64_t(value);
|
||||
set_raw(name, &int64);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Setting a string:
|
||||
|
||||
* to an enum, if the string names a member of the enum, sets the value.
|
||||
*/
|
||||
template <> bool set(const std::string &name, const std::string &value) {
|
||||
const auto target_type = type_of(name);
|
||||
if(!target_type) return false;
|
||||
|
||||
if(Reflection::Enum::name(*target_type).empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto enum_value = Reflection::Enum::from_string(*target_type, value);
|
||||
if(enum_value == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int int_value = int(enum_value);
|
||||
set_raw(name, &int_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <> bool set(const std::string &name, const char *value) {
|
||||
const std::string string(value);
|
||||
return set<const std::string &>(name, string);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
Attempts to set the property @c name to @c value ; will perform limited type conversions.
|
||||
|
||||
@returns @c true if t
|
||||
*/
|
||||
template <typename Type> bool set(Struct &target, const std::string &name, Type value);
|
||||
|
||||
/*!
|
||||
Setting an int:
|
||||
|
||||
* to an int copies the int;
|
||||
* to an int64_t promotes the int; and
|
||||
* to a registered enum, copies the int.
|
||||
*/
|
||||
template <> bool set(Struct &target, const std::string &name, int value);
|
||||
|
||||
/*!
|
||||
Setting a string:
|
||||
|
||||
* to an enum, if the string names a member of the enum, sets the value.
|
||||
*/
|
||||
template <> bool set(Struct &target, const std::string &name, const std::string &value);
|
||||
template <> bool set(Struct &target, const std::string &name, const char *value);
|
||||
|
||||
struct Serialisable {
|
||||
/// Serialises this object, appending it to @c target.
|
||||
virtual void serialise(std::vector<uint8_t> &target) = 0;
|
||||
@@ -109,7 +67,7 @@ template <typename Owner> class StructImpl: public Struct {
|
||||
@returns the value of type @c Type that is loaded from the offset registered for the field @c name.
|
||||
It is the caller's responsibility to provide an appropriate type of data.
|
||||
*/
|
||||
const void *get_raw(const std::string &name) final {
|
||||
const void *get(const std::string &name) final {
|
||||
const auto iterator = contents_.find(name);
|
||||
if(iterator == contents_.end()) return nullptr;
|
||||
return reinterpret_cast<uint8_t *>(this) + iterator->second.offset;
|
||||
@@ -120,7 +78,7 @@ template <typename Owner> class StructImpl: public Struct {
|
||||
|
||||
It is the caller's responsibility to provide an appropriate type of data.
|
||||
*/
|
||||
void set_raw(const std::string &name, const void *value) final {
|
||||
void set(const std::string &name, const void *value) final {
|
||||
const auto iterator = contents_.find(name);
|
||||
if(iterator == contents_.end()) return;
|
||||
memcpy(reinterpret_cast<uint8_t *>(this) + iterator->second.offset, value, iterator->second.size);
|
||||
|
||||
Reference in New Issue
Block a user