diff --git a/.gitignore b/.gitignore index a8552c1..c5ecf30 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ _deps .vscode build/ doxygen/ -doxygen-awesome-css/ \ No newline at end of file +doxygen-awesome-css/ +.cache/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index aa8cdf9..70e8099 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,15 +47,6 @@ set_target_properties( target_link_libraries(hyprlang PkgConfig::deps) -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # for std::expected. probably evil. Arch's clang is very outdated tho... - target_compile_options(hyprlang PUBLIC -std=gnu++2b -D__cpp_concepts=202002L - -Wno-macro-redefined) - add_compile_options(-stdlib=libc++) - add_link_options(-stdlib=libc++) - message(STATUS "Using clang++ to compile hyprlang") -endif() - add_library(hypr::hyprlang ALIAS hyprlang) install(TARGETS hyprlang) diff --git a/VERSION b/VERSION index be14282..a918a2a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.3 +0.6.0 diff --git a/flake.lock b/flake.lock index 5abff22..f10b776 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1721324102, - "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "lastModified": 1733502241, + "narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "962582a090bc233c4de9d9897f46794280288989", + "rev": "104117aed6dd68561be38b50f218190aa47f2cd8", "type": "github" }, "original": { @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1721138476, - "narHash": "sha256-+W5eZOhhemLQxelojLxETfbFbc19NWawsXBlapYpqIA=", + "lastModified": 1734119587, + "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad0b5eed1b6031efaed382844806550c3dcb4206", + "rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 959d3cf..bf45f9a 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ inputs.hyprutils.overlays.default (final: prev: { hyprlang = final.callPackage ./nix/default.nix { - stdenv = final.gcc13Stdenv; + stdenv = final.gcc14Stdenv; version = version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty"); }; hyprlang-with-tests = final.hyprlang.override {doCheck = true;}; diff --git a/include/hyprlang.hpp b/include/hyprlang.hpp index 739206a..bdcec2e 100644 --- a/include/hyprlang.hpp +++ b/include/hyprlang.hpp @@ -3,11 +3,13 @@ #ifndef HYPRLANG_HPP #define HYPRLANG_HPP +#include #include -#include #include -#include +#include #include +#include +#include #include class CConfigImpl; @@ -459,6 +461,87 @@ namespace Hyprlang { void retrieveKeysForCat(const char* category, const char*** out, size_t* len); CParseResult parseRawStream(const std::string& stream); }; + + /*! + Templated wrapper for Hyprlang values. Much more straightforward to use. + + \since 0.6.0 + */ + template + class CSimpleConfigValue { + public: + CSimpleConfigValue(CConfig* const pConfig, const char* val) { + const auto VAL = pConfig->getConfigValuePtr(val); + + if (!VAL) { + std::println("CSimpleConfigValue: value not found"); + abort(); + } + + // NOLINTNEXTLINE + p_ = VAL->getDataStaticPtr(); + +#ifdef HYPRLAND_DEBUG + // verify type + const auto ANY = VAL->getValue(); + const auto TYPE = std::type_index(ANY.type()); + + // exceptions + const bool STRINGEX = (typeid(T) == typeid(std::string) && TYPE == typeid(Hyprlang::STRING)); + const bool CUSTOMEX = (typeid(T) == typeid(Hyprlang::CUSTOMTYPE) && (TYPE == typeid(Hyprlang::CUSTOMTYPE*) || TYPE == typeid(void*) /* dunno why it does this? */)); + + if (typeid(T) != TYPE && !STRINGEX && !CUSTOMEX) { + std::println("CSimpleConfigValue: Mismatched type in CConfigValue, got {} but has {}", typeid(T).name(), TYPE.name()); + abort(); + } +#endif + } + + T* ptr() const { + return *(T* const*)p_; + } + + T operator*() const { + return *ptr(); + } + + private: + void* const* p_ = nullptr; + }; + + template <> + inline std::string* CSimpleConfigValue::ptr() const { + std::print("Impossible to implement ptr() of CConfigValue"); + abort(); + return nullptr; + } + + template <> + inline std::string CSimpleConfigValue::operator*() const { + return std::string{*(Hyprlang::STRING*)p_}; + } + + template <> + inline Hyprlang::STRING* CSimpleConfigValue::ptr() const { + return (Hyprlang::STRING*)p_; + } + + template <> + inline Hyprlang::STRING CSimpleConfigValue::operator*() const { + return *(Hyprlang::STRING*)p_; + } + + template <> + inline Hyprlang::CUSTOMTYPE* CSimpleConfigValue::ptr() const { + return *(Hyprlang::CUSTOMTYPE* const*)p_; + } + + template <> + inline Hyprlang::CUSTOMTYPE CSimpleConfigValue::operator*() const { + std::print("Impossible to implement operator* of CConfigValue, use ptr()"); + abort(); + return *ptr(); + } }; #ifndef HYPRLANG_INTERNAL diff --git a/src/config.hpp b/src/config.hpp index f81bc3e..61072b8 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -3,6 +3,7 @@ #include #include #include +#include static const char* MULTILINE_SPACE_CHARSET = " \t"; diff --git a/tests/parse/main.cpp b/tests/parse/main.cpp index 521376d..52d3154 100755 --- a/tests/parse/main.cpp +++ b/tests/parse/main.cpp @@ -187,6 +187,16 @@ int main(int argc, char** argv, char** envp) { EXPECT(ignoreKeyword, "aaa"); EXPECT(useKeyword, "yes"); + // Test templated wrapper + auto T1 = Hyprlang::CSimpleConfigValue(&config, "testInt"); + auto T2 = Hyprlang::CSimpleConfigValue(&config, "testFloat"); + auto T3 = Hyprlang::CSimpleConfigValue(&config, "testVec"); + auto T4 = Hyprlang::CSimpleConfigValue(&config, "testString"); + EXPECT(*T1, 123); + EXPECT(*T2, 123.456F); + EXPECT(*T3, EXP); + EXPECT(*T4, "Hello World! # This is not a comment!"); + // test static values std::cout << " → Testing static values\n"; static auto* const PTESTINT = config.getConfigValuePtr("testInt")->getDataStaticPtr();