diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index ee4db8516..377c50181 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -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 = ""; }; 4B4518A71F76004200926311 /* TapeParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TapeParser.hpp; path = Parsers/TapeParser.hpp; sourceTree = ""; }; 4B4518A81F76022000926311 /* DiskImageImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskImageImplementation.hpp; sourceTree = ""; }; + 4B47F6C4241C87A100ED06F7 /* Struct.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Struct.cpp; sourceTree = ""; }; 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 = ""; }; 4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AY38910.hpp; path = AY38910/AY38910.hpp; sourceTree = ""; }; @@ -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 */, diff --git a/OSBindings/SDL/SConstruct b/OSBindings/SDL/SConstruct index 93d84ede7..3889c723d 100644 --- a/OSBindings/SDL/SConstruct +++ b/OSBindings/SDL/SConstruct @@ -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') diff --git a/Reflection/Enum.h b/Reflection/Enum.h index 85e38b7c9..f91106c81 100644 --- a/Reflection/Enum.h +++ b/Reflection/Enum.h @@ -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 &all_values(const std::type_info &type) { - const auto entry = members_by_type_.find(&type); + static const std::vector &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> members_by_type_; - static inline std::unordered_map names_by_type_; + static inline std::unordered_map> members_by_type_; + static inline std::unordered_map names_by_type_; static inline const std::string empty_string_; static inline const std::vector empty_vector_; }; diff --git a/Reflection/Struct.cpp b/Reflection/Struct.cpp new file mode 100644 index 000000000..fbf92ab09 --- /dev/null +++ b/Reflection/Struct.cpp @@ -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(target, name, string); +} diff --git a/Reflection/Struct.h b/Reflection/Struct.h index 058de8b13..3ceae6155 100644 --- a/Reflection/Struct.h +++ b/Reflection/Struct.h @@ -24,77 +24,35 @@ namespace Reflection { struct Struct { virtual std::vector 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 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(name, string); - } - }; +/*! + Attempts to set the property @c name to @c value ; will perform limited type conversions. + + @returns @c true if t +*/ +template 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 &target) = 0; @@ -109,7 +67,7 @@ template 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(this) + iterator->second.offset; @@ -120,7 +78,7 @@ template 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(this) + iterator->second.offset, value, iterator->second.size);