mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Promotes explicit specialisations to namespace scope.
This commit is contained in:
parent
1a2872c815
commit
cab4bead72
@ -198,6 +198,8 @@
|
||||
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518951F75FD1B00926311 /* HFE.cpp */; };
|
||||
4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518971F75FD1B00926311 /* OricMFMDSK.cpp */; };
|
||||
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4518991F75FD1B00926311 /* SSD.cpp */; };
|
||||
4B47F6C5241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; };
|
||||
4B47F6C6241C87A100ED06F7 /* Struct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B47F6C4241C87A100ED06F7 /* Struct.cpp */; };
|
||||
4B49F0A923346F7A0045E6A6 /* MacintoshOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B49F0A723346F7A0045E6A6 /* MacintoshOptions.xib */; };
|
||||
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; };
|
||||
4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; };
|
||||
@ -1095,6 +1097,7 @@
|
||||
4B45189A1F75FD1B00926311 /* SSD.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SSD.hpp; sourceTree = "<group>"; };
|
||||
4B4518A71F76004200926311 /* TapeParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TapeParser.hpp; path = Parsers/TapeParser.hpp; sourceTree = "<group>"; };
|
||||
4B4518A81F76022000926311 /* DiskImageImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskImageImplementation.hpp; sourceTree = "<group>"; };
|
||||
4B47F6C4241C87A100ED06F7 /* Struct.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Struct.cpp; sourceTree = "<group>"; };
|
||||
4B49F0A823346F7A0045E6A6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MacintoshOptions.xib"; sourceTree = SOURCE_ROOT; };
|
||||
4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AY38910.cpp; path = AY38910/AY38910.cpp; sourceTree = "<group>"; };
|
||||
4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AY38910.hpp; path = AY38910/AY38910.hpp; sourceTree = "<group>"; };
|
||||
@ -2201,6 +2204,7 @@
|
||||
children = (
|
||||
4B3AF7D02413470E00873C0B /* Enum.h */,
|
||||
4B3AF7D12413472200873C0B /* Struct.h */,
|
||||
4B47F6C4241C87A100ED06F7 /* Struct.cpp */,
|
||||
);
|
||||
name = Reflection;
|
||||
path = ../../Reflection;
|
||||
@ -4421,6 +4425,7 @@
|
||||
4B0ACC3323775819008902D0 /* Atari2600.cpp in Sources */,
|
||||
4BD424E02193B5340097291A /* TextureTarget.cpp in Sources */,
|
||||
4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */,
|
||||
4B47F6C6241C87A100ED06F7 /* Struct.cpp in Sources */,
|
||||
4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */,
|
||||
4B894527201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4BB244D622AABAF600BE20E5 /* z8530.cpp in Sources */,
|
||||
@ -4580,6 +4585,7 @@
|
||||
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */,
|
||||
4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */,
|
||||
4B7F1897215486A200388727 /* StaticAnalyser.cpp in Sources */,
|
||||
4B47F6C5241C87A100ED06F7 /* Struct.cpp in Sources */,
|
||||
4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */,
|
||||
4B5FADBA1DE3151600AEC565 /* FileHolder.cpp in Sources */,
|
||||
4B643F3A1D77AD1900D431D6 /* CSStaticAnalyser.mm in Sources */,
|
||||
|
@ -85,6 +85,8 @@ SOURCES += glob.glob('../../Processors/6502/Implementation/*.cpp')
|
||||
SOURCES += glob.glob('../../Processors/68000/Implementation/*.cpp')
|
||||
SOURCES += glob.glob('../../Processors/Z80/Implementation/*.cpp')
|
||||
|
||||
SOURCES += glob.glob('../../Reflection/*.cpp')
|
||||
|
||||
SOURCES += glob.glob('../../SignalProcessing/*.cpp')
|
||||
|
||||
SOURCES += glob.glob('../../Storage/*.cpp')
|
||||
|
@ -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
Reflection/Struct.cpp
Normal file
53
Reflection/Struct.cpp
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user