flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:41:23 -05:00
commit d33ec72fa2
43 changed files with 3296 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.DS_Store
*.pyc
xcuserdata
.bin

View File

@@ -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 = "<group>"; };
F608AA6D2826BCD8005C276B /* Variant+Dispatch.inl */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Variant+Dispatch.inl"; sourceTree = "<group>"; };
F608AA6E2826BCD8005C276B /* ConcreteVariant.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ConcreteVariant.hpp; sourceTree = "<group>"; };
F608AA702826BCD8005C276B /* VType.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VType.hpp; sourceTree = "<group>"; };
F608AA712826BCD8005C276B /* VType+IO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VType+IO.h"; sourceTree = "<group>"; };
F608AA722826BCD8005C276B /* ConcreteVariant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConcreteVariant.h; sourceTree = "<group>"; };
F608AA732826BCD8005C276B /* VType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VType.cpp; sourceTree = "<group>"; };
F608AA742826BCD8005C276B /* VariantIO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VariantIO.hpp; sourceTree = "<group>"; };
F608AA752826BCD8005C276B /* VariantIO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VariantIO.h; sourceTree = "<group>"; };
F608AA762826BCD8005C276B /* ConcreteVariant+IO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ConcreteVariant+IO.h"; sourceTree = "<group>"; };
F608AA772826BCD8005C276B /* VariantSerialization+IO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "VariantSerialization+IO.hpp"; sourceTree = "<group>"; };
F608AA782826BCD8005C276B /* Variant+Dispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Variant+Dispatch.h"; sourceTree = "<group>"; };
F608AA792826BCD8005C276B /* VType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VType.h; sourceTree = "<group>"; };
F608AA7A2826BCD8005C276B /* Variant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Variant.h; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
F608AB6E2827F3CE005C276B /* Makefile.project */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.project; sourceTree = "<group>"; };
F608AB9328282DF3005C276B /* Variant+VariantFunctionalUsingMap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingMap.hpp"; sourceTree = "<group>"; };
F608AB9428282E40005C276B /* Variant+VariantFunctionalUsingMapAndVectorCache.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingMapAndVectorCache.hpp"; sourceTree = "<group>"; };
F608AB9528282E8E005C276B /* Variant+VariantFunctionalUsingSingleFunctionsObject.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+VariantFunctionalUsingSingleFunctionsObject.hpp"; sourceTree = "<group>"; };
F608AB9D28283866005C276B /* VariantSerialization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VariantSerialization.h; sourceTree = "<group>"; };
F608AB9E2828387E005C276B /* VariantSerialization.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VariantSerialization.hpp; sourceTree = "<group>"; };
F608ABA028283CC7005C276B /* Variant+IO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+IO.hpp"; sourceTree = "<group>"; };
F608ABA128284A65005C276B /* VType+Functional.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "VType+Functional.hpp"; sourceTree = "<group>"; };
F608ABA228284B6C005C276B /* Variant+Functional.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+Functional.hpp"; sourceTree = "<group>"; };
F608ABA328285011005C276B /* Variant.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Variant.hpp; sourceTree = "<group>"; };
F61F9BEC2C6E4CB400F79137 /* Makefile.project */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.project; sourceTree = "<group>"; };
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 = "<group>"; };
F62C2BDF2A5005A9007B43A3 /* Variant+Functional+Generate.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "Variant+Functional+Generate.hpp"; sourceTree = "<group>"; };
F666630628679CAE00239768 /* VType+IO.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "VType+IO.cpp"; sourceTree = "<group>"; };
F680BDB3285645BA00044A4F /* VType.inl */ = {isa = PBXFileReference; lastKnownFileType = text; path = VType.inl; sourceTree = "<group>"; };
F680BDB628567BCF00044A4F /* VVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VVector.h; sourceTree = "<group>"; };
F69548BE2828930D005D1B64 /* Variant+Functional.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "Variant+Functional.cpp"; sourceTree = "<group>"; };
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 = "<group>"; };
F69AB77E2B16D8CE000115BC /* VType_of.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VType_of.cpp; sourceTree = "<group>"; };
F6BF9BE22E3901E3002E6AF0 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
F6FC229E284F73DA00A6381D /* Notes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Notes.txt; sourceTree = "<group>"; };
/* 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 = "<group>";
};
F608A98D2826B791005C276B /* Products */ = {
isa = PBXGroup;
children = (
F608A98C2826B791005C276B /* libCore_Variant.a */,
F608AAAE28270AA8005C276B /* Core_Variant_Tests */,
F6971F5A282B123D008FBD17 /* libCore_Variant_iOS.a */,
);
name = Products;
sourceTree = "<group>";
};
F608A9B52826BA8C005C276B /* core */ = {
isa = PBXGroup;
children = (
F608AA6B2826BCD8005C276B /* variant */,
);
path = core;
sourceTree = "<group>";
};
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 = "<group>";
};
F608AAAF28270AA8005C276B /* tests */ = {
isa = PBXGroup;
children = (
F61F9BEC2C6E4CB400F79137 /* Makefile.project */,
F608AAB028270AA8005C276B /* main.cpp */,
);
path = tests;
sourceTree = "<group>";
};
F608AAB828271CFE005C276B /* Frameworks */ = {
isa = PBXGroup;
children = (
F61F9BEE2C6E4D7300F79137 /* libCore_Allocator.a */,
F608AAB928271CFE005C276B /* libCore_Zero.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
F61D7C3F2E381655002A1AED /* tjp */ = {
isa = PBXGroup;
children = (
F608A9B52826BA8C005C276B /* core */,
);
path = tjp;
sourceTree = "<group>";
};
F61F9BED2C6E4CEC00F79137 /* _tests */ = {
isa = PBXGroup;
children = (
F608AA6C2826BCD8005C276B /* Variant.cpp */,
F69AB77E2B16D8CE000115BC /* VType_of.cpp */,
);
path = _tests;
sourceTree = "<group>";
};
/* 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 */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1420"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F608AAAD28270AA8005C276B"
BuildableName = "Core_Variant_Tests"
BlueprintName = "Core_Variant_Tests"
ReferencedContainer = "container:Core_Variant.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
viewDebuggingEnabled = "No">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F608AAAD28270AA8005C276B"
BuildableName = "Core_Variant_Tests"
BlueprintName = "Core_Variant_Tests"
ReferencedContainer = "container:Core_Variant.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "&quot;Scenario: core::variant::VType_of&quot;"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "&quot;Scenario: core::variant::VType_of::other_namespace&quot;"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-s -b"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F608AAAD28270AA8005C276B"
BuildableName = "Core_Variant_Tests"
BlueprintName = "Core_Variant_Tests"
ReferencedContainer = "container:Core_Variant.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

2
Makefile Normal file
View File

@@ -0,0 +1,2 @@
ROOTDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..)
include $(ROOTDIR)/Core_Make/tjp/Make/Makefile

6
Makefile.def Executable file
View File

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

18
Makefile.project Executable file
View File

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

1
tests/Makefile Symbolic link
View File

@@ -0,0 +1 @@
../../Make/Makefile

31
tests/Makefile.project Executable file
View File

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

20
tests/main.cpp Normal file
View File

@@ -0,0 +1,20 @@
// TJP COPYRIGHT HEADER
#define CATCH_CONFIG_RUNNER
#include <tjp/core/testing/catch.hpp>
#include <tjp/core/log/Log.h>
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;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include "ConcreteVariant.h"
namespace tjp {
namespace core {
namespace variant {
template<typename IO, typename T>
void io_bin(IO &io, ConcreteVariant<T> &v)
{
io.any((Variant &)v);
}
template<typename IO, typename T>
void io_json(IO &io, ConcreteVariant<T> &v)
{
io.any((Variant &)v);
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,13 @@
#pragma once
namespace tjp {
namespace core {
namespace variant {
template<typename T>
struct ConcreteVariant;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,84 @@
#pragma once
#include "ConcreteVariant.h"
#include "Variant.h"
#include <tjp/core/system/Debug.h>
namespace tjp {
namespace core {
namespace variant {
#ifdef DEBUG
#define DEBUG_CONCRETE_VARIANT
#endif
template<typename T>
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>();
}
T &operator *()
{
return Super::template ref<T>();
}
ConcreteVariant()
{
}
template<typename U>
ConcreteVariant(const U &rhs) :
Super(rhs)
{
execute_debug();
}
template<typename U>
ConcreteVariant &operator =(const U &rhs)
{
Super::template set<>(rhs);
execute_debug();
return *this;
}
auto ptr ()
{
return Super::template ptr<T>();
}
template<typename U>
auto ptr ()
{
return Super::template ptr<U>();
}
auto valid ()
{
return Super::template valid<T>();
}
auto &variant ()
{
return (Super &)*this;
}
} ;
} // namespace
} // namespace
} // namespace

View File

@@ -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;
} ;

View File

@@ -0,0 +1,115 @@
#pragma once
#include "VType.hpp"
#include "VType_of.hpp"
#include <tjp/core/types/Types.h>
#include <tjp/core/assert/debug_assert.h>
#include <tjp/core/ptr/Ptr.hpp>
#include <tjp/core/type_traits/always_false.hpp>
//#include <tjp/core/type_traits/is_mappish.hpp>
#include <vector>
#include <map>
#include <set>
#include <typeindex>
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<typename T>
constexpr
VType vtype_of_custom(const StrongPtr<T> *)
{
return vtype_of<T>();
}
template<typename T>
struct vtype_of_dispatch<StrongPtr<T>> {
static
constexpr
auto dispatch(const StrongPtr<T> *t) {
return vtype_of_custom(t);
}
} ;
template<typename T>
constexpr
VType VType::type_of()
{
return vtype_of<T>();
}
template<typename T>
constexpr
bool vtype_cast(const T &t, const VType &to)
{
return false;
}
template<typename T>
constexpr
bool vtype_cast(const StrongPtr<T> &t, const VType &to)
{
return VType::type_cast<T>(to);
}
template<typename T>
constexpr
bool vtype_cast_dispatch(const T *t, const VType &to)
{
return vtype_cast<T>(*t, to);
}
template<typename T>
constexpr
bool vtype_cast_dispatch(const VType &to)
{
return vtype_cast_dispatch<T>(nullptr, to);
}
template<>
constexpr
bool vtype_cast_dispatch<void>(const VType &to)
{
return false;
}
template<typename T>
constexpr
bool vtype_cast(const VType &to)
{
return vtype_cast_dispatch<T>(to);
}
template<typename T>
constexpr
bool VType::type_cast(const VType &to)
{
return vtype_cast_dispatch<T>(to);
}
} // namespace
} // namespace

View File

@@ -0,0 +1,13 @@
#include "VType+IO.h"
#include <iostream>
namespace tjp {
namespace core {
std::ostream &operator <<(std::ostream &o, const VType &v)
{
return o << v.id;
}
} // namespace
} // namespace

View File

@@ -0,0 +1,18 @@
#pragma once
#include "VType.hpp"
#include <iosfwd>
namespace tjp {
namespace core {
template<typename IO>
void io_(IO &io, VType &v)
{
io.any(v.id);
}
std::ostream &operator <<(std::ostream &o, const VType &v);
} // namespace
} // namespace

View File

@@ -0,0 +1,10 @@
#include "VType.hpp"
namespace tjp {
namespace core {
const VType VType::Null = {0};
} // namespace
} // namespace

48
tjp/core/variant/VType.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include <tjp/core/types/Types.h>
#include <tjp/core/const_hash/Hash.hpp>
#include <tjp/core/string/StringView.hpp>
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<typename T>
struct vtype_of_dispatch;
template<typename T>
constexpr VType vtype_of(const T &);
template<typename T>
constexpr
VType vtype_of();
template<typename T>
constexpr
VType_ID vtype_id();
template<typename T>
constexpr
bool vtype_cast(const T &t, const VType &to);
using Type_ = VType;
} // namespace

View File

@@ -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<typename T>
static
constexpr
VType type_of();
template<typename T>
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"

View File

@@ -0,0 +1,39 @@
#include <tjp/core/debug/Debug.h>
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

View File

@@ -0,0 +1,102 @@
#pragma once
#include "VType.hpp"
#include <tjp/core/rtti/TypeName.hpp>
#include <tjp/core/const_hash/Hash.hpp>
#include <tjp/core/type_traits/always_false.hpp>
#include <utility>
namespace tjp::core {
constexpr
auto vtype_id_class_using(const StringView &v)
{
return hash_compile<VType_ID>(v);
}
constexpr
auto vtype_id_using(const VType_Namespace n, const StringView &t)
{
return vtype_make(n, vtype_id_class_using(t));
}
template<typename T>
constexpr
auto vtype_id_from(const VType_Namespace n, const T *t)
{
return vtype_id_using(n, type_name<T>());
}
template<typename T>
constexpr
VType vtype_from(const VType_Namespace n, const T *t)
{
return { vtype_id_from(n, t) };
}
template<typename T>
constexpr
VType vtype_from(const T *t)
{
return vtype_from(0, t);
}
static_assert(hash_compile<VType_ID>("tjp::core::variant::Variant") == 2549889722U);
// ------------
template<typename T>
constexpr
VType vtype_of_custom(const T *t)
{
return VType { vtype_id_from(0, t) };
}
template<typename T>
struct vtype_of_dispatch {
static
constexpr
auto dispatch(const T *t) {
return vtype_of_custom(t);
}
} ;
template<typename T>
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<T>::dispatch(static_cast<T *>(nullptr));
return result;
}
template<>
constexpr
VType vtype_of<void>()
{
// 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<typename T>
constexpr
VType_ID vtype_id()
{
constexpr auto result = vtype_of<T>().id;
return result;
}
} // namespace

View File

@@ -0,0 +1,22 @@
#pragma once
#include "VType.h"
#include <tjp/core/containers/Vector.h>
namespace tjp {
namespace core {
template<typename T>
struct VVector : Vector<T>
{
using Super = Vector<T>;
VVector() {}
VVector(size_t size) : Super(size) {}
VVector(std::initializer_list<T> l) : Super(l) {}
VVector(Super &&rhs) : Super(std::move(rhs)) {}
VVector(const Super &rhs) : Super(rhs) {}
};
} // namespace
} // namespace

View File

@@ -0,0 +1,28 @@
#pragma once
#include "Variant+IO.hpp"
namespace tjp {
namespace core {
namespace variant {
template<typename D>
bool dispatch_type_builtin(int, D &d);
template<typename T, typename D, typename R>
struct dispatch_variant;
template<typename T, typename D, typename R>
struct dispatch_object;
template<typename T, typename D, typename R>
struct dispatch_array;
template<typename T, typename D, typename R>
struct dispatch_primitive;
} // namespace
} // namespace
} // namespace
#include "Variant+Dispatch.inl"

View File

@@ -0,0 +1,99 @@
#pragma once
#include "VType.hpp"
#include "VariantSerialization.h"
namespace tjp {
namespace core {
namespace variant {
template<typename D>
bool dispatch_type_builtin_value(VType type, D &d)
{
switch(type.id) {
case vtype_id<bool>(): d.template visit<bool>(); return true;
case vtype_id<u8>(): d.template visit<u8>(); return true;
case vtype_id<s8>(): d.template visit<s8>(); return true;
case vtype_id<u16>(): d.template visit<u16>(); return true;
case vtype_id<s16>(): d.template visit<s16>(); return true;
case vtype_id<u32>(): d.template visit<u32>(); return true;
case vtype_id<s32>(): d.template visit<s32>(); return true;
case vtype_id<u64>(): d.template visit<u64>(); return true;
case vtype_id<s64>(): d.template visit<s64>(); return true;
case vtype_id<r32>(): d.template visit<r32>(); return true;
case vtype_id<r64>(): d.template visit<r64>(); return true;
case vtype_id<std::string>(): d.template visit<std::string>(); return true;
case vtype_id<VariantSerialization>(): d.template visit<VariantSerialization>(); return true;
}
return false;
}
template<typename D, typename Type, typename T>
void dispatch_primitive_if(D &d, const Type &type, T &t)
{
d.dispatch_primitive(type, t);
}
template<typename T, typename D, typename R>
struct dispatch_primitive
{
typedef dispatch_primitive<T,D,R> Self;
T &variant;
D &d;
R r;
struct Value
{
Self &self;
template<typename V>
void visit()
{
self.r.template visit<V>(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<typename T, typename D, typename R>
struct dispatch_variant
{
typedef dispatch_variant<T,D,R> 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<T,D,R>(variant, d, std::move(r));
}
} ;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,27 @@
template<typename T>
Functions generateVariantFunctions ();
template<typename T>
Functions generateVariantFunctions ()
{
using Type = Type_;
return Functions {
.construct = variant_construct<T>,
.copy = variant_copy<T>,
.destruct = variant_destruct<T>,
.cast = Type::type_cast<T>
};
}
Functions generateVariantFunctionsVoid ();
template<>
inline
Functions generateVariantFunctions<void> ()
{
return generateVariantFunctionsVoid();
}

View File

@@ -0,0 +1,25 @@
#include "Variant+Functional.hpp"
namespace tjp {
namespace core {
namespace variant {
Variant::Type Variant::voidType = Variant::Type::template type_of<void>();
Functions generateVariantFunctionsVoid ()
{
using Type = Type_;
return Functions {
[](Value &) {},
[](Value &, const Value &) {},
[](Value &) {},
[](const Type &) { return false; }
};
}
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,605 @@
#pragma once
#include "Variant.h"
#include "VType.hpp"
#include "VType+Functional.hpp"
#include "VariantSerialization.h"
#include <tjp/core/types/Types.h>
#include <tjp/core/debug/Debug.h>
#include <tjp/core/assert/debug_assert.h>
#include <tjp/core/exception/Exception.hpp>
#include <tjp/core/ptr/Ptr.hpp>
#include <tjp/core/allocator/SFINAE.hpp>
#include <tjp/core/string/StringView.h>
#include <cstring>
#include <functional>
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<int>)];
} __attribute__ ((aligned (8)));
typedef Value_ Value;
inline
Value emptyValue () {
Value v;
memset(&v, 0, sizeof(v));
return v;
}
template<typename T> struct is_intrinsic : std::false_type {};
template<> struct is_intrinsic<u8> : std::true_type {};
template<> struct is_intrinsic<s8> : std::true_type {};
template<> struct is_intrinsic<char> : std::true_type {};
template<> struct is_intrinsic<u16> : std::true_type {};
template<> struct is_intrinsic<s16> : std::true_type {};
template<> struct is_intrinsic<u32> : std::true_type {};
template<> struct is_intrinsic<s32> : std::true_type {};
template<> struct is_intrinsic<u64> : std::true_type {};
template<> struct is_intrinsic<s64> : std::true_type {};
template<> struct is_intrinsic<r32> : std::true_type {};
template<> struct is_intrinsic<r64> : std::true_type {};
template<typename T> struct is_intrinsic<StrongPtr<T>> : std::true_type {};
template<typename T> struct is_variant : std::false_type {};
template<> struct is_variant<Variant> : std::true_type {};
// ------ SFINAE
template<typename T>
struct variant_type_ptr {
template<typename U, typename std::enable_if<is_intrinsic<U>::value, U>::type* = nullptr>
static T *type_();
template<typename U, typename std::enable_if<!is_intrinsic<U>::value, U>::type* = nullptr>
static StrongPtr<T> type_();
typedef decltype(type_<T>()) type;
} ;
// ------ SFINAE
template<typename T>
using has_variant_allocator = allocators::has_strong_allocator<T>;
// -----
// variant
template<typename T>
T &deref (const Value &value) {
static_assert(sizeof(T) <= sizeof(Value));
auto *vp = &value;
auto *pp = const_cast<T *>(reinterpret_cast<const T *>(vp));
return *pp;
} ;
struct Functions {
using Type = Type_;
std::function<void(Value &)> construct;
std::function<void(Value &, const Value &)> copy;
std::function<void(Value &)> destruct;
std::function<bool(const Type &)> cast;
};
DECLARE_EXCEPTION(CastException);
template<typename T>
void variant_construct(Value &lhs) {
new(&deref<T>(lhs)) T();
}
template<typename T>
void variant_copy(Value &lhs, const Value &rhs) {
deref<T>(lhs) = deref<T>(rhs);
}
template<typename T>
void variant_destruct(Value &lhs) {
deref<T>(lhs).~T();
};
#include "Variant+Functional+Generate.hpp"
//#include "Variant+VariantFunctionalUsingSingleFunctionsObject.hpp"
#include "Variant+VariantFunctionalUsingSingleFunctionsObjectPointer.hpp"
struct DefaultAllocator
{
template<typename T, typename ... Args>
auto strong(Args && ...args)
{
return core::strong<T>(std::forward<Args>(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<typename U>
Variant(const Variant &rhs, U &allocator)
{
set(rhs, allocator);
}
template<
typename T,
typename std::enable_if<!is_variant<T>::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<!is_variant<T>::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<void>();
}
template<typename T>
bool valid () const
{
return is_<T>() && (bool)ptr<T>();
}
void clear ()
{
inferTypeName<void>();
if (type == voidType)
return;
auto &f0 = functional.functionsFor(type);
f0.destruct(value);
type = voidType;
auto &f1 = functional.ensureFunctions<void>();
f1.construct(value);
}
template<typename T>
T &ensure_()
{
inferTypeName<T>();
if (!(type == Type::template type_of<void>()))
{
if (!is_<T>())
{
debug_assert(false);
throw CastException{};
}
return deref<T>(value);
}
type = Type::template type_of<T>();
auto &functions = functional.template ensureFunctions<T>();
functions.construct(value);
return deref<T>(value);
}
template<typename T, typename P>
T &ensure_()
{
auto &r = ensure_<T>();
inferTypeName<P>();
return r;
}
template<typename T>
bool is_() const
{
auto otherType = Type::template type_of<T>();
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<VariantSerialization>();
}
template<typename T>
T &ref_() const
{
if (!is_<T>())
{
throw CastException{};
}
return deref<T>(value);
}
#ifdef CORE_VARIANT_INCLUDES_DEBUG_TYPE
// debug
mutable StringView typeName;
template<typename T>
void inferTypeName()
{
typeName = type_unique_label_stringview<T>();
}
template<typename T>
void copyTypeName(const T &rhs)
{
typeName = rhs.typeName;
}
StringView getTypeName() {
return typeName;
}
#else
template<typename T>
void inferTypeName () {}
template<typename T>
void copyTypeName(const T &rhs) {}
StringView getTypeName() {
return {};
}
#endif
// copy
template<
typename T,
typename std::enable_if<is_variant<T>::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<is_variant<T>::value, T>::type* = nullptr
>
void set(const T &rhs, U &)
{
set(rhs);
}
// intrinsic
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T *ptr()
{
if (!is_<T>())
return nullptr;
return &ref<T>();
}
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T *ptr() const
{
if (!is_<T>())
return nullptr;
return &ref<T>();
}
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
void set(const T &rhs)
{
ensure_<T>() = rhs;
}
template<
typename T,
typename U,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
void set(const T &rhs, U &allocator)
{
ensure_<T>() = rhs;
}
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T &ref()
{
return ref_<T>();
}
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T &ref() const
{
return ref_<T>();
}
template<
typename T,
typename U,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T &load(U &)
{
return ensure_<T>();
}
template<
typename T,
typename std::enable_if<is_intrinsic<T>::value, T>::type* = nullptr
>
T &load()
{
return load<T>(defaultAllocator);
}
// pointer
template<typename TP, typename std::enable_if<std::is_pointer<TP>::value, TP>::type* = nullptr>
void set(const TP rhs)
{
typedef typename std::remove_pointer<TP>::type T;
typedef StrongPtr<T> P;
ensure_<P, T>() = rhs;
}
// complex
template<
typename T,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
StrongPtr<T> ptr()
{
typedef StrongPtr<T> T_;
if (!is_<T_>())
return StrongPtr<T>();
return deref<T_>(value);
}
template<
typename T,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
const StrongPtr<T> ptr() const
{
typedef StrongPtr<T> T_;
if (!is_<T_>())
return StrongPtr<T>();
return deref<T_>(value);
}
template<
typename T,
typename U,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
void set(const T &rhs, U &allocator)
{
typedef StrongPtr<T> T_;
auto &p = ensure_<T_, T>();
if (!p)
p = allocator.template strong<T>(rhs);
else
*p = rhs;
}
template<
typename T,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
void set(const T &rhs)
{
set(rhs, defaultAllocator);
}
template<
typename T,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
T &ref()
{
typedef StrongPtr<T> T_;
return *ref_<T_>();
}
template<
typename T,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
T &ref() const
{
typedef StrongPtr<T> T_;
return *ref_<T_>();
}
template <
typename T,
typename U,
typename std::enable_if<!std::is_void<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
T &load(U &allocator)
{
typedef StrongPtr<T> T_;
auto &ptr = ensure_<T_, T>();
if (ptr == nullptr)
ptr = allocator.template strong<T>();
return *ptr;
}
template<
typename T,
typename std::enable_if<!std::is_void<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_variant<T>::value, T>::type* = nullptr,
typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr,
typename std::enable_if<!is_intrinsic<T>::value, T>::type* = nullptr
>
T &load()
{
return load<T>(defaultAllocator);
}
template <
typename T,
typename U,
typename std::enable_if<std::is_void<T>::value, T>::type* = nullptr
>
void load(U &allocator)
{
clear();
}
template<
typename T,
typename std::enable_if<std::is_void<T>::value, T>::type* = nullptr
>
void load()
{
return load<T>(defaultAllocator);
}
// -- operator =
template<typename T>
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

View File

@@ -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 <tjp/core/algorithm/remove_const_of_var.hpp>
namespace tjp {
namespace core {
namespace variant {
template<typename IO, typename T>
struct io_bin_variant {
IO &io;
template<typename V>
void visit(T &t)
{
auto &v = t.template as<V>(io);
io.any(v);
}
void visit_void(T &v) {}
} ;
template<typename IO>
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<typename IO>
void deserialize_(IO &io, Variant &variant, const StrongPtr<VariantSerialization> &serialization)
{
auto io_ = io.partial(serialization->block);
variant = Variant();
io_->any(variant);
}
template<typename IO>
bool io_variant_deserialization_available(IO &io, Type_ type)
{
return io.variant_deserialization_available(type);
}
template<typename IO>
void deserialize_io(IO &io, Variant &variant)
{
using Type = Type_;
if (variant.type == Type::template type_of<VariantSerialization>())
{
auto serialization = variant.template ptr<VariantSerialization>();
if (io_variant_deserialization_available(io, serialization->type))
{
deserialize_(io, variant, serialization);
}
}
}
// ----------------------
template<typename IO>
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<typename IO, typename T>
bool io_use_variant_serialization_for(IO &io, const T &t)
{
return io.use_variant_serialization_for(t);
}
template<typename IO>
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&>(v));
}
template<typename IO>
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<typename IO>
void io_bin(IO &io, Variant &v) { return io_(io, v); }
template<typename IO>
void io_json(IO &io, Variant &v) { return io_(io, v); }
#endif
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
} // namespace
} // namespace
} // namespace

View File

@@ -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<typename Type_>
struct VariantFunctionalUsingMap
{
typedef Type_ Type;
struct FunctionsMap {
SharedMutex mutex;
std::map<Type, Functions<Type>> values;
} ;
static FunctionsMap *functionsMap_;
static std::once_flag initializeFunctionMapFlag;
static void initializeFunctionMap ()
{
functionsMap_ = new FunctionsMap();
(*functionsMap_).values[Type::template type_of<void>()] =
generateVariantFunctionsVoid<Type>();
}
static FunctionsMap &functionsMap ()
{
std::call_once(initializeFunctionMapFlag, initializeFunctionMap);
return *functionsMap_;
}
template<typename T>
static Functions<Type> &ensureFunctions()
{
Type type = Type::template type_of<T>();
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<Type, T>();
auto emplaced = functions.values.insert({type, variantFunctions});
i = emplaced.first;
}
return i->second;
}
static const Functions<Type> &ensureFunctions(Type type_, const Functions<Type> &functions_)
{
return functions_;
}
static Functions<Type> &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 Type_>
typename VariantFunctionalUsingMap<Type_>::FunctionsMap *VariantFunctionalUsingMap<Type_>::functionsMap_ = nullptr;
template<typename Type_>
std::once_flag VariantFunctionalUsingMap<Type_>::initializeFunctionMapFlag;

View File

@@ -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<typename Type_>
struct VariantFunctionalUsingMapAndVectorCache
{
typedef Type_ Type;
struct CacheItem {
bool cached = false;
Functions<Type> functions;
void set(Functions<Type> &&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<Type, Functions<Type>> values;
} ;
static FunctionsMap *functionsMap_;
static std::once_flag initializeFunctionMapFlag;
static void initializeFunctionMap ()
{
functionsMap_ = new FunctionsMap();
auto type = Type::template type_of<void>();
auto cacheIndex = type.id;
debug_assert(cacheIndex < functionsMap_->maxCache);
auto &item = functionsMap_->cache[cacheIndex];
item.set(generateVariantFunctionsVoid<Type>());
}
static FunctionsMap &functionsMap ()
{
std::call_once(initializeFunctionMapFlag, initializeFunctionMap);
return *functionsMap_;
}
template<typename T>
static Functions<Type> &ensureFunctions()
{
auto &functions = functionsMap();
Type type = Type::template type_of<T>();
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<Type, T>());
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<Type, T>();
auto emplaced = functions.values.insert({type, variantFunctions});
i = emplaced.first;
}
return i->second;
}
static const Functions<Type> &ensureFunctions(Type type_, const Functions<Type> &functions_)
{
return functions_;
}
static Functions<Type> &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 Type_>
typename VariantFunctionalUsingMapAndVectorCache<Type_>::FunctionsMap *VariantFunctionalUsingMapAndVectorCache<Type_>::functionsMap_ = nullptr;
template<typename Type_>
std::once_flag VariantFunctionalUsingMapAndVectorCache<Type_>::initializeFunctionMapFlag;

View File

@@ -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<void>();
Functions functions = generateVariantFunctions<void>();
template<typename T>
const Functions &ensureFunctions()
{
type = Type::template type_of<T>();
functions = generateVariantFunctions<T>();
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;

View File

@@ -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<typename T>
struct SingleFunctionsObject {
static const Functions functions_;
static const Functions *functions() {
return &functions_;
}
} ;
template<typename T>
const Functions SingleFunctionsObject<T>::functions_ = generateVariantFunctions<T>();
#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<void>();
#endif
const Functions *functions = SingleFunctionsObject<void>::functions();
void setType(Type type_)
{
#ifdef VARIANT_FUNCTIONS_INCLUDE_TYPE
type = type_;
#endif
}
template<typename T>
const Functions &ensureFunctions()
{
setType(Type::template type_of<T>());
functions = SingleFunctionsObject<T>::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;

View File

@@ -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<typename T>
Functions generateVariantFunctions ();
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Variant+Functional.hpp"
namespace tjp {
namespace core {
namespace variant {
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Variant.h"
namespace tjp {
namespace core {
namespace variant {
struct VariantIO;
} // namespace
} // namespace
} // namespace

View File

@@ -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<has_variant_allocator<IO>::value, IO>::type* = nullptr
>
auto &as(IO &io)
{
return variant.load<T>(io.allocator);
}
template<
typename T,
typename IO,
typename std::enable_if<!has_variant_allocator<IO>::value, IO>::type* = nullptr
>
auto &as(IO &io)
{
return variant.load<T>();
}
} ;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,24 @@
#pragma once
namespace tjp {
namespace core {
namespace variant {
// -------------------------------------
template<typename IO>
void io_(IO &io, VariantSerialization &v)
{
io.object("type", v.type, "block", v.block);
}
template<typename IO>
void io_json(IO &io, VariantSerialization &v) { return io_(io, v); }
template<typename IO>
void io_bin(IO &io, VariantSerialization &v) { return io_(io, v); }
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,14 @@
#pragma once
#include "VType.hpp"
namespace tjp {
namespace core {
namespace variant {
struct VariantSerialization;
} // namespace
} // namespace
} // namespace

View File

@@ -0,0 +1,36 @@
#pragma once
#include "VariantIO.hpp"
namespace tjp {
namespace core {
namespace variant {
struct VariantSerialization
{
typedef std::vector<char> Block;
Type_ type;
Block block;
VariantSerialization() {}
template<typename IO>
VariantSerialization(const Variant &v, IO &io)
{
auto &v_ = const_cast<Variant &>(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

View File

@@ -0,0 +1,132 @@
// TJP COPYRIGHT HEADER
#include <tjp/core/variant/VType.hpp>
#include <tjp/core/variant/VType_of.hpp>
#include <tjp/core/variant/VType+IO.h>
#include <tjp/core/variant/VType+Functional.hpp>
#include <tjp/core/log/Log.h>
#include <tjp/core/log/LogOf.h>
#include <iostream>
#include <tjp/core/testing/catch.hpp>
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<abcdefgh>()));
constexpr auto x = vtype_of<abcdefgh>();
sLogTest("testing",
logVar(x));
sLogTest("testing",
logVar(vtype_of<abcdefgh>()));
}
}
SCENARIO("core::variant::VType_of")
{
GIVEN("compile vs runtime")
{
using A = VType;
sLogTest("testing",
logVar(type_name<VType>()) <<
logVar(type_name<A>()) <<
logVar(type_name<VType_ID>()) <<
logVar(type_name<std::iostream>()) <<
logVar(type_name<std::numeric_limits<int>>())
);
sLogTest("testing",
logVar(rtti::impl::format.leading_junk) <<
logVar(rtti::impl::format.trailing_junk)
);
sLogTest("testing",
"\n" << rtti::impl::RawTypeName<int>() <<
"\n" << type_name<int>() <<
"\n" << rtti::impl::RawTypeName<VType>() <<
"\n" << type_name<VType>() <<
"\n" << rtti::impl::RawTypeName<A>() <<
"\n" << type_name<A>() <<
"\n" << rtti::impl::RawTypeName<VType_ID>() <<
"\n" << type_name<VType_ID>() <<
"\n" << rtti::impl::RawTypeName<std::iostream>() <<
"\n" << type_name<std::iostream>() <<
"\n" << rtti::impl::RawTypeName<std::numeric_limits<int>>() <<
"\n" << type_name<std::numeric_limits<int>>()
);
sLogTest("testing",
logVar(hash_compile<u64>(type_name<VType>())) <<
logVar(hash_compile<u64>(type_name<VType_ID>())) <<
logVar(hash_runtime<u64>(type_name<VType>())) <<
logVar(hash_runtime<u64>(type_name<VType_ID>()))
);
constexpr VType v0 = vtype_of<VType>();
constexpr VType v1 = vtype_of<VType_ID>();
constexpr VType xt = vtype_of<X1>();
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<X1>();
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<variant_testing::X1>();
constexpr VType xt_ = vtype_from("X");
REQUIRE(xt == xt_);
constexpr VType xtv = VType::type_of<variant_testing::X1>();
REQUIRE(xt == xtv);
}
}
} // namespace
} // namespace

View File

@@ -0,0 +1,379 @@
// TJP COPYRIGHT HEADER
#include <tjp/core/string/String.h>
#include <tjp/core/variant/Variant.hpp>
#include <tjp/core/variant/Variant+IO.hpp>
#include <tjp/core/variant/VType+IO.h>
#include <tjp/core/variant/Variant+Dispatch.h>
#include <tjp/core/io/bin/IO.h>
#include <tjp/core/ptr/Ptr+IO.h>
#include <tjp/core/testing/catch.hpp>
#include <tjp/core/algorithm/unused.hpp>
#include <tjp/core/log/Log.h>
#include <tjp/core/log/LogOf.h>
// -------------------------------------------------------------------------------
// 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<std::string,Variant> CustomMapType;
constexpr
VType vtype_of_custom(const CustomMapType *) { return VType::make(30, 13); }
} // namespace
// -------------------------------------------------------------------------------
namespace tjp::core::variant::test_compile {
typedef std::map<std::string,Variant> 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<typename IO>
void io_bin(IO &io, Custom &a)
{
io.all(a.i);
}
template<typename IO>
void io_bin(IO &io, External &a)
{
io.all(a.x);
}
struct DispatchVariant
{
template<typename IO>
void dispatch_custom(IO &io, VariantIO &v)
{
core::variant::dispatch_variant(
v,
*this,
io_bin_variant<IO, VariantIO> { io }
);
}
template<typename D>
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<CustomMapType>();
}
} break;
case 64:
{
switch (type.getClass())
{
case 23: return d.template visit<Custom>();
}
}
}
debug_assert(false);
}
template<typename V>
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<typename IO>
void dispatch_custom(IO &io, VariantIO &v)
{
core::variant::dispatch_variant(
v,
*this,
io_bin_variant<IO, VariantIO> { io }
);
}
template<typename D>
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<CustomMapType>();
}
} break;
case 64:
{
switch (type.getClass())
{
case 23: return d.template visit<Custom>();
}
}
case 65:
{
switch (type.getClass())
{
case 33: return d.template visit<External>();
}
}
}
debug_assert(false);
}
template<typename V>
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<typename T>
void allocate(T &t)
{
io_ptr_allocate_default(*this, t);
}
template<typename T, typename ... Args>
auto strong(Args && ...args)
{
return core::strong<T>(std::forward<Args>(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<External>();
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<decltype(c)>().x == c.x);
}
WHEN("the variant with unknown is serialized from external -> internal -> internal -> external")
{
typedef io::bin::Writer<io::bin::memory_out, DispatchVariant> WriterInternal;
typedef io::bin::Reader<io::bin::memory_in, DispatchVariant> ReaderInternal;
typedef io::bin::Writer<io::bin::memory_out, DispatchVariantHandleExternal> WriterExternal;
typedef io::bin::Reader<io::bin::memory_in, DispatchVariantHandleExternal> ReaderExternal;
WriterExternal wE;
auto s1 = io::bin::serializeTo(wE, v);
ReaderInternal rI({ s1.data(), s1.size() });
auto v2 = io::bin::deserializeFrom<Variant>(rI);
WriterInternal wI;
auto s2 = io::bin::serializeTo(wI, v2);
ReaderExternal rE({ s2.data(), s2.size() });
auto v_ = io::bin::deserializeFrom<Variant>(rE);
THEN("unknown survives")
{
REQUIRE(v.ref<decltype(c)>().x == c.x);
}
}
}
WHEN("variant is set to a number")
{
auto c = 5;
v = c;
THEN("number is set")
{
REQUIRE(v.ref<decltype(c)>() == c);
}
}
WHEN("variant is set to a string")
{
auto c = std::string("hello");
v = c;
THEN("value is set")
{
REQUIRE(v.ref<decltype(c)>() == 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<decltype(c)>()["hi"].ref<decltype(onePZero)>();
auto r = c["hi"].ref<decltype(onePZero)>();
REQUIRE(l == r);
}
THEN("there value is set")
{
auto l = v.ref<decltype(c)>()["there"].ref<decltype(threeP5)>();
auto r = c["there"].ref<decltype(threeP5)>();
REQUIRE(l == r);
}
THEN("the value is serialized and deserialized")
{
typedef io::bin::Writer<io::bin::memory_out, DispatchVariant> Writer;
typedef io::bin::Reader<io::bin::memory_in, DispatchVariant> Reader;
io::bin::Serialization s1;
Writer w1;
s1 = io::bin::serializeTo(w1, v);
Reader reader({ s1.data(), s1.size() });
auto v2 = io::bin::deserializeFrom<Variant>(reader);
auto &m = v2.ref<CustomMapType>();
REQUIRE(m["hi"].ref<decltype(onePZero)>() == onePZero);
REQUIRE(m["there"].ref<decltype(threeP5)>() == threeP5);
REQUIRE(m["recursive"].ref<CustomMapType>()["a"].ref<decltype(onePZero)>() == onePZero);
}
THEN("the value is serialized deserialized and serialized again")
{
typedef io::bin::Writer<io::bin::memory_out, DispatchVariant> Writer;
typedef io::bin::Reader<io::bin::memory_in, DispatchVariant> 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<Variant>(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<io::bin::memory_out, DispatchVariant, PoolAllocatorTest> Writer;
typedef io::bin::Reader<io::bin::memory_in, DispatchVariant, PoolAllocatorTest> Reader;
io::bin::Serialization s1, s2;
static_assert(allocators::has_allocator<Reader>::value);
static_assert(has_variant_allocator<Reader>::value);
static_assert(allocators::has_strong_allocator_flag<Reader::Allocator>::value);
{
Writer w1;
s1 = io::bin::serializeTo(w1, v);
Reader reader({ s1.data(), s1.size() });
auto v2 = io::bin::deserializeFrom<Variant>(reader);
Writer w2;
s2 = io::bin::serializeTo(w2, v2);
}
REQUIRE(s1 == s2);
}
}
}
}
} // namespace