From d33ec72fa251bbc7f1cc24074c31067b3c54d3bb Mon Sep 17 00:00:00 2001 From: Timothy Prepscius Date: Wed, 25 Feb 2026 12:41:23 -0500 Subject: [PATCH] flatten 20260225 --- .gitignore | 4 + Core_Variant.xcodeproj/project.pbxproj | 650 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/Core_Variant_Tests.xcscheme | 93 +++ Makefile | 2 + Makefile.def | 6 + Makefile.project | 18 + tests/Makefile | 1 + tests/Makefile.project | 31 + tests/main.cpp | 20 + tjp/core/variant/ConcreteVariant+IO.h | 24 + tjp/core/variant/ConcreteVariant.h | 13 + tjp/core/variant/ConcreteVariant.hpp | 84 +++ tjp/core/variant/Notes.txt | 21 + tjp/core/variant/VType+Functional.hpp | 115 ++++ tjp/core/variant/VType+IO.cpp | 13 + tjp/core/variant/VType+IO.h | 18 + tjp/core/variant/VType.cpp | 10 + tjp/core/variant/VType.h | 48 ++ tjp/core/variant/VType.hpp | 47 ++ tjp/core/variant/VType.inl | 39 ++ tjp/core/variant/VType_of.hpp | 102 +++ tjp/core/variant/VVector.h | 22 + tjp/core/variant/Variant+Dispatch.h | 28 + tjp/core/variant/Variant+Dispatch.inl | 99 +++ .../variant/Variant+Functional+Generate.hpp | 27 + tjp/core/variant/Variant+Functional.cpp | 25 + tjp/core/variant/Variant+Functional.hpp | 605 ++++++++++++++++ tjp/core/variant/Variant+IO.hpp | 137 ++++ .../Variant+VariantFunctionalUsingMap.hpp | 77 +++ ...ariantFunctionalUsingMapAndVectorCache.hpp | 122 ++++ ...ntFunctionalUsingSingleFunctionsObject.hpp | 39 ++ ...ionalUsingSingleFunctionsObjectPointer.hpp | 67 ++ tjp/core/variant/Variant.h | 23 + tjp/core/variant/Variant.hpp | 12 + tjp/core/variant/VariantIO.h | 13 + tjp/core/variant/VariantIO.hpp | 41 ++ tjp/core/variant/VariantSerialization+IO.hpp | 24 + tjp/core/variant/VariantSerialization.h | 14 + tjp/core/variant/VariantSerialization.hpp | 36 + tjp/core/variant/_tests/VType_of.cpp | 132 ++++ tjp/core/variant/_tests/Variant.cpp | 379 ++++++++++ 43 files changed, 3296 insertions(+) create mode 100644 .gitignore create mode 100644 Core_Variant.xcodeproj/project.pbxproj create mode 100644 Core_Variant.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Core_Variant.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Core_Variant.xcodeproj/xcshareddata/xcschemes/Core_Variant_Tests.xcscheme create mode 100644 Makefile create mode 100755 Makefile.def create mode 100755 Makefile.project create mode 120000 tests/Makefile create mode 100755 tests/Makefile.project create mode 100644 tests/main.cpp create mode 100644 tjp/core/variant/ConcreteVariant+IO.h create mode 100644 tjp/core/variant/ConcreteVariant.h create mode 100644 tjp/core/variant/ConcreteVariant.hpp create mode 100644 tjp/core/variant/Notes.txt create mode 100644 tjp/core/variant/VType+Functional.hpp create mode 100644 tjp/core/variant/VType+IO.cpp create mode 100644 tjp/core/variant/VType+IO.h create mode 100644 tjp/core/variant/VType.cpp create mode 100644 tjp/core/variant/VType.h create mode 100644 tjp/core/variant/VType.hpp create mode 100644 tjp/core/variant/VType.inl create mode 100644 tjp/core/variant/VType_of.hpp create mode 100644 tjp/core/variant/VVector.h create mode 100644 tjp/core/variant/Variant+Dispatch.h create mode 100644 tjp/core/variant/Variant+Dispatch.inl create mode 100644 tjp/core/variant/Variant+Functional+Generate.hpp create mode 100644 tjp/core/variant/Variant+Functional.cpp create mode 100644 tjp/core/variant/Variant+Functional.hpp create mode 100644 tjp/core/variant/Variant+IO.hpp create mode 100644 tjp/core/variant/Variant+VariantFunctionalUsingMap.hpp create mode 100644 tjp/core/variant/Variant+VariantFunctionalUsingMapAndVectorCache.hpp create mode 100644 tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObject.hpp create mode 100644 tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp create mode 100644 tjp/core/variant/Variant.h create mode 100644 tjp/core/variant/Variant.hpp create mode 100644 tjp/core/variant/VariantIO.h create mode 100644 tjp/core/variant/VariantIO.hpp create mode 100644 tjp/core/variant/VariantSerialization+IO.hpp create mode 100644 tjp/core/variant/VariantSerialization.h create mode 100644 tjp/core/variant/VariantSerialization.hpp create mode 100644 tjp/core/variant/_tests/VType_of.cpp create mode 100644 tjp/core/variant/_tests/Variant.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54958c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +*.pyc +xcuserdata +.bin diff --git a/Core_Variant.xcodeproj/project.pbxproj b/Core_Variant.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1e1d7e5 --- /dev/null +++ b/Core_Variant.xcodeproj/project.pbxproj @@ -0,0 +1,650 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + F608AAB128270AA8005C276B /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F608AAB028270AA8005C276B /* main.cpp */; }; + F608AAB528270AC8005C276B /* Variant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F608AA6C2826BCD8005C276B /* Variant.cpp */; }; + F608AAFC28271FF8005C276B /* VType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F608AA732826BCD8005C276B /* VType.cpp */; }; + F666630728679CB800239768 /* VType+IO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F666630628679CAE00239768 /* VType+IO.cpp */; }; + F666630828679CB900239768 /* VType+IO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F666630628679CAE00239768 /* VType+IO.cpp */; }; + F67119E02C8A63D300F72EE9 /* libCore_Variant.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F608A98C2826B791005C276B /* libCore_Variant.a */; }; + F67119E12C8A63D300F72EE9 /* libCore_Allocator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F61F9BEE2C6E4D7300F79137 /* libCore_Allocator.a */; }; + F67119E22C8A63D300F72EE9 /* libCore_Zero.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F608AAB928271CFE005C276B /* libCore_Zero.a */; }; + F69548BF28289357005D1B64 /* Variant+Functional.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69548BE2828930D005D1B64 /* Variant+Functional.cpp */; }; + F6971F54282B123D008FBD17 /* Variant+Functional.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69548BE2828930D005D1B64 /* Variant+Functional.cpp */; }; + F6971F55282B123D008FBD17 /* VType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F608AA732826BCD8005C276B /* VType.cpp */; }; + F69AB77F2B16D9DB000115BC /* VType_of.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69AB77E2B16D8CE000115BC /* VType_of.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + F62C2BE12A500925007B43A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F608A9842826B791005C276B /* Project object */; + proxyType = 1; + remoteGlobalIDString = F608A98B2826B791005C276B; + remoteInfo = Core_Variant; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + F608AAAC28270AA8005C276B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + F608A98C2826B791005C276B /* libCore_Variant.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCore_Variant.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F608AA6C2826BCD8005C276B /* Variant.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Variant.cpp; sourceTree = ""; }; + F608AA6D2826BCD8005C276B /* Variant+Dispatch.inl */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Variant+Dispatch.inl"; sourceTree = ""; }; + F608AA6E2826BCD8005C276B /* ConcreteVariant.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ConcreteVariant.hpp; sourceTree = ""; }; + F608AA702826BCD8005C276B /* VType.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VType.hpp; sourceTree = ""; }; + F608AA712826BCD8005C276B /* VType+IO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VType+IO.h"; sourceTree = ""; }; + F608AA722826BCD8005C276B /* ConcreteVariant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConcreteVariant.h; sourceTree = ""; }; + F608AA732826BCD8005C276B /* VType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VType.cpp; sourceTree = ""; }; + F608AA742826BCD8005C276B /* VariantIO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VariantIO.hpp; sourceTree = ""; }; + F608AA752826BCD8005C276B /* VariantIO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VariantIO.h; sourceTree = ""; }; + F608AA762826BCD8005C276B /* ConcreteVariant+IO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ConcreteVariant+IO.h"; sourceTree = ""; }; + F608AA772826BCD8005C276B /* VariantSerialization+IO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "VariantSerialization+IO.hpp"; sourceTree = ""; }; + F608AA782826BCD8005C276B /* Variant+Dispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Variant+Dispatch.h"; sourceTree = ""; }; + F608AA792826BCD8005C276B /* VType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VType.h; sourceTree = ""; }; + F608AA7A2826BCD8005C276B /* Variant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Variant.h; sourceTree = ""; }; + F608AAAE28270AA8005C276B /* Core_Variant_Tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Core_Variant_Tests; sourceTree = BUILT_PRODUCTS_DIR; }; + F608AAB028270AA8005C276B /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + F608AAB928271CFE005C276B /* libCore_Zero.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libCore_Zero.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F608AB6D2827F3CE005C276B /* Makefile.def */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.def; sourceTree = ""; }; + F608AB6E2827F3CE005C276B /* Makefile.project */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.project; sourceTree = ""; }; + F608AB9328282DF3005C276B /* Variant+VariantFunctionalUsingMap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingMap.hpp"; sourceTree = ""; }; + F608AB9428282E40005C276B /* Variant+VariantFunctionalUsingMapAndVectorCache.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingMapAndVectorCache.hpp"; sourceTree = ""; }; + F608AB9528282E8E005C276B /* Variant+VariantFunctionalUsingSingleFunctionsObject.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingSingleFunctionsObject.hpp"; sourceTree = ""; }; + F608AB9D28283866005C276B /* VariantSerialization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VariantSerialization.h; sourceTree = ""; }; + F608AB9E2828387E005C276B /* VariantSerialization.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VariantSerialization.hpp; sourceTree = ""; }; + F608ABA028283CC7005C276B /* Variant+IO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+IO.hpp"; sourceTree = ""; }; + F608ABA128284A65005C276B /* VType+Functional.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "VType+Functional.hpp"; sourceTree = ""; }; + F608ABA228284B6C005C276B /* Variant+Functional.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+Functional.hpp"; sourceTree = ""; }; + F608ABA328285011005C276B /* Variant.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Variant.hpp; sourceTree = ""; }; + F61F9BEC2C6E4CB400F79137 /* Makefile.project */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.project; sourceTree = ""; }; + F61F9BEE2C6E4D7300F79137 /* libCore_Allocator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libCore_Allocator.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F62C2BDE2A50043B007B43A3 /* Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp"; sourceTree = ""; }; + F62C2BDF2A5005A9007B43A3 /* Variant+Functional+Generate.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+Functional+Generate.hpp"; sourceTree = ""; }; + F666630628679CAE00239768 /* VType+IO.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "VType+IO.cpp"; sourceTree = ""; }; + F680BDB3285645BA00044A4F /* VType.inl */ = {isa = PBXFileReference; lastKnownFileType = text; path = VType.inl; sourceTree = ""; }; + F680BDB628567BCF00044A4F /* VVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VVector.h; sourceTree = ""; }; + F69548BE2828930D005D1B64 /* Variant+Functional.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "Variant+Functional.cpp"; sourceTree = ""; }; + F6971F5A282B123D008FBD17 /* libCore_Variant_iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCore_Variant_iOS.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F69AB77A2B16D210000115BC /* VType_of.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VType_of.hpp; sourceTree = ""; }; + F69AB77E2B16D8CE000115BC /* VType_of.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VType_of.cpp; sourceTree = ""; }; + F6BF9BE22E3901E3002E6AF0 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + F6FC229E284F73DA00A6381D /* Notes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Notes.txt; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + F608A98A2826B791005C276B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F608AAAB28270AA8005C276B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F67119E02C8A63D300F72EE9 /* libCore_Variant.a in Frameworks */, + F67119E12C8A63D300F72EE9 /* libCore_Allocator.a in Frameworks */, + F67119E22C8A63D300F72EE9 /* libCore_Zero.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F6971F56282B123D008FBD17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + F608A9832826B791005C276B = { + isa = PBXGroup; + children = ( + F608AAB828271CFE005C276B /* Frameworks */, + F6BF9BE22E3901E3002E6AF0 /* Makefile */, + F608AB6D2827F3CE005C276B /* Makefile.def */, + F608AB6E2827F3CE005C276B /* Makefile.project */, + F608A98D2826B791005C276B /* Products */, + F608AAAF28270AA8005C276B /* tests */, + F61D7C3F2E381655002A1AED /* tjp */, + ); + sourceTree = ""; + }; + F608A98D2826B791005C276B /* Products */ = { + isa = PBXGroup; + children = ( + F608A98C2826B791005C276B /* libCore_Variant.a */, + F608AAAE28270AA8005C276B /* Core_Variant_Tests */, + F6971F5A282B123D008FBD17 /* libCore_Variant_iOS.a */, + ); + name = Products; + sourceTree = ""; + }; + F608A9B52826BA8C005C276B /* core */ = { + isa = PBXGroup; + children = ( + F608AA6B2826BCD8005C276B /* variant */, + ); + path = core; + sourceTree = ""; + }; + F608AA6B2826BCD8005C276B /* variant */ = { + isa = PBXGroup; + children = ( + F61F9BED2C6E4CEC00F79137 /* _tests */, + F6FC229E284F73DA00A6381D /* Notes.txt */, + F608AA722826BCD8005C276B /* ConcreteVariant.h */, + F608AA6E2826BCD8005C276B /* ConcreteVariant.hpp */, + F608AA762826BCD8005C276B /* ConcreteVariant+IO.h */, + F608AA732826BCD8005C276B /* VType.cpp */, + F680BDB3285645BA00044A4F /* VType.inl */, + F608AA792826BCD8005C276B /* VType.h */, + F608AA702826BCD8005C276B /* VType.hpp */, + F69AB77A2B16D210000115BC /* VType_of.hpp */, + F608ABA128284A65005C276B /* VType+Functional.hpp */, + F608AA712826BCD8005C276B /* VType+IO.h */, + F666630628679CAE00239768 /* VType+IO.cpp */, + F680BDB628567BCF00044A4F /* VVector.h */, + F608AA7A2826BCD8005C276B /* Variant.h */, + F608ABA328285011005C276B /* Variant.hpp */, + F608AA782826BCD8005C276B /* Variant+Dispatch.h */, + F608AA6D2826BCD8005C276B /* Variant+Dispatch.inl */, + F608ABA228284B6C005C276B /* Variant+Functional.hpp */, + F62C2BDF2A5005A9007B43A3 /* Variant+Functional+Generate.hpp */, + F69548BE2828930D005D1B64 /* Variant+Functional.cpp */, + F608ABA028283CC7005C276B /* Variant+IO.hpp */, + F608AB9328282DF3005C276B /* Variant+VariantFunctionalUsingMap.hpp */, + F608AB9428282E40005C276B /* Variant+VariantFunctionalUsingMapAndVectorCache.hpp */, + F608AB9528282E8E005C276B /* Variant+VariantFunctionalUsingSingleFunctionsObject.hpp */, + F62C2BDE2A50043B007B43A3 /* Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp */, + F608AA752826BCD8005C276B /* VariantIO.h */, + F608AA742826BCD8005C276B /* VariantIO.hpp */, + F608AB9D28283866005C276B /* VariantSerialization.h */, + F608AB9E2828387E005C276B /* VariantSerialization.hpp */, + F608AA772826BCD8005C276B /* VariantSerialization+IO.hpp */, + ); + path = variant; + sourceTree = ""; + }; + F608AAAF28270AA8005C276B /* tests */ = { + isa = PBXGroup; + children = ( + F61F9BEC2C6E4CB400F79137 /* Makefile.project */, + F608AAB028270AA8005C276B /* main.cpp */, + ); + path = tests; + sourceTree = ""; + }; + F608AAB828271CFE005C276B /* Frameworks */ = { + isa = PBXGroup; + children = ( + F61F9BEE2C6E4D7300F79137 /* libCore_Allocator.a */, + F608AAB928271CFE005C276B /* libCore_Zero.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + F61D7C3F2E381655002A1AED /* tjp */ = { + isa = PBXGroup; + children = ( + F608A9B52826BA8C005C276B /* core */, + ); + path = tjp; + sourceTree = ""; + }; + F61F9BED2C6E4CEC00F79137 /* _tests */ = { + isa = PBXGroup; + children = ( + F608AA6C2826BCD8005C276B /* Variant.cpp */, + F69AB77E2B16D8CE000115BC /* VType_of.cpp */, + ); + path = _tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + F608A9882826B791005C276B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F6971F52282B123D008FBD17 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + F608A98B2826B791005C276B /* Core_Variant */ = { + isa = PBXNativeTarget; + buildConfigurationList = F608A9902826B791005C276B /* Build configuration list for PBXNativeTarget "Core_Variant" */; + buildPhases = ( + F608A9882826B791005C276B /* Headers */, + F608A9892826B791005C276B /* Sources */, + F608A98A2826B791005C276B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Core_Variant; + productName = Core_Variant; + productReference = F608A98C2826B791005C276B /* libCore_Variant.a */; + productType = "com.apple.product-type.library.static"; + }; + F608AAAD28270AA8005C276B /* Core_Variant_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F608AAB228270AA8005C276B /* Build configuration list for PBXNativeTarget "Core_Variant_Tests" */; + buildPhases = ( + F608AAAA28270AA8005C276B /* Sources */, + F608AAAB28270AA8005C276B /* Frameworks */, + F608AAAC28270AA8005C276B /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + F62C2BE22A500925007B43A3 /* PBXTargetDependency */, + ); + name = Core_Variant_Tests; + productName = Core_Variant_Tests; + productReference = F608AAAE28270AA8005C276B /* Core_Variant_Tests */; + productType = "com.apple.product-type.tool"; + }; + F6971F51282B123D008FBD17 /* Core_Variant_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = F6971F57282B123D008FBD17 /* Build configuration list for PBXNativeTarget "Core_Variant_iOS" */; + buildPhases = ( + F6971F52282B123D008FBD17 /* Headers */, + F6971F53282B123D008FBD17 /* Sources */, + F6971F56282B123D008FBD17 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Core_Variant_iOS; + productName = Core_Variant; + productReference = F6971F5A282B123D008FBD17 /* libCore_Variant_iOS.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F608A9842826B791005C276B /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + DefaultBuildSystemTypeForWorkspace = Original; + LastUpgradeCheck = 1330; + TargetAttributes = { + F608A98B2826B791005C276B = { + CreatedOnToolsVersion = 13.3; + }; + F608AAAD28270AA8005C276B = { + CreatedOnToolsVersion = 13.3; + }; + }; + }; + buildConfigurationList = F608A9872826B791005C276B /* Build configuration list for PBXProject "Core_Variant" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = F608A9832826B791005C276B; + productRefGroup = F608A98D2826B791005C276B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F608A98B2826B791005C276B /* Core_Variant */, + F6971F51282B123D008FBD17 /* Core_Variant_iOS */, + F608AAAD28270AA8005C276B /* Core_Variant_Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + F608A9892826B791005C276B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F666630828679CB900239768 /* VType+IO.cpp in Sources */, + F69548BF28289357005D1B64 /* Variant+Functional.cpp in Sources */, + F608AAFC28271FF8005C276B /* VType.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F608AAAA28270AA8005C276B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F69AB77F2B16D9DB000115BC /* VType_of.cpp in Sources */, + F608AAB128270AA8005C276B /* main.cpp in Sources */, + F608AAB528270AC8005C276B /* Variant.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F6971F53282B123D008FBD17 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F666630728679CB800239768 /* VType+IO.cpp in Sources */, + F6971F54282B123D008FBD17 /* Variant+Functional.cpp in Sources */, + F6971F55282B123D008FBD17 /* VType.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + F62C2BE22A500925007B43A3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F608A98B2826B791005C276B /* Core_Variant */; + targetProxy = F62C2BE12A500925007B43A3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + F608A98E2826B791005C276B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + ../Core_Zero, + ../Core_IO, + ../Core_Misc, + ../Core_Allocator, + ); + IPHONEOS_DEPLOYMENT_TARGET = 13.6; + LIBRARY_SEARCH_PATHS = ""; + "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = ( + "../Libraries/sdk/lib/Debug.iOS-arm64", + "../Libraries/project/Debug.iOS-arm64", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "../Libraries/sdk/lib/Debug.iOS-sim", + "../Libraries/project/Debug.iOS-sim", + ); + "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=arm64]" = ( + "../Libraries/sdk/lib/Debug.Darwin-arm64", + "../Libraries/project/Debug.Darwin-arm64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + USE_HEADERMAP = NO; + }; + name = Debug; + }; + F608A98F2826B791005C276B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + ../Core_Zero, + ../Core_IO, + ../Core_Misc, + ../Core_Allocator, + ); + IPHONEOS_DEPLOYMENT_TARGET = 13.6; + LIBRARY_SEARCH_PATHS = ""; + "LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = ( + "../Libraries/sdk/lib/Release.iOS-arm64", + "../Libraries/project/Release.iOS-arm64", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "../Libraries/sdk/lib/Release.iOS-sim", + "../Libraries/project/Release.iOS-sim", + ); + "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=arm64]" = ( + "../Libraries/sdk/lib/Release.Darwin-arm64", + "../Libraries/project/Release.Darwin-arm64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + USE_HEADERMAP = NO; + }; + name = Release; + }; + F608A9912826B791005C276B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + F608A9922826B791005C276B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + EXECUTABLE_PREFIX = lib; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + F608AAB328270AA8005C276B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + ENABLE_HARDENED_RUNTIME = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + LOG_TEST, + ); + HEADER_SEARCH_PATHS = ( + "${inherited}", + ../Core_Variant, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + F608AAB428270AA8005C276B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + ENABLE_HARDENED_RUNTIME = YES; + GCC_PREPROCESSOR_DEFINITIONS = LOG_TEST; + HEADER_SEARCH_PATHS = ( + "${inherited}", + ../Core_Variant, + ); + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + F6971F58282B123D008FBD17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + F6971F59282B123D008FBD17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = T2M28D3T75; + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + F608A9872826B791005C276B /* Build configuration list for PBXProject "Core_Variant" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F608A98E2826B791005C276B /* Debug */, + F608A98F2826B791005C276B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F608A9902826B791005C276B /* Build configuration list for PBXNativeTarget "Core_Variant" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F608A9912826B791005C276B /* Debug */, + F608A9922826B791005C276B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F608AAB228270AA8005C276B /* Build configuration list for PBXNativeTarget "Core_Variant_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F608AAB328270AA8005C276B /* Debug */, + F608AAB428270AA8005C276B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F6971F57282B123D008FBD17 /* Build configuration list for PBXNativeTarget "Core_Variant_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F6971F58282B123D008FBD17 /* Debug */, + F6971F59282B123D008FBD17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F608A9842826B791005C276B /* Project object */; +} diff --git a/Core_Variant.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Core_Variant.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Core_Variant.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Core_Variant.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Core_Variant.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Core_Variant.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Core_Variant.xcodeproj/xcshareddata/xcschemes/Core_Variant_Tests.xcscheme b/Core_Variant.xcodeproj/xcshareddata/xcschemes/Core_Variant_Tests.xcscheme new file mode 100644 index 0000000..9c1baf2 --- /dev/null +++ b/Core_Variant.xcodeproj/xcshareddata/xcschemes/Core_Variant_Tests.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f61a565 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +ROOTDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) +include $(ROOTDIR)/Core_Make/tjp/Make/Makefile diff --git a/Makefile.def b/Makefile.def new file mode 100755 index 0000000..7833dbb --- /dev/null +++ b/Makefile.def @@ -0,0 +1,6 @@ +timprepscius.core.include := $(timprepscius.core.include) -I $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +timprepscius.core.link := $(timprepscius.core.link) -L $(dir $(realpath $(lastword $(MAKEFILE_LIST))))/.bin/$(OBJDIR) + +timprepscius.core_variant.include := -I $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +timprepscius.core_variant.link := -L $(dir $(realpath $(lastword $(MAKEFILE_LIST))))/.bin/$(OBJDIR) + diff --git a/Makefile.project b/Makefile.project new file mode 100755 index 0000000..a4ff268 --- /dev/null +++ b/Makefile.project @@ -0,0 +1,18 @@ +include $(MAKEDIR)/Makefile.base + +# use: ls -d core/*/ core/*/*/ | rev | cut -c 2- | rev | sed 's/$/ \\/' + +PROJECTS := \ + tjp/core/variant \ + +#SRC_PCH := tjp/core/Precompile.pch + +INCPATH := \ + $(timprepscius.libraries.cpp.include) \ + $(timprepscius.core.include) + +LIBFILE := libCore_Variant.a + +COPYTO := $(LIBRARIES_PROJECT) + +include $(MAKEDIR)/Makefile.lib diff --git a/tests/Makefile b/tests/Makefile new file mode 120000 index 0000000..b8f87c1 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1 @@ +../../Make/Makefile \ No newline at end of file diff --git a/tests/Makefile.project b/tests/Makefile.project new file mode 100755 index 0000000..cf7e4ff --- /dev/null +++ b/tests/Makefile.project @@ -0,0 +1,31 @@ +include $(MAKEDIR)/Makefile.base + +# use: ls -d core/*/ core/*/*/ | rev | cut -c 2- | rev | sed 's/$/ \\/' + +PROJECTS := \ + . \ + ../core/variant/_tests \ + +INCPATH := \ + $(timprepscius.libraries.cpp.include) \ + $(timprepscius.core.include) + +LDPATH := $(timprepscius.libraries.cpp.link) + +LIBS := \ + -lCore_Variant \ + -lCore_Zero \ + -lCore_Misc \ + -lCore_Allocator \ + -lz_ + +EXEFILE := Core_Variant_Tests.exe + +#COPYTO := $(ROOTDIR)/.bin + +ifeq (Darwin,$(SYS_NAME)) + LIBS += -lc++ +endif + + +include $(MAKEDIR)/Makefile.bin diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..7fa20fc --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,20 @@ +// TJP COPYRIGHT HEADER + +#define CATCH_CONFIG_RUNNER +#include + +#include + +using namespace tjp; +using namespace core; + +int main( int argc, char* argv[] ) +{ +// xLogInitialize("Core_Variant_Tests.txt"); + xLogInitialize(); + xLogActivateStory("testing"); + xLogActivateStory("debug"); + + int result = Catch::Session().run( argc, argv ); + return result; +} diff --git a/tjp/core/variant/ConcreteVariant+IO.h b/tjp/core/variant/ConcreteVariant+IO.h new file mode 100644 index 0000000..a8323c8 --- /dev/null +++ b/tjp/core/variant/ConcreteVariant+IO.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ConcreteVariant.h" + +namespace tjp { +namespace core { +namespace variant { + +template +void io_bin(IO &io, ConcreteVariant &v) +{ + io.any((Variant &)v); +} + +template +void io_json(IO &io, ConcreteVariant &v) +{ + io.any((Variant &)v); +} + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/ConcreteVariant.h b/tjp/core/variant/ConcreteVariant.h new file mode 100644 index 0000000..69a57ea --- /dev/null +++ b/tjp/core/variant/ConcreteVariant.h @@ -0,0 +1,13 @@ +#pragma once + +namespace tjp { +namespace core { +namespace variant { + +template +struct ConcreteVariant; + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/ConcreteVariant.hpp b/tjp/core/variant/ConcreteVariant.hpp new file mode 100644 index 0000000..ca9f374 --- /dev/null +++ b/tjp/core/variant/ConcreteVariant.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include "ConcreteVariant.h" +#include "Variant.h" +#include + +namespace tjp { +namespace core { +namespace variant { + +#ifdef DEBUG + #define DEBUG_CONCRETE_VARIANT +#endif + +template +struct ConcreteVariant : Variant +{ + typedef Variant Super; + + #ifdef DEBUG_CONCRETE_VARIANT + T *debug_ = nullptr; + void execute_debug () + { + debug_ = ptr_of(ptr()); + } + #else + void execute_debug () {} + #endif + + T *operator ->() + { + return &Super::template ref(); + } + + T &operator *() + { + return Super::template ref(); + } + + ConcreteVariant() + { + } + + template + ConcreteVariant(const U &rhs) : + Super(rhs) + { + execute_debug(); + } + + template + ConcreteVariant &operator =(const U &rhs) + { + Super::template set<>(rhs); + execute_debug(); + return *this; + } + + auto ptr () + { + return Super::template ptr(); + } + + template + auto ptr () + { + return Super::template ptr(); + } + + auto valid () + { + return Super::template valid(); + } + + auto &variant () + { + return (Super &)*this; + } +} ; + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/Notes.txt b/tjp/core/variant/Notes.txt new file mode 100644 index 0000000..b7f21a5 --- /dev/null +++ b/tjp/core/variant/Notes.txt @@ -0,0 +1,21 @@ +When I redo VType + +I want to make IOType to be 3 unsigned integers. +type[0] is modifications, like, is it a vector +type[1] is category, like 0 is intrinsics, 1 is core, 2, network, 3, crown, etc. +type[2] is type, but with respect to category. + + +VType is u64; + +u32 + +struct { + u8 nothing; + u24 keyType; + u24 valueType; + u8 meta; +} ; + + + diff --git a/tjp/core/variant/VType+Functional.hpp b/tjp/core/variant/VType+Functional.hpp new file mode 100644 index 0000000..060b56f --- /dev/null +++ b/tjp/core/variant/VType+Functional.hpp @@ -0,0 +1,115 @@ +#pragma once + +#include "VType.hpp" +#include "VType_of.hpp" + +#include +#include + +#include +#include + +//#include + +#include +#include +#include +#include + +namespace tjp { +namespace core { + +inline +bool operator <(const VType &lhs, const VType &rhs) +{ + return lhs.id < rhs.id; +} + +inline +bool operator ==(const VType &lhs, const VType &rhs) +{ + return lhs.id == rhs.id; +} + +inline +bool operator !=(const VType &lhs, const VType &rhs) +{ + return lhs.id != rhs.id; +} + +template +constexpr +VType vtype_of_custom(const StrongPtr *) +{ + return vtype_of(); +} + +template +struct vtype_of_dispatch> { + static + constexpr + auto dispatch(const StrongPtr *t) { + return vtype_of_custom(t); + } +} ; + +template +constexpr +VType VType::type_of() +{ + return vtype_of(); +} + +template +constexpr +bool vtype_cast(const T &t, const VType &to) +{ + return false; +} + +template +constexpr +bool vtype_cast(const StrongPtr &t, const VType &to) +{ + return VType::type_cast(to); +} + +template +constexpr +bool vtype_cast_dispatch(const T *t, const VType &to) +{ + return vtype_cast(*t, to); +} + +template +constexpr +bool vtype_cast_dispatch(const VType &to) +{ + return vtype_cast_dispatch(nullptr, to); +} + +template<> +constexpr +bool vtype_cast_dispatch(const VType &to) +{ + return false; +} + +template +constexpr +bool vtype_cast(const VType &to) +{ + return vtype_cast_dispatch(to); +} + +template +constexpr +bool VType::type_cast(const VType &to) +{ + return vtype_cast_dispatch(to); +} + + +} // namespace +} // namespace + diff --git a/tjp/core/variant/VType+IO.cpp b/tjp/core/variant/VType+IO.cpp new file mode 100644 index 0000000..29b1e5b --- /dev/null +++ b/tjp/core/variant/VType+IO.cpp @@ -0,0 +1,13 @@ +#include "VType+IO.h" +#include + +namespace tjp { +namespace core { + +std::ostream &operator <<(std::ostream &o, const VType &v) +{ + return o << v.id; +} + +} // namespace +} // namespace diff --git a/tjp/core/variant/VType+IO.h b/tjp/core/variant/VType+IO.h new file mode 100644 index 0000000..0f2d376 --- /dev/null +++ b/tjp/core/variant/VType+IO.h @@ -0,0 +1,18 @@ +#pragma once + +#include "VType.hpp" +#include + +namespace tjp { +namespace core { + +template +void io_(IO &io, VType &v) +{ + io.any(v.id); +} + +std::ostream &operator <<(std::ostream &o, const VType &v); + +} // namespace +} // namespace diff --git a/tjp/core/variant/VType.cpp b/tjp/core/variant/VType.cpp new file mode 100644 index 0000000..b72f9ac --- /dev/null +++ b/tjp/core/variant/VType.cpp @@ -0,0 +1,10 @@ +#include "VType.hpp" + +namespace tjp { +namespace core { + +const VType VType::Null = {0}; + +} // namespace +} // namespace + diff --git a/tjp/core/variant/VType.h b/tjp/core/variant/VType.h new file mode 100644 index 0000000..dacc2fd --- /dev/null +++ b/tjp/core/variant/VType.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +namespace tjp::core { + +using VType_ID = u32; +using VType_Namespace = u8; +using VType_Class = u32; + +constexpr +VType_ID vtype_make(const VType_Namespace, const VType_Class); + +constexpr +VType_Namespace vtype_namespace(const VType_ID); + +constexpr +VType_Class vtype_class(const VType_ID); + +struct VType; + +bool operator <(const VType &lhs, const VType &rhs); +bool operator ==(const VType &lhs, const VType &rhs); +bool operator !=(const VType &lhs, const VType &rhs); + +template +struct vtype_of_dispatch; + +template +constexpr VType vtype_of(const T &); + +template +constexpr +VType vtype_of(); + +template +constexpr +VType_ID vtype_id(); + +template +constexpr +bool vtype_cast(const T &t, const VType &to); + +using Type_ = VType; + +} // namespace diff --git a/tjp/core/variant/VType.hpp b/tjp/core/variant/VType.hpp new file mode 100644 index 0000000..27582aa --- /dev/null +++ b/tjp/core/variant/VType.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "VType.h" + +namespace tjp { +namespace core { + +struct VType +{ + using Namespace = VType_Namespace; + using Class = VType_Class; + using ID = VType_ID; + + constexpr static Namespace primitive = 0; + const static VType Null; + + ID id; + + static + constexpr + VType make(Namespace, Class); + + template + static + constexpr + VType type_of(); + + template + static + constexpr + bool type_cast(const VType &to); + + constexpr + Namespace getNamespace() const { + return vtype_namespace(id); + } + + constexpr + Class getClass() const { + return vtype_class(id); + } +}; + +} // namespace +} // namespace + +#include "VType.inl" diff --git a/tjp/core/variant/VType.inl b/tjp/core/variant/VType.inl new file mode 100644 index 0000000..59a5bf1 --- /dev/null +++ b/tjp/core/variant/VType.inl @@ -0,0 +1,39 @@ +#include + +namespace tjp { +namespace core { + +constexpr VType_ID VType_Bits8 = 0xFF; + +constexpr +VType_ID vtype_make(const VType_Namespace n, const VType_Class c) +{ + auto r = + (VType_ID(c) << 8) | + (VType_ID(n)); + + return r; +} + +constexpr +VType_Namespace vtype_namespace(const VType_ID t) +{ + return VType_Namespace(t & VType_Bits8); +} + +constexpr +VType_Class vtype_class(const VType_ID t) +{ + return VType_Class((t >> 8)); +} + +inline +constexpr +VType VType::make(const Namespace n, const Class c) +{ + return { .id = vtype_make(n, c) }; +} + +} // namespace +} // namespace + diff --git a/tjp/core/variant/VType_of.hpp b/tjp/core/variant/VType_of.hpp new file mode 100644 index 0000000..95f6af2 --- /dev/null +++ b/tjp/core/variant/VType_of.hpp @@ -0,0 +1,102 @@ +#pragma once + +#include "VType.hpp" +#include +#include + +#include + +#include + +namespace tjp::core { + +constexpr +auto vtype_id_class_using(const StringView &v) +{ + return hash_compile(v); +} + +constexpr +auto vtype_id_using(const VType_Namespace n, const StringView &t) +{ + return vtype_make(n, vtype_id_class_using(t)); +} + +template +constexpr +auto vtype_id_from(const VType_Namespace n, const T *t) +{ + return vtype_id_using(n, type_name()); +} + +template +constexpr +VType vtype_from(const VType_Namespace n, const T *t) +{ + return { vtype_id_from(n, t) }; +} + +template +constexpr +VType vtype_from(const T *t) +{ + return vtype_from(0, t); +} + +static_assert(hash_compile("tjp::core::variant::Variant") == 2549889722U); + +// ------------ + +template +constexpr +VType vtype_of_custom(const T *t) +{ + return VType { vtype_id_from(0, t) }; +} + +template +struct vtype_of_dispatch { + static + constexpr + auto dispatch(const T *t) { + return vtype_of_custom(t); + } +} ; + +template +constexpr +VType vtype_of() +{ + // somehow, if these are not isolated as a constexpr before returning + // the compiler does not discard the temporaries, and full type names + // will exist in the code + constexpr VType result = + vtype_of_dispatch::dispatch(static_cast(nullptr)); + + return result; +} + +template<> +constexpr +VType vtype_of() +{ + // somehow, if these are not isolated as a constexpr before returning + // the compiler does not discard the temporaries, and full type names + // will exist in the code + constexpr VType result = + { vtype_make(0, vtype_id_class_using("void")) }; + + return result; +} + +template +constexpr +VType_ID vtype_id() +{ + constexpr auto result = vtype_of().id; + + return result; +} + + +} // namespace diff --git a/tjp/core/variant/VVector.h b/tjp/core/variant/VVector.h new file mode 100644 index 0000000..def3610 --- /dev/null +++ b/tjp/core/variant/VVector.h @@ -0,0 +1,22 @@ +#pragma once + +#include "VType.h" +#include + +namespace tjp { +namespace core { + +template +struct VVector : Vector +{ + using Super = Vector; + + VVector() {} + VVector(size_t size) : Super(size) {} + VVector(std::initializer_list l) : Super(l) {} + VVector(Super &&rhs) : Super(std::move(rhs)) {} + VVector(const Super &rhs) : Super(rhs) {} +}; + +} // namespace +} // namespace diff --git a/tjp/core/variant/Variant+Dispatch.h b/tjp/core/variant/Variant+Dispatch.h new file mode 100644 index 0000000..450b5b3 --- /dev/null +++ b/tjp/core/variant/Variant+Dispatch.h @@ -0,0 +1,28 @@ +#pragma once + +#include "Variant+IO.hpp" + +namespace tjp { +namespace core { +namespace variant { + +template +bool dispatch_type_builtin(int, D &d); + +template +struct dispatch_variant; + +template +struct dispatch_object; + +template +struct dispatch_array; + +template +struct dispatch_primitive; + +} // namespace +} // namespace +} // namespace + +#include "Variant+Dispatch.inl" diff --git a/tjp/core/variant/Variant+Dispatch.inl b/tjp/core/variant/Variant+Dispatch.inl new file mode 100644 index 0000000..204f612 --- /dev/null +++ b/tjp/core/variant/Variant+Dispatch.inl @@ -0,0 +1,99 @@ +#pragma once + +#include "VType.hpp" +#include "VariantSerialization.h" + +namespace tjp { +namespace core { +namespace variant { + +template +bool dispatch_type_builtin_value(VType type, D &d) +{ + switch(type.id) { + + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + case vtype_id(): d.template visit(); return true; + + } + + return false; +} + +template +void dispatch_primitive_if(D &d, const Type &type, T &t) +{ + d.dispatch_primitive(type, t); +} + +template +struct dispatch_primitive +{ + typedef dispatch_primitive Self; + T &variant; + D &d; + R r; + + struct Value + { + Self &self; + + template + void visit() + { + self.r.template visit(self.variant); + } + } ; + + dispatch_primitive(T &variant_, D &d_, R &&r_) : + variant(variant_), + d(d_), + r(std::move(r_)) + { + infer(); + } + + void infer () + { + Value v{*this}; + dispatch_primitive_if(d, variant.type, v); + } +} ; + +template +struct dispatch_variant +{ + typedef dispatch_variant Self; + T &variant; + D &d; + + dispatch_variant(T &variant_, D &d_, R &&r) : + d(d_), + variant(variant_) + { + infer(std::move(r)); + } + + void infer (R &&r) + { + if (variant.type == T::Type::Null) + r.visit_void(variant); + else + dispatch_primitive(variant, d, std::move(r)); + } +} ; + +} // namespace +} // namespace +} // namespace diff --git a/tjp/core/variant/Variant+Functional+Generate.hpp b/tjp/core/variant/Variant+Functional+Generate.hpp new file mode 100644 index 0000000..ac70286 --- /dev/null +++ b/tjp/core/variant/Variant+Functional+Generate.hpp @@ -0,0 +1,27 @@ + +template +Functions generateVariantFunctions (); + +template +Functions generateVariantFunctions () +{ + using Type = Type_; + + return Functions { + .construct = variant_construct, + .copy = variant_copy, + .destruct = variant_destruct, + .cast = Type::type_cast + }; +} + + +Functions generateVariantFunctionsVoid (); + +template<> +inline +Functions generateVariantFunctions () +{ + return generateVariantFunctionsVoid(); +} + diff --git a/tjp/core/variant/Variant+Functional.cpp b/tjp/core/variant/Variant+Functional.cpp new file mode 100644 index 0000000..0b7e9d4 --- /dev/null +++ b/tjp/core/variant/Variant+Functional.cpp @@ -0,0 +1,25 @@ +#include "Variant+Functional.hpp" + +namespace tjp { +namespace core { +namespace variant { + +Variant::Type Variant::voidType = Variant::Type::template type_of(); + +Functions generateVariantFunctionsVoid () +{ + using Type = Type_; + + return Functions { + [](Value &) {}, + [](Value &, const Value &) {}, + [](Value &) {}, + + [](const Type &) { return false; } + }; +} + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/Variant+Functional.hpp b/tjp/core/variant/Variant+Functional.hpp new file mode 100644 index 0000000..c420e3c --- /dev/null +++ b/tjp/core/variant/Variant+Functional.hpp @@ -0,0 +1,605 @@ +#pragma once + +#include "Variant.h" +#include "VType.hpp" +#include "VType+Functional.hpp" +#include "VariantSerialization.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace tjp { +namespace core { +namespace variant { + +#ifdef DEBUG + #define DEBUG_VARIANT +#else +// #define DEBUG_VARIANT +#endif + +// types +struct Value_ { + char memory [sizeof(core::ptr::StrongPtr)]; +} __attribute__ ((aligned (8))); + +typedef Value_ Value; + +inline +Value emptyValue () { + Value v; + memset(&v, 0, sizeof(v)); + return v; +} + +template struct is_intrinsic : std::false_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template<> struct is_intrinsic : std::true_type {}; +template struct is_intrinsic> : std::true_type {}; + +template struct is_variant : std::false_type {}; +template<> struct is_variant : std::true_type {}; + +// ------ SFINAE + +template +struct variant_type_ptr { + + template::value, U>::type* = nullptr> + static T *type_(); + + template::value, U>::type* = nullptr> + static StrongPtr type_(); + + + typedef decltype(type_()) type; +} ; + + +// ------ SFINAE + +template +using has_variant_allocator = allocators::has_strong_allocator; + +// ----- + +// variant + +template +T &deref (const Value &value) { + static_assert(sizeof(T) <= sizeof(Value)); + auto *vp = &value; + auto *pp = const_cast(reinterpret_cast(vp)); + return *pp; +} ; + +struct Functions { + using Type = Type_; + + std::function construct; + std::function copy; + std::function destruct; + + std::function cast; +}; + +DECLARE_EXCEPTION(CastException); + +template +void variant_construct(Value &lhs) { + new(&deref(lhs)) T(); +} + +template +void variant_copy(Value &lhs, const Value &rhs) { + deref(lhs) = deref(rhs); +} + +template +void variant_destruct(Value &lhs) { + deref(lhs).~T(); +}; + +#include "Variant+Functional+Generate.hpp" + +//#include "Variant+VariantFunctionalUsingSingleFunctionsObject.hpp" +#include "Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp" + +struct DefaultAllocator +{ + template + auto strong(Args && ...args) + { + return core::strong(std::forward(args)...); + } +} ; + +#ifdef DEBUG_VARIANT + #define CORE_VARIANT_INCLUDES_DEBUG_TYPE +#endif + +struct Variant +{ + using Type = Type_; + using Allocator_ = DefaultAllocator; + using Functional = VariantFunctional; + using Self = Variant; + using value_type = Value; + + Value value = emptyValue(); + mutable Functional functional; + + static Type voidType; + Type type = voidType; + + [[no_unique_address]] + Allocator_ defaultAllocator; + + Variant() + { + auto &functions = functional.functionsFor(type); + functions.construct(value); + } + + Variant(const Variant &rhs) + { + set(rhs); + } + + template + Variant(const Variant &rhs, U &allocator) + { + set(rhs, allocator); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + Variant(const T &t) + { + auto &functions = functional.functionsFor(type); + functions.construct(value); + + set(t); + } + + template< + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr + > + Variant(const T &t, U &allocator) + { + auto &functions = functional.functionsFor(type); + functions.construct(value); + + set(t, allocator); + } + + ~Variant() + { + auto &functions = functional.functionsFor(type); + functions.destruct(value); + } + + bool valid () const + { + return type != Type::template type_of(); + } + + template + bool valid () const + { + return is_() && (bool)ptr(); + } + + void clear () + { + inferTypeName(); + + if (type == voidType) + return; + + auto &f0 = functional.functionsFor(type); + f0.destruct(value); + + type = voidType; + auto &f1 = functional.ensureFunctions(); + f1.construct(value); + } + + template + T &ensure_() + { + inferTypeName(); + + if (!(type == Type::template type_of())) + { + if (!is_()) + { + debug_assert(false); + throw CastException{}; + } + + return deref(value); + } + + type = Type::template type_of(); + auto &functions = functional.template ensureFunctions(); + functions.construct(value); + + return deref(value); + } + + template + T &ensure_() + { + auto &r = ensure_(); + inferTypeName

(); + + return r; + } + + template + bool is_() const + { + auto otherType = Type::template type_of(); + + if (!(type == otherType)) + { + auto &functions = functional.functionsFor(type); + if (!functions.cast(otherType)) + return false; + } + + return true; + } + + bool is_serialization () const + { + return type == Type::template type_of(); + } + + template + T &ref_() const + { + if (!is_()) + { + throw CastException{}; + } + + return deref(value); + } + +#ifdef CORE_VARIANT_INCLUDES_DEBUG_TYPE + // debug + mutable StringView typeName; + + template + void inferTypeName() + { + typeName = type_unique_label_stringview(); + } + + template + void copyTypeName(const T &rhs) + { + typeName = rhs.typeName; + } + + StringView getTypeName() { + return typeName; + } + +#else + template + void inferTypeName () {} + + template + void copyTypeName(const T &rhs) {} + + StringView getTypeName() { + return {}; + } +#endif + + // copy + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs) + { + copyTypeName(rhs); + + auto &functions = functional.functionsFor(type); + functions.destruct(value); + + type = rhs.type; + auto &rhsFunctions = functional.ensureFunctions(type, rhs.functional.functionsFor(rhs.type)); + + rhsFunctions.construct(value); + rhsFunctions.copy(value, rhs.value); + } + + template< + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs, U &) + { + set(rhs); + } + + // intrinsic + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + T *ptr() + { + if (!is_()) + return nullptr; + + return &ref(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + T *ptr() const + { + if (!is_()) + return nullptr; + + return &ref(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs) + { + ensure_() = rhs; + } + + template< + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs, U &allocator) + { + ensure_() = rhs; + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + T &ref() + { + return ref_(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + T &ref() const + { + return ref_(); + } + + + template< + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr + > + T &load(U &) + { + return ensure_(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + T &load() + { + return load(defaultAllocator); + } + + + // pointer + + template::value, TP>::type* = nullptr> + void set(const TP rhs) + { + typedef typename std::remove_pointer::type T; + typedef StrongPtr P; + + ensure_() = rhs; + } + + + // complex + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + StrongPtr ptr() + { + typedef StrongPtr T_; + if (!is_()) + return StrongPtr(); + + return deref(value); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + const StrongPtr ptr() const + { + typedef StrongPtr T_; + if (!is_()) + return StrongPtr(); + + return deref(value); + } + + template< + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs, U &allocator) + { + typedef StrongPtr T_; + auto &p = ensure_(); + if (!p) + p = allocator.template strong(rhs); + else + *p = rhs; + } + + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + void set(const T &rhs) + { + set(rhs, defaultAllocator); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + T &ref() + { + typedef StrongPtr T_; + return *ref_(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + T &ref() const + { + typedef StrongPtr T_; + return *ref_(); + } + + template < + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + T &load(U &allocator) + { + typedef StrongPtr T_; + auto &ptr = ensure_(); + if (ptr == nullptr) + ptr = allocator.template strong(); + + return *ptr; + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr, + typename std::enable_if::value, T>::type* = nullptr + > + T &load() + { + return load(defaultAllocator); + } + + template < + typename T, + typename U, + typename std::enable_if::value, T>::type* = nullptr + > + void load(U &allocator) + { + clear(); + } + + template< + typename T, + typename std::enable_if::value, T>::type* = nullptr + > + void load() + { + return load(defaultAllocator); + } + + // -- operator = + + template + Variant &operator=(const T &rhs) + { + set(rhs); + return *this; + } + + // even though this should be covered by the operator = above, + // somehow the compiler misses this occasionally and must be explicity specified + Variant &operator=(const Variant &rhs) + { + set(rhs); + return *this; + } +} ; + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/Variant+IO.hpp b/tjp/core/variant/Variant+IO.hpp new file mode 100644 index 0000000..4a49594 --- /dev/null +++ b/tjp/core/variant/Variant+IO.hpp @@ -0,0 +1,137 @@ +#pragma once + +#include "VariantIO.hpp" +#include "Variant.hpp" +#include "VariantSerialization.hpp" +#include "VariantSerialization+IO.hpp" + +#include "VType.hpp" +#include "VType+IO.h" +#include + +namespace tjp { +namespace core { +namespace variant { + +template +struct io_bin_variant { + IO &io; + + template + void visit(T &t) + { + auto &v = t.template as(io); + io.any(v); + } + + void visit_void(T &v) {} +} ; + +template +void io_(IO &io, Variant &v) +{ + VariantIO vio{ v.type, v }; + io.object("type", vio.type, "value", io.custom(vio)); +} + +// ------------------------------------- + +#define IO_ENABLE_VARIANT_SERIALIZATION + +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +#ifdef IO_ENABLE_VARIANT_SERIALIZATION + + +// ---------------------- + +template +void deserialize_(IO &io, Variant &variant, const StrongPtr &serialization) +{ + auto io_ = io.partial(serialization->block); + variant = Variant(); + io_->any(variant); +} + +template +bool io_variant_deserialization_available(IO &io, Type_ type) +{ + return io.variant_deserialization_available(type); +} + +template +void deserialize_io(IO &io, Variant &variant) +{ + using Type = Type_; + if (variant.type == Type::template type_of()) + { + auto serialization = variant.template ptr(); + if (io_variant_deserialization_available(io, serialization->type)) + { + deserialize_(io, variant, serialization); + } + } +} + +// ---------------------- + +template +void io_w_serialization(IO &io, const Variant &v) +{ + VariantSerialization s(v, io); + Variant v_(s); + + VariantIO vio{ v_.type, v_ }; + io.object("type", vio.type, "value", io.custom(vio)); +} + +template +bool io_use_variant_serialization_for(IO &io, const T &t) +{ + return io.use_variant_serialization_for(t); +} + +template +void io_w(IO &io, const Variant &v) +{ + typedef Variant V; + if (io_use_variant_serialization_for(io, v)) + { + return io_w_serialization(io, v); + } + + io_(io, const_cast(v)); +} + +template +void io_r(IO &io, Variant &v) +{ + VariantIO vio{ v.type, v }; + io.object("type", vio.type, "value", io.custom(vio)); + deserialize_io(io, v); +} + +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +#else +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- + +template +void io_bin(IO &io, Variant &v) { return io_(io, v); } + +template +void io_json(IO &io, Variant &v) { return io_(io, v); } + + +#endif +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- + +} // namespace +} // namespace +} // namespace diff --git a/tjp/core/variant/Variant+VariantFunctionalUsingMap.hpp b/tjp/core/variant/Variant+VariantFunctionalUsingMap.hpp new file mode 100644 index 0000000..06441ca --- /dev/null +++ b/tjp/core/variant/Variant+VariantFunctionalUsingMap.hpp @@ -0,0 +1,77 @@ + +// VariantFunctionalUsingMap implements the functional aspect of a variant, +// using both a Map to look up the functions object. +// +// I did this, because at the time of writing it was still unclear exactly what types would be needed +// and when they would be needed, and then I also didn't know the overhead of constructing the +// Function<> objects. + +template +struct VariantFunctionalUsingMap +{ + typedef Type_ Type; + + struct FunctionsMap { + SharedMutex mutex; + std::map> values; + } ; + + static FunctionsMap *functionsMap_; + static std::once_flag initializeFunctionMapFlag; + static void initializeFunctionMap () + { + functionsMap_ = new FunctionsMap(); + (*functionsMap_).values[Type::template type_of()] = + generateVariantFunctionsVoid(); + } + + static FunctionsMap &functionsMap () + { + std::call_once(initializeFunctionMapFlag, initializeFunctionMap); + return *functionsMap_; + } + + template + static Functions &ensureFunctions() + { + Type type = Type::template type_of(); + auto &functions = functionsMap(); + auto r = shared_lock_of(functions.mutex); + + auto i = functions.values.find(type); + if (i == functions.values.end()) + { + r.unlock(); + auto w = lock_of(functions.mutex); + + auto variantFunctions = generateVariantFunctions(); + auto emplaced = functions.values.insert({type, variantFunctions}); + i = emplaced.first; + } + + return i->second; + } + + static const Functions &ensureFunctions(Type type_, const Functions &functions_) + { + return functions_; + } + + static Functions &functionsFor(Type type) + { + auto &functions = functionsMap(); + auto r = shared_lock_of(functions.mutex); + + auto i = functions.values.find(type); + debug_assert(i != functions.values.end()); + + return i->second; + } +} ; + +template +typename VariantFunctionalUsingMap::FunctionsMap *VariantFunctionalUsingMap::functionsMap_ = nullptr; + +template +std::once_flag VariantFunctionalUsingMap::initializeFunctionMapFlag; + diff --git a/tjp/core/variant/Variant+VariantFunctionalUsingMapAndVectorCache.hpp b/tjp/core/variant/Variant+VariantFunctionalUsingMapAndVectorCache.hpp new file mode 100644 index 0000000..7bc54a9 --- /dev/null +++ b/tjp/core/variant/Variant+VariantFunctionalUsingMapAndVectorCache.hpp @@ -0,0 +1,122 @@ + +// VariantFunctionalUsingMapAndVectorCache implements the functional aspect of a variant, +// using both a Map lookup for complex types and a Vector cache for indexing into commonly used +// types. This is significantly faster. + +template +struct VariantFunctionalUsingMapAndVectorCache +{ + typedef Type_ Type; + + struct CacheItem { + bool cached = false; + Functions functions; + + void set(Functions &&functions_) + { + functions = std::move(functions_); + cached = true; + } + } ; + + struct FunctionsMap + { + typedef CacheItem Cache; + static constexpr size_t maxCache = 256; + Cache cache[maxCache]; + + SharedMutex mutex; + std::map> values; + } ; + + static FunctionsMap *functionsMap_; + static std::once_flag initializeFunctionMapFlag; + static void initializeFunctionMap () + { + functionsMap_ = new FunctionsMap(); + + auto type = Type::template type_of(); + + auto cacheIndex = type.id; + debug_assert(cacheIndex < functionsMap_->maxCache); + + auto &item = functionsMap_->cache[cacheIndex]; + item.set(generateVariantFunctionsVoid()); + } + + static FunctionsMap &functionsMap () + { + std::call_once(initializeFunctionMapFlag, initializeFunctionMap); + return *functionsMap_; + } + + template + static Functions &ensureFunctions() + { + auto &functions = functionsMap(); + + Type type = Type::template type_of(); + + auto cacheIndex = type.id; + if (cacheIndex < functions.maxCache) + { + auto &item = functions.cache[cacheIndex]; + if (item.cached) + return item.functions; + + auto w = lock_of(functions.mutex); + if (!item.cached) + item.set(generateVariantFunctions()); + + return item.functions; + } + + auto r = shared_lock_of(functions.mutex); + + auto i = functions.values.find(type); + if (i == functions.values.end()) + { + r.unlock(); + auto w = lock_of(functions.mutex); + + auto variantFunctions = generateVariantFunctions(); + auto emplaced = functions.values.insert({type, variantFunctions}); + i = emplaced.first; + } + + return i->second; + } + + static const Functions &ensureFunctions(Type type_, const Functions &functions_) + { + return functions_; + } + + static Functions &functionsFor(Type type) + { + auto &functions = functionsMap(); + + auto cacheIndex = type.id; + if (cacheIndex < functions.maxCache) + { + auto &item = functions.cache[cacheIndex]; + debug_assert(item.cached); + + return item.functions; + } + + auto r = shared_lock_of(functions.mutex); + + auto i = functions.values.find(type); + debug_assert(i != functions.values.end()); + + return i->second; + } +} ; + + +template +typename VariantFunctionalUsingMapAndVectorCache::FunctionsMap *VariantFunctionalUsingMapAndVectorCache::functionsMap_ = nullptr; + +template +std::once_flag VariantFunctionalUsingMapAndVectorCache::initializeFunctionMapFlag; diff --git a/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObject.hpp b/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObject.hpp new file mode 100644 index 0000000..3cf7457 --- /dev/null +++ b/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObject.hpp @@ -0,0 +1,39 @@ + + +// VariantFunctionalUsingSingleFunctionsObject implements the functional aspect of a variant +// without using any lookups or caching. If the Function<> objects don't use the heap, and +// are nearly instantaneous to construct, this is the best option. +// +// And it turns out that Function<> objects don't use the heap if they capture < threshold bytes +// and are in fact nearly instantaneous to construct + +struct VariantFunctionalUsingSingleFunctionsObject +{ + typedef Type_ Type; + + Type type = Type::template type_of(); + Functions functions = generateVariantFunctions(); + + template + const Functions &ensureFunctions() + { + type = Type::template type_of(); + functions = generateVariantFunctions(); + return functions; + } + + const Functions &ensureFunctions(Type type_, const Functions &functions_) + { + type = type_; + functions = functions_; + return functions; + } + + const Functions &functionsFor(Type type) const + { + debug_assert(type == type); + return functions; + } +} ; + +using VariantFunctional = VariantFunctionalUsingSingleFunctionsObject; diff --git a/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp b/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp new file mode 100644 index 0000000..17cd908 --- /dev/null +++ b/tjp/core/variant/Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp @@ -0,0 +1,67 @@ + + +// VariantFunctionalUsingSingleFunctionsObject implements the functional aspect of a variant +// without using any lookups or caching. If the Function<> objects don't use the heap, and +// are nearly instantaneous to construct, this is the best option. +// +// And it turns out that Function<> objects don't use the heap if they capture < threshold bytes +// and are in fact nearly instantaneous to construct + +template +struct SingleFunctionsObject { + static const Functions functions_; + + static const Functions *functions() { + return &functions_; + } +} ; + +template +const Functions SingleFunctionsObject::functions_ = generateVariantFunctions(); + +#ifdef DEBUG_VARIANT + #define VARIANT_FUNCTIONS_INCLUDE_TYPE +#endif + +struct VariantFunctionalUsingSingleFunctionsObjectPointer +{ + typedef Type_ Type; + +#ifdef VARIANT_FUNCTIONS_INCLUDE_TYPE + Type type = Type::template type_of(); +#endif + + const Functions *functions = SingleFunctionsObject::functions(); + + void setType(Type type_) + { +#ifdef VARIANT_FUNCTIONS_INCLUDE_TYPE + type = type_; +#endif + } + + template + const Functions &ensureFunctions() + { + setType(Type::template type_of()); + functions = SingleFunctionsObject::functions(); + return *functions; + } + + const Functions &ensureFunctions(Type type_, const Functions &functions_) + { + setType(type_); + functions = &functions_; + return *functions; + } + + const Functions &functionsFor(Type type) const + { +#ifdef VARIANT_FUNCTIONS_INCLUDE_TYPE + debug_assert(type == type); +#endif + return *functions; + } +} ; + +using VariantFunctional = VariantFunctionalUsingSingleFunctionsObjectPointer; diff --git a/tjp/core/variant/Variant.h b/tjp/core/variant/Variant.h new file mode 100644 index 0000000..efd2115 --- /dev/null +++ b/tjp/core/variant/Variant.h @@ -0,0 +1,23 @@ +#pragma once + +#include "VType.h" + +namespace tjp { +namespace core { +namespace variant { + +struct DefaultAllocator; + +struct Variant; +struct VariantSerialization; +struct Functions; + +struct CastException; + +template +Functions generateVariantFunctions (); + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/Variant.hpp b/tjp/core/variant/Variant.hpp new file mode 100644 index 0000000..89af3b9 --- /dev/null +++ b/tjp/core/variant/Variant.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "Variant+Functional.hpp" + +namespace tjp { +namespace core { +namespace variant { + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/VariantIO.h b/tjp/core/variant/VariantIO.h new file mode 100644 index 0000000..303e6d9 --- /dev/null +++ b/tjp/core/variant/VariantIO.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Variant.h" + +namespace tjp { +namespace core { +namespace variant { + +struct VariantIO; + +} // namespace +} // namespace +} // namespace diff --git a/tjp/core/variant/VariantIO.hpp b/tjp/core/variant/VariantIO.hpp new file mode 100644 index 0000000..14c8918 --- /dev/null +++ b/tjp/core/variant/VariantIO.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "VariantIO.h" +#include "Variant.hpp" + +namespace tjp { +namespace core { +namespace variant { + +// ------------------------------------- + +struct VariantIO { + typedef Type_ Type; + + Type type; + Variant &variant; + + template< + typename T, + typename IO, + typename std::enable_if::value, IO>::type* = nullptr + > + auto &as(IO &io) + { + return variant.load(io.allocator); + } + + template< + typename T, + typename IO, + typename std::enable_if::value, IO>::type* = nullptr + > + auto &as(IO &io) + { + return variant.load(); + } +} ; + +} // namespace +} // namespace +} // namespace diff --git a/tjp/core/variant/VariantSerialization+IO.hpp b/tjp/core/variant/VariantSerialization+IO.hpp new file mode 100644 index 0000000..ae0950f --- /dev/null +++ b/tjp/core/variant/VariantSerialization+IO.hpp @@ -0,0 +1,24 @@ +#pragma once + +namespace tjp { +namespace core { +namespace variant { + +// ------------------------------------- + +template +void io_(IO &io, VariantSerialization &v) +{ + io.object("type", v.type, "block", v.block); +} + +template +void io_json(IO &io, VariantSerialization &v) { return io_(io, v); } + +template +void io_bin(IO &io, VariantSerialization &v) { return io_(io, v); } + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/VariantSerialization.h b/tjp/core/variant/VariantSerialization.h new file mode 100644 index 0000000..75121f0 --- /dev/null +++ b/tjp/core/variant/VariantSerialization.h @@ -0,0 +1,14 @@ +#pragma once + +#include "VType.hpp" + +namespace tjp { +namespace core { +namespace variant { + +struct VariantSerialization; + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/VariantSerialization.hpp b/tjp/core/variant/VariantSerialization.hpp new file mode 100644 index 0000000..8421395 --- /dev/null +++ b/tjp/core/variant/VariantSerialization.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "VariantIO.hpp" + +namespace tjp { +namespace core { +namespace variant { + +struct VariantSerialization +{ + typedef std::vector Block; + + Type_ type; + Block block; + + VariantSerialization() {} + + template + VariantSerialization(const Variant &v, IO &io) + { + auto &v_ = const_cast(v); + + auto io_ = io.partial(); + + VariantIO vio{ v_.type, v_ }; + io_.object("type", v.type, "value", io_.custom(vio)); + + type = v.type; + block = io_.partial_serialization(); + } ; +} ; + +} // namespace +} // namespace +} // namespace + diff --git a/tjp/core/variant/_tests/VType_of.cpp b/tjp/core/variant/_tests/VType_of.cpp new file mode 100644 index 0000000..f009585 --- /dev/null +++ b/tjp/core/variant/_tests/VType_of.cpp @@ -0,0 +1,132 @@ +// TJP COPYRIGHT HEADER + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +namespace tjp::core { +namespace variant_testing { + +struct X1 {}; + +constexpr +VType vtype_of_custom(const X1 *) +{ + return vtype_from("X"); +} + +SCENARIO("core::variant::VType_of_strings") +{ + GIVEN("compile vs runtime") + { + struct abcdefgh {}; + +// sLogTest("testing", +// logVar(type_name())); + + constexpr auto x = vtype_of(); + + sLogTest("testing", + logVar(x)); + + sLogTest("testing", + logVar(vtype_of())); + + } +} + +SCENARIO("core::variant::VType_of") +{ + GIVEN("compile vs runtime") + { + using A = VType; + + sLogTest("testing", + logVar(type_name()) << + logVar(type_name()) << + logVar(type_name()) << + logVar(type_name()) << + logVar(type_name>()) + ); + + sLogTest("testing", + logVar(rtti::impl::format.leading_junk) << + logVar(rtti::impl::format.trailing_junk) + ); + + sLogTest("testing", + "\n" << rtti::impl::RawTypeName() << + "\n" << type_name() << + + "\n" << rtti::impl::RawTypeName() << + "\n" << type_name() << + + "\n" << rtti::impl::RawTypeName() << + "\n" << type_name() << + + "\n" << rtti::impl::RawTypeName() << + "\n" << type_name() << + + "\n" << rtti::impl::RawTypeName() << + "\n" << type_name() << + + "\n" << rtti::impl::RawTypeName>() << + "\n" << type_name>() + ); + + sLogTest("testing", + logVar(hash_compile(type_name())) << + logVar(hash_compile(type_name())) << + logVar(hash_runtime(type_name())) << + logVar(hash_runtime(type_name())) + ); + + constexpr VType v0 = vtype_of(); + constexpr VType v1 = vtype_of(); + + constexpr VType xt = vtype_of(); + constexpr VType xt_ = core::vtype_from("X"); + constexpr int xti = xt.id; + constexpr int xt_i = xt_.id; + + static_assert(xti == xt_i); + REQUIRE(xt.id == xt_.id); + + constexpr VType xtv = VType::type_of(); + REQUIRE(xt == xtv); + + + + + sLogTest("testing", + logVar(v0) << logVar(v1)); + } +} + +} // namespace + +namespace variant_testing_2 { + +SCENARIO("core::variant::VType_of::other_namespace") +{ + GIVEN("compile vs runtime") + { + constexpr VType xt = vtype_of(); + constexpr VType xt_ = vtype_from("X"); + REQUIRE(xt == xt_); + + constexpr VType xtv = VType::type_of(); + REQUIRE(xt == xtv); + } +} + +} // namespace +} // namespace diff --git a/tjp/core/variant/_tests/Variant.cpp b/tjp/core/variant/_tests/Variant.cpp new file mode 100644 index 0000000..928f8cf --- /dev/null +++ b/tjp/core/variant/_tests/Variant.cpp @@ -0,0 +1,379 @@ +// TJP COPYRIGHT HEADER + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------------- +// because the custom map type is actually in the std namespace +// we can either make it in the std namespace or put it in the variant namespace +namespace tjp::core::variant { + +typedef std::map CustomMapType; + +constexpr +VType vtype_of_custom(const CustomMapType *) { return VType::make(30, 13); } + +} // namespace +// ------------------------------------------------------------------------------- + +namespace tjp::core::variant::test_compile { + +typedef std::map CustomMapType; + +constexpr +VType vtype_of_custom(const CustomMapType *) { return VType::make(30, 13); } + +struct Custom +{ + int i; +} ; + +constexpr +VType vtype_of_custom(const Custom *) { return VType::make(64, 23); } + +struct External +{ + int x; +} ; + +constexpr +VType vtype_of_custom(const External *) { return VType::make(65, 33); } + +template +void io_bin(IO &io, Custom &a) +{ + io.all(a.i); +} + +template +void io_bin(IO &io, External &a) +{ + io.all(a.x); +} + +struct DispatchVariant +{ + template + void dispatch_custom(IO &io, VariantIO &v) + { + core::variant::dispatch_variant( + v, + *this, + io_bin_variant { io } + ); + } + + template + void dispatch_primitive(VType type, D &d) + { + if (core::variant::dispatch_type_builtin_value(type, d)) + return; + + switch(type.getNamespace()) + { + case 30: + { + switch (type.getClass()) + { + case 13: return d.template visit(); + } + } break; + case 64: + { + switch (type.getClass()) + { + case 23: return d.template visit(); + } + } + } + + debug_assert(false); + } + + template + bool use_variant_serialization_for(const V &v) + { + auto primary = vtype_namespace(v.type.id); + return primary > 64; + } + + bool variant_deserialization_available(VType type) + { + auto primary = vtype_namespace(type.id); + return primary <= 64; + } +} ; + +struct DispatchVariantHandleExternal : DispatchVariant +{ + template + void dispatch_custom(IO &io, VariantIO &v) + { + core::variant::dispatch_variant( + v, + *this, + io_bin_variant { io } + ); + } + + template + void dispatch_primitive(VType type, D &d) + { + auto ns = type.getNamespace(); + unused(ns); + + if (core::variant::dispatch_type_builtin_value(type, d)) + return; + + switch(type.getNamespace()) + { + case 30: + { + switch (type.getClass()) + { + case 13: return d.template visit(); + } + } break; + case 64: + { + switch (type.getClass()) + { + case 23: return d.template visit(); + } + } + case 65: + { + switch (type.getClass()) + { + case 33: return d.template visit(); + } + } + } + + debug_assert(false); + } + + template + bool use_variant_serialization_for(const V &v) + { + return v.type.getNamespace() > 64; + } + + bool variant_deserialization_available(VType type) + { + return true; + } +} ; + +struct PoolAllocatorTest +{ + typedef void is_strong_allocator; + + template + void allocate(T &t) + { + io_ptr_allocate_default(*this, t); + } + + template + auto strong(Args && ...args) + { + return core::strong(std::forward(args)...); + } +} ; + + +SCENARIO("core::variant") +{ + GIVEN("nothing") + { + sLogTest("testing", + logVar(sizeof(Variant)) << + logVar(sizeof(Variant::Functional)) << + logVar(sizeof(Variant::value_type)) << + logVar(sizeof(Variant::Type)) << + logVar(sizeof(Variant::Allocator_)) + ); + } + + GIVEN("a variant") + { + Variant v; + + WHEN("variant is set to a unknown") + { + auto c = External { 5 }; + v = c; + + constexpr auto cv = vtype_of(); + constexpr auto cvn = cv.getNamespace(); + static_assert(cvn == 65); + REQUIRE(cv.getNamespace() == 65); + + auto vt = v.type; + REQUIRE(vt == cv); + + THEN("unknown is set") + { + REQUIRE(v.ref().x == c.x); + } + + WHEN("the variant with unknown is serialized from external -> internal -> internal -> external") + { + typedef io::bin::Writer WriterInternal; + typedef io::bin::Reader ReaderInternal; + typedef io::bin::Writer WriterExternal; + typedef io::bin::Reader ReaderExternal; + + WriterExternal wE; + auto s1 = io::bin::serializeTo(wE, v); + + ReaderInternal rI({ s1.data(), s1.size() }); + auto v2 = io::bin::deserializeFrom(rI); + + WriterInternal wI; + auto s2 = io::bin::serializeTo(wI, v2); + + ReaderExternal rE({ s2.data(), s2.size() }); + auto v_ = io::bin::deserializeFrom(rE); + + THEN("unknown survives") + { + REQUIRE(v.ref().x == c.x); + } + } + } + + WHEN("variant is set to a number") + { + auto c = 5; + v = c; + + THEN("number is set") + { + REQUIRE(v.ref() == c); + } + } + + WHEN("variant is set to a string") + { + auto c = std::string("hello"); + v = c; + + THEN("value is set") + { + REQUIRE(v.ref() == c); + } + } + + WHEN("variant is set to a map") + { + float onePZero = 1.0; + double threeP5 = 3.5; + + auto c = CustomMapType(); + c["hi"] = onePZero; + c["there"] = Variant(threeP5); + c["what"] = Custom{ .i = 10 }; + c["recursive"] = CustomMapType { { "a", onePZero }}; + + v = c; + + THEN("hi value is set") + { + auto l = v.ref()["hi"].ref(); + auto r = c["hi"].ref(); + + REQUIRE(l == r); + } + + THEN("there value is set") + { + auto l = v.ref()["there"].ref(); + auto r = c["there"].ref(); + + REQUIRE(l == r); + } + + THEN("the value is serialized and deserialized") + { + typedef io::bin::Writer Writer; + typedef io::bin::Reader Reader; + + io::bin::Serialization s1; + + Writer w1; + s1 = io::bin::serializeTo(w1, v); + + Reader reader({ s1.data(), s1.size() }); + auto v2 = io::bin::deserializeFrom(reader); + + auto &m = v2.ref(); + REQUIRE(m["hi"].ref() == onePZero); + REQUIRE(m["there"].ref() == threeP5); + REQUIRE(m["recursive"].ref()["a"].ref() == onePZero); + } + + THEN("the value is serialized deserialized and serialized again") + { + typedef io::bin::Writer Writer; + typedef io::bin::Reader Reader; + + io::bin::Serialization s1, s2; + + { + Writer w1; + s1 = io::bin::serializeTo(w1, v); + + Reader reader({ s1.data(), s1.size() }); + auto v2 = io::bin::deserializeFrom(reader); + + Writer w2; + s2 = io::bin::serializeTo(w2, v2); + } + + REQUIRE(s1 == s2); + } + + + THEN("the value is serialized deserialized and serialized again with a pool allocator") + { + typedef io::bin::Writer Writer; + typedef io::bin::Reader Reader; + + io::bin::Serialization s1, s2; + + static_assert(allocators::has_allocator::value); + static_assert(has_variant_allocator::value); + static_assert(allocators::has_strong_allocator_flag::value); + + { + Writer w1; + s1 = io::bin::serializeTo(w1, v); + + Reader reader({ s1.data(), s1.size() }); + auto v2 = io::bin::deserializeFrom(reader); + + Writer w2; + s2 = io::bin::serializeTo(w2, v2); + } + + REQUIRE(s1 == s2); + } + + } + } +} + + +} // namespace