1
0
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:
Thomas Harte
2020-03-13 23:38:29 -04:00
parent 1a2872c815
commit cab4bead72
5 changed files with 103 additions and 84 deletions
+14 -14
View File
@@ -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_;
};
+53
View File
@@ -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
View File
@@ -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);