1
0
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:
Thomas Harte 2020-03-13 23:38:29 -04:00
parent 1a2872c815
commit cab4bead72
5 changed files with 103 additions and 84 deletions

View File

@ -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 */,

View File

@ -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')

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
Reflection/Struct.cpp Normal file
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);
}

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);