From 525b273a84295f0a38cc38176a6131f26558cbc2 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 11:38:45 +0300 Subject: [PATCH 01/13] added stuff --- .../omath/containers/encrypted_variable.hpp | 176 ++++++++++++++++++ tests/CMakeLists.txt | 2 +- tests/general/unit_test_var_encryption.cpp | 20 ++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 include/omath/containers/encrypted_variable.hpp create mode 100644 tests/general/unit_test_var_encryption.cpp diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp new file mode 100644 index 00000000..6388fcb7 --- /dev/null +++ b/include/omath/containers/encrypted_variable.hpp @@ -0,0 +1,176 @@ +// +// Created by Vladislav on 04.01.2026. +// +#pragma once +#include +#include +#include +#include + +#ifdef _MSC_VER +#define OMATH_FORCEINLINE __forceinline +#else +#define OMATH_FORCEINLINE __attribute__((always_inline)) inline +#endif + +namespace omath +{ + template + class Anchor; + + consteval std::uint64_t fnv1a_64(const char* s) + { + std::uint64_t h = 14695981039346656037ull; + while (*s) + { + h ^= static_cast(*s++); + h *= 1099511628211ull; + } + return h; + } + + // SplitMix64 mixer (good quality for seeding / scrambling) + consteval std::uint64_t splitmix64(std::uint64_t x) + { + x += 0x9E3779B97F4A7C15ull; + x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ull; + x = (x ^ (x >> 27)) * 0x94D049BB133111EBull; + return x ^ (x >> 31); + } + + // Choose your policy: + // - If you want reproducible builds, REMOVE __DATE__/__TIME__. + // - If you want "different each build", keep them. + consteval std::uint64_t base_seed() + { + std::uint64_t h = 0; + h ^= fnv1a_64(__FILE__); + h ^= splitmix64(fnv1a_64(__DATE__)); + h ^= splitmix64(fnv1a_64(__TIME__)); + return splitmix64(h); + } + + // Produce a "random" 64-bit value for a given stream index (compile-time) + template + consteval std::uint64_t rand_u64() + { + // Stream is usually __COUNTER__ so each call site differs + return splitmix64(base_seed() + 0xD1B54A32D192ED03ull * (Stream + 1)); + } + + // Unbiased bounded uniform using Lemire's method (uses 128-bit multiply) + consteval std::uint64_t bounded_u64(std::uint64_t x, std::uint64_t bound) + { + // bound must be > 0 + __uint128_t m = static_cast<__uint128_t>(x) * static_cast<__uint128_t>(bound); + return static_cast(m >> 64); + } + + template + consteval std::int64_t rand_uint8t() + { + static_assert(Lo <= Hi); + const std::uint64_t span = static_cast(Hi - Lo) + 1ull; + const std::uint64_t r = rand_u64(); + return static_cast(bounded_u64(r, span)) + Lo; + } + consteval std::uint64_t rand_u64(std::uint64_t seed, std::uint64_t i) + { + return splitmix64(seed + 0xD1B54A32D192ED03ull * (i + 1ull)); + } + + // Convert to int (uses low 32 bits; you can also use high bits if you prefer) + consteval std::uint8_t rand_uint8t(std::uint64_t seed, std::uint64_t i) + { + return static_cast(rand_u64(seed, i)); // narrowing is fine/deterministic + } + + constexpr std::array create_key() + { + std::array key{}; + + for (auto& byte : key) + { + byte = static_cast(rand_u64<__COUNTER__>()); + } + return key; + } + template + consteval std::array make_array_impl(std::index_sequence) + { + return {rand_uint8t(Seed, static_cast(I))...}; + } + + template + consteval std::array make_array() + { + return make_array_impl(std::make_index_sequence{}); + } + template key> + class EncryptedVariable final + { + bool m_is_encrypted{}; + T m_data; + + public: + OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(true), m_data(data) + { + encrypt(); + } + [[nodiscard]] constexpr bool is_encrypted() const + { + return m_is_encrypted; + } + OMATH_FORCEINLINE constexpr void decrypt() + { + std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + + for (auto& byte : bytes) + for (const auto key_byte : key) + byte ^= key_byte; + m_is_encrypted = false; + } + OMATH_FORCEINLINE constexpr void encrypt() + { + std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + + for (auto& byte : bytes) + for (const auto key_byte : key) + byte ^= key_byte; + m_is_encrypted = true; + } + OMATH_FORCEINLINE constexpr T& value() + { + return m_data; + } + OMATH_FORCEINLINE constexpr const T& value() const + { + return m_data; + } + OMATH_FORCEINLINE ~EncryptedVariable() + { + decrypt(); + } + }; + template + class Anchor + { + public: + OMATH_FORCEINLINE constexpr Anchor(EncryptedVarType& var): m_var(var) + { + m_var.decrypt(); + } + OMATH_FORCEINLINE constexpr ~Anchor() + { + m_var.encrypt(); + } + + private: + EncryptedVarType& m_var; + }; +} // namespace omath + + +#define CT_RAND_ARRAY_INT(N) \ +(::omath::make_array<(N), (::omath::base_seed() ^ static_cast(__COUNTER__))>()) +#define OMATH_DEF_CRYPT_VAR(TYPE, KEY_SIZE) omath::EncryptedVariable \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 76ef3a7e..9f82b6e5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,7 +20,7 @@ else() # GTest is being linked as vcpkg package find_package(GTest CONFIG REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath) endif() - +target_compile_options(${PROJECT_NAME} PRIVATE -static) if(OMATH_ENABLE_COVERAGE) include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake) omath_setup_coverage(${PROJECT_NAME}) diff --git a/tests/general/unit_test_var_encryption.cpp b/tests/general/unit_test_var_encryption.cpp new file mode 100644 index 00000000..07afe2ad --- /dev/null +++ b/tests/general/unit_test_var_encryption.cpp @@ -0,0 +1,20 @@ +// +// Created by Vladislav on 04.01.2026. +// +#include "omath/linear_algebra/vector3.hpp" +#include +#include +TEST(Enc, Test) +{ + OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var{{1.f, 2.f, 3.f}}; + OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var2{{1.f, 2.f, 3.f}}; + { + omath::Anchor _ = {var}; + omath::Anchor __ = {var2}; + + std::println("Decrypted var1: {}", var.value()); + std::println("Decrypted var2: {}", var2.value()); + } + std::println("Encrypted var1: {}", var.value()); + std::println("Encrypted var2: {}", var2.value()); +} \ No newline at end of file From be1049db936e1e328f61f380657235b55570338f Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 11:50:32 +0300 Subject: [PATCH 02/13] changed algorithm --- include/omath/containers/encrypted_variable.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 6388fcb7..dbd7fcf9 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -125,18 +125,16 @@ namespace omath { std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; - for (auto& byte : bytes) - for (const auto key_byte : key) - byte ^= key_byte; + for (size_t i = 0; i < bytes.size(); ++i) + bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); m_is_encrypted = false; } - OMATH_FORCEINLINE constexpr void encrypt() + OMATH_FORCEINLINE constexpr void encrypt() { std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; - for (auto& byte : bytes) - for (const auto key_byte : key) - byte ^= key_byte; + for (size_t i = 0; i < bytes.size(); ++i) + bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); m_is_encrypted = true; } OMATH_FORCEINLINE constexpr T& value() @@ -170,7 +168,6 @@ namespace omath }; } // namespace omath - -#define CT_RAND_ARRAY_INT(N) \ -(::omath::make_array<(N), (::omath::base_seed() ^ static_cast(__COUNTER__))>()) +#define CT_RAND_ARRAY_INT(N) \ + (::omath::make_array<(N), (::omath::base_seed() ^ static_cast(__COUNTER__))>()) #define OMATH_DEF_CRYPT_VAR(TYPE, KEY_SIZE) omath::EncryptedVariable \ No newline at end of file From 9a3f5abb7c95e7dca1658d2e2d6796e0742f8fe2 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 11:56:15 +0300 Subject: [PATCH 03/13] added check --- include/omath/containers/encrypted_variable.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index dbd7fcf9..5956a533 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -123,6 +123,8 @@ namespace omath } OMATH_FORCEINLINE constexpr void decrypt() { + if (m_is_encrypted) + return; std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; for (size_t i = 0; i < bytes.size(); ++i) @@ -131,6 +133,8 @@ namespace omath } OMATH_FORCEINLINE constexpr void encrypt() { + if (!m_is_encrypted) + return; std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; for (size_t i = 0; i < bytes.size(); ++i) From 2b75b33d602829fe7cf15776b166f78d06f56625 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 12:01:24 +0300 Subject: [PATCH 04/13] fix --- include/omath/containers/encrypted_variable.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 5956a533..08cca91a 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -109,11 +109,11 @@ namespace omath template key> class EncryptedVariable final { - bool m_is_encrypted{}; + bool m_is_encrypted; T m_data; public: - OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(true), m_data(data) + OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) { encrypt(); } @@ -123,7 +123,7 @@ namespace omath } OMATH_FORCEINLINE constexpr void decrypt() { - if (m_is_encrypted) + if (!m_is_encrypted) return; std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; @@ -133,7 +133,7 @@ namespace omath } OMATH_FORCEINLINE constexpr void encrypt() { - if (!m_is_encrypted) + if (m_is_encrypted) return; std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; From aabdebbbbeb158de76d54c78b17c7f5ba78ca1ba Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:14:54 +0300 Subject: [PATCH 05/13] improved stuff --- .../omath/containers/encrypted_variable.hpp | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 08cca91a..2d9809af 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -13,11 +13,8 @@ #define OMATH_FORCEINLINE __attribute__((always_inline)) inline #endif -namespace omath +namespace omath::detail { - template - class Anchor; - consteval std::uint64_t fnv1a_64(const char* s) { std::uint64_t h = 14695981039346656037ull; @@ -84,17 +81,6 @@ namespace omath { return static_cast(rand_u64(seed, i)); // narrowing is fine/deterministic } - - constexpr std::array create_key() - { - std::array key{}; - - for (auto& byte : key) - { - byte = static_cast(rand_u64<__COUNTER__>()); - } - return key; - } template consteval std::array make_array_impl(std::index_sequence) { @@ -106,6 +92,12 @@ namespace omath { return make_array_impl(std::make_index_sequence{}); } +} // namespace omath::detail + +namespace omath +{ + template + class Anchor; template key> class EncryptedVariable final { @@ -141,10 +133,12 @@ namespace omath bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); m_is_encrypted = true; } + [[nodiscard]] OMATH_FORCEINLINE constexpr T& value() { return m_data; } + [[nodiscard]] OMATH_FORCEINLINE constexpr const T& value() const { return m_data; @@ -172,6 +166,6 @@ namespace omath }; } // namespace omath -#define CT_RAND_ARRAY_INT(N) \ - (::omath::make_array<(N), (::omath::base_seed() ^ static_cast(__COUNTER__))>()) -#define OMATH_DEF_CRYPT_VAR(TYPE, KEY_SIZE) omath::EncryptedVariable \ No newline at end of file +#define OMATH_CT_RAND_ARRAY_BYTE(N) \ + (::omath::detail::make_array<(N), (::omath::detail::base_seed() ^ static_cast(__COUNTER__))>()) +#define OMATH_DEF_CRYPT_VAR(TYPE, KEY_SIZE) omath::EncryptedVariable \ No newline at end of file From d56d05f01e176c6f0e82c1ed39e0cb90f03c3f27 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:16:32 +0300 Subject: [PATCH 06/13] silenced warn --- include/omath/containers/encrypted_variable.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 2d9809af..d077e51c 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -152,7 +152,8 @@ namespace omath class Anchor { public: - OMATH_FORCEINLINE constexpr Anchor(EncryptedVarType& var): m_var(var) + // ReSharper disable once CppNonExplicitConvertingConstructor + OMATH_FORCEINLINE constexpr Anchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) { m_var.decrypt(); } From 8812abdf3332e01ea906382c8c241d7075cb25f4 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:23:57 +0300 Subject: [PATCH 07/13] fixed test --- include/omath/containers/encrypted_variable.hpp | 13 +++++++++---- tests/general/unit_test_var_encryption.cpp | 13 +++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index d077e51c..dbf8f728 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -97,7 +97,7 @@ namespace omath::detail namespace omath { template - class Anchor; + class VarAnchor; template key> class EncryptedVariable final { @@ -147,17 +147,22 @@ namespace omath { decrypt(); } + [[nodiscard]] + OMATH_FORCEINLINE auto drop_anchor() + { + return VarAnchor{*this}; + } }; template - class Anchor + class VarAnchor { public: // ReSharper disable once CppNonExplicitConvertingConstructor - OMATH_FORCEINLINE constexpr Anchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) + OMATH_FORCEINLINE constexpr VarAnchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) { m_var.decrypt(); } - OMATH_FORCEINLINE constexpr ~Anchor() + OMATH_FORCEINLINE constexpr ~VarAnchor() { m_var.encrypt(); } diff --git a/tests/general/unit_test_var_encryption.cpp b/tests/general/unit_test_var_encryption.cpp index 07afe2ad..108e84b4 100644 --- a/tests/general/unit_test_var_encryption.cpp +++ b/tests/general/unit_test_var_encryption.cpp @@ -6,15 +6,12 @@ #include TEST(Enc, Test) { - OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var{{1.f, 2.f, 3.f}}; - OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var2{{1.f, 2.f, 3.f}}; + constexpr omath::Vector3 original = {1.f, 2.f, 3.f}; + OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var{original}; { - omath::Anchor _ = {var}; - omath::Anchor __ = {var2}; + omath::VarAnchor _ = var.drop_anchor(); - std::println("Decrypted var1: {}", var.value()); - std::println("Decrypted var2: {}", var2.value()); + EXPECT_EQ(original, var.value()); } - std::println("Encrypted var1: {}", var.value()); - std::println("Encrypted var2: {}", var2.value()); + EXPECT_NE(original, var.value()); } \ No newline at end of file From 0846022f8a62095c3a0234a900f001dfebd9b4ba Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:41:28 +0300 Subject: [PATCH 08/13] improvement --- .../omath/containers/encrypted_variable.hpp | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index dbf8f728..711a80d9 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -15,6 +15,7 @@ namespace omath::detail { + [[nodiscard]] consteval std::uint64_t fnv1a_64(const char* s) { std::uint64_t h = 14695981039346656037ull; @@ -27,6 +28,7 @@ namespace omath::detail } // SplitMix64 mixer (good quality for seeding / scrambling) + [[nodiscard]] consteval std::uint64_t splitmix64(std::uint64_t x) { x += 0x9E3779B97F4A7C15ull; @@ -38,6 +40,7 @@ namespace omath::detail // Choose your policy: // - If you want reproducible builds, REMOVE __DATE__/__TIME__. // - If you want "different each build", keep them. + [[nodiscard]] consteval std::uint64_t base_seed() { std::uint64_t h = 0; @@ -49,6 +52,7 @@ namespace omath::detail // Produce a "random" 64-bit value for a given stream index (compile-time) template + [[nodiscard]] consteval std::uint64_t rand_u64() { // Stream is usually __COUNTER__ so each call site differs @@ -56,7 +60,8 @@ namespace omath::detail } // Unbiased bounded uniform using Lemire's method (uses 128-bit multiply) - consteval std::uint64_t bounded_u64(std::uint64_t x, std::uint64_t bound) + [[nodiscard]] + consteval std::uint64_t bounded_u64(const std::uint64_t x, const std::uint64_t bound) { // bound must be > 0 __uint128_t m = static_cast<__uint128_t>(x) * static_cast<__uint128_t>(bound); @@ -64,30 +69,35 @@ namespace omath::detail } template - consteval std::int64_t rand_uint8t() + [[nodiscard]] + consteval std::int64_t rand_uint8_t() { static_assert(Lo <= Hi); const std::uint64_t span = static_cast(Hi - Lo) + 1ull; const std::uint64_t r = rand_u64(); return static_cast(bounded_u64(r, span)) + Lo; } - consteval std::uint64_t rand_u64(std::uint64_t seed, std::uint64_t i) + [[nodiscard]] + consteval std::uint64_t rand_u64(const std::uint64_t seed, const std::uint64_t i) { return splitmix64(seed + 0xD1B54A32D192ED03ull * (i + 1ull)); } // Convert to int (uses low 32 bits; you can also use high bits if you prefer) - consteval std::uint8_t rand_uint8t(std::uint64_t seed, std::uint64_t i) + [[nodiscard]] + consteval std::uint8_t rand_uint8t(const std::uint64_t seed, const std::uint64_t i) { return static_cast(rand_u64(seed, i)); // narrowing is fine/deterministic } template + [[nodiscard]] consteval std::array make_array_impl(std::index_sequence) { return {rand_uint8t(Seed, static_cast(I))...}; } template + [[nodiscard]] consteval std::array make_array() { return make_array_impl(std::make_index_sequence{}); @@ -104,6 +114,14 @@ namespace omath bool m_is_encrypted; T m_data; + OMATH_FORCEINLINE constexpr void xor_contained_var_by_key() + { + std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + + for (size_t i = 0; i < bytes.size(); ++i) + bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); + m_is_encrypted = true; + } public: OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) { @@ -117,20 +135,14 @@ namespace omath { if (!m_is_encrypted) return; - std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; - - for (size_t i = 0; i < bytes.size(); ++i) - bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); + xor_contained_var_by_key(); m_is_encrypted = false; } OMATH_FORCEINLINE constexpr void encrypt() { if (m_is_encrypted) return; - std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; - - for (size_t i = 0; i < bytes.size(); ++i) - bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); + xor_contained_var_by_key(); m_is_encrypted = true; } [[nodiscard]] From 3f940c8e35b20bec7b779eff081f2e5f6f72e0be Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:46:09 +0300 Subject: [PATCH 09/13] removed 128 bit int --- include/omath/containers/encrypted_variable.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 711a80d9..158fb21d 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -59,13 +59,10 @@ namespace omath::detail return splitmix64(base_seed() + 0xD1B54A32D192ED03ull * (Stream + 1)); } - // Unbiased bounded uniform using Lemire's method (uses 128-bit multiply) [[nodiscard]] consteval std::uint64_t bounded_u64(const std::uint64_t x, const std::uint64_t bound) { - // bound must be > 0 - __uint128_t m = static_cast<__uint128_t>(x) * static_cast<__uint128_t>(bound); - return static_cast(m >> 64); + return (x * bound) >> 64; } template @@ -97,7 +94,7 @@ namespace omath::detail } template - [[nodiscard]] + [[nodiscard]] consteval std::array make_array() { return make_array_impl(std::make_index_sequence{}); @@ -122,6 +119,7 @@ namespace omath bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); m_is_encrypted = true; } + public: OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) { From eae10d92caae3dad95c31c58b8a1953b3c2fc908 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 22:53:57 +0300 Subject: [PATCH 10/13] forgot to remove --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9f82b6e5..76ef3a7e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,7 +20,7 @@ else() # GTest is being linked as vcpkg package find_package(GTest CONFIG REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath) endif() -target_compile_options(${PROJECT_NAME} PRIVATE -static) + if(OMATH_ENABLE_COVERAGE) include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake) omath_setup_coverage(${PROJECT_NAME}) From d2e418c50bba3af2df045030c489d94dd2e55a0a Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 23:02:58 +0300 Subject: [PATCH 11/13] added cmake option --- CMakeLists.txt | 6 +++- .../omath/containers/encrypted_variable.hpp | 29 ++++++++++--------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fdf9c8ef..4d382ccd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" OFF) option(OMATH_ENABLE_LEGACY "Will enable legacy classes that MUST be used ONLY for backward compatibility" ON) option(OMATH_ENABLE_COVERAGE "Enable coverage" OFF) - +option(OMATH_ENABLE_FORCE_INLINE "Will for compiler to make some functions to be force inlined no matter what" ON) if (VCPKG_MANIFEST_FEATURES) foreach (omath_feature IN LISTS VCPKG_MANIFEST_FEATURES) if (omath_feature STREQUAL "imgui") @@ -112,6 +112,10 @@ if (OMATH_ENABLE_LEGACY) target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY) endif () +if (OMATH_ENABLE_FORCE_INLINE) + target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_FORCE_INLINE) +endif () + set_target_properties(${PROJECT_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}" diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 158fb21d..633fa798 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -6,11 +6,14 @@ #include #include #include - +#ifdef OMATH_ENABLE_FORCE_INLINE #ifdef _MSC_VER -#define OMATH_FORCEINLINE __forceinline +#define OMATH_FORCE_INLINE __forceinline +#else +#define OMATH_FORCE_INLINE __attribute__((always_inline)) inline +#endif #else -#define OMATH_FORCEINLINE __attribute__((always_inline)) inline +#define OMATH_FORCE_INLINE #endif namespace omath::detail @@ -111,7 +114,7 @@ namespace omath bool m_is_encrypted; T m_data; - OMATH_FORCEINLINE constexpr void xor_contained_var_by_key() + OMATH_FORCE_INLINE constexpr void xor_contained_var_by_key() { std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; @@ -121,7 +124,7 @@ namespace omath } public: - OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) + OMATH_FORCE_INLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) { encrypt(); } @@ -129,14 +132,14 @@ namespace omath { return m_is_encrypted; } - OMATH_FORCEINLINE constexpr void decrypt() + OMATH_FORCE_INLINE constexpr void decrypt() { if (!m_is_encrypted) return; xor_contained_var_by_key(); m_is_encrypted = false; } - OMATH_FORCEINLINE constexpr void encrypt() + OMATH_FORCE_INLINE constexpr void encrypt() { if (m_is_encrypted) return; @@ -144,21 +147,21 @@ namespace omath m_is_encrypted = true; } [[nodiscard]] - OMATH_FORCEINLINE constexpr T& value() + OMATH_FORCE_INLINE constexpr T& value() { return m_data; } [[nodiscard]] - OMATH_FORCEINLINE constexpr const T& value() const + OMATH_FORCE_INLINE constexpr const T& value() const { return m_data; } - OMATH_FORCEINLINE ~EncryptedVariable() + OMATH_FORCE_INLINE ~EncryptedVariable() { decrypt(); } [[nodiscard]] - OMATH_FORCEINLINE auto drop_anchor() + OMATH_FORCE_INLINE auto drop_anchor() { return VarAnchor{*this}; } @@ -168,11 +171,11 @@ namespace omath { public: // ReSharper disable once CppNonExplicitConvertingConstructor - OMATH_FORCEINLINE constexpr VarAnchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) + OMATH_FORCE_INLINE constexpr VarAnchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) { m_var.decrypt(); } - OMATH_FORCEINLINE constexpr ~VarAnchor() + OMATH_FORCE_INLINE constexpr ~VarAnchor() { m_var.encrypt(); } From 8366c48965387a20c7216c81514f79d0d0a5c0cd Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 23:22:25 +0300 Subject: [PATCH 12/13] improvement --- .../omath/containers/encrypted_variable.hpp | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index 633fa798..c1ba8f40 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -108,30 +108,39 @@ namespace omath { template class VarAnchor; + template key> class EncryptedVariable final { - bool m_is_encrypted; - T m_data; + using value_type = std::remove_cvref_t; + + bool m_is_encrypted{}; + value_type m_data{}; OMATH_FORCE_INLINE constexpr void xor_contained_var_by_key() { - std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + // Safe, keeps const-correctness, and avoids reinterpret_cast issues + auto bytes = std::as_writable_bytes(std::span{&m_data, 1}); - for (size_t i = 0; i < bytes.size(); ++i) - bytes[i] ^= static_cast(key[i % key.size()] + (i * key_size)); - m_is_encrypted = true; + for (std::size_t i = 0; i < bytes.size(); ++i) + { + const std::uint8_t k = static_cast(key[i % key_size] + (i * key_size)); + bytes[i] ^= static_cast(k); + } } public: - OMATH_FORCE_INLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(false), m_data(data) + OMATH_FORCE_INLINE constexpr explicit EncryptedVariable(const value_type& data) + : m_is_encrypted(false), m_data(data) { encrypt(); } + [[nodiscard]] constexpr bool is_encrypted() const { return m_is_encrypted; } + OMATH_FORCE_INLINE constexpr void decrypt() { if (!m_is_encrypted) @@ -139,6 +148,7 @@ namespace omath xor_contained_var_by_key(); m_is_encrypted = false; } + OMATH_FORCE_INLINE constexpr void encrypt() { if (m_is_encrypted) @@ -146,32 +156,33 @@ namespace omath xor_contained_var_by_key(); m_is_encrypted = true; } - [[nodiscard]] - OMATH_FORCE_INLINE constexpr T& value() + + [[nodiscard]] OMATH_FORCE_INLINE constexpr value_type& value() { return m_data; } - [[nodiscard]] - OMATH_FORCE_INLINE constexpr const T& value() const + [[nodiscard]] OMATH_FORCE_INLINE constexpr const value_type& value() const { return m_data; } - OMATH_FORCE_INLINE ~EncryptedVariable() + + constexpr OMATH_FORCE_INLINE ~EncryptedVariable() { decrypt(); } - [[nodiscard]] - OMATH_FORCE_INLINE auto drop_anchor() + + [[nodiscard]] constexpr OMATH_FORCE_INLINE auto drop_anchor() { return VarAnchor{*this}; } }; + template class VarAnchor { public: // ReSharper disable once CppNonExplicitConvertingConstructor - OMATH_FORCE_INLINE constexpr VarAnchor(EncryptedVarType& var): m_var(var) // NOLINT(*-explicit-constructor) + OMATH_FORCE_INLINE constexpr VarAnchor(EncryptedVarType& var): m_var(var) { m_var.decrypt(); } From 618d4aa1c09fefa1505f4b8a913bcbbd5a2027be Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 23:24:07 +0300 Subject: [PATCH 13/13] added final --- include/omath/containers/encrypted_variable.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp index c1ba8f40..3d1c250f 100644 --- a/include/omath/containers/encrypted_variable.hpp +++ b/include/omath/containers/encrypted_variable.hpp @@ -178,7 +178,7 @@ namespace omath }; template - class VarAnchor + class VarAnchor final { public: // ReSharper disable once CppNonExplicitConvertingConstructor