diff --git a/fggl/util/guid.cpp b/fggl/util/guid.cpp index 569353daa74538496ab20a0ecd41abcbb2968c78..f2f908a080a174290ee6039470cc789fe88936c0 100644 --- a/fggl/util/guid.cpp +++ b/fggl/util/guid.cpp @@ -23,9 +23,13 @@ #include "fggl/util/guid.hpp" namespace fggl::util { - static std::map<GUID, std::string> guidTable; + namespace { + std::map<GUID, std::string> guidTable; + } GUID internString(const char* str) { + assert(str != nullptr); + GUID guid = make_guid(str); auto tableValue = guidTable.find(guid); if (tableValue != guidTable.end()) { @@ -33,6 +37,7 @@ namespace fggl::util { } else { guidTable[guid] = str; } + return guid; } std::string guidToString(GUID guid) { @@ -43,4 +48,15 @@ namespace fggl::util { return "FGGL_UNKNOWN_GUID"; } } + +} + +fggl::util::GUID operator "" _fid(const char* str) { + fggl::util::internString(str); + return fggl::util::make_guid(str); +} + +fggl::util::GUID operator "" _fid(const char* str, std::size_t) { + fggl::util::internString(str); + return fggl::util::make_guid(str); } diff --git a/include/fggl/util/guid.hpp b/include/fggl/util/guid.hpp index a4ac1e805c920998a607d0a643f44e520f9870f1..c9c85b2db090d69700223911214b6ad3b982c683 100644 --- a/include/fggl/util/guid.hpp +++ b/include/fggl/util/guid.hpp @@ -68,14 +68,13 @@ namespace fggl::util { return GUID::make(hash_fnv1a_64(str)); } - constexpr GUID operator ""_fid(const char* str) { - return make_guid(str); - } - // debug-only functions GUID internString(const char* str); std::string guidToString(GUID guid); } // namespace fggl::util +fggl::util::GUID operator "" _fid(const char* str); +fggl::util::GUID operator "" _fid(const char* str, std::size_t); + #endif //FGGL_UTIL_GUID_HPP diff --git a/include/fggl/util/safety.hpp b/include/fggl/util/safety.hpp index 18797eab7b97af1fcad579bd366e79fd7ba44380..6a10829c40fc7ee7a07cbfb238f1e442c6f82460 100644 --- a/include/fggl/util/safety.hpp +++ b/include/fggl/util/safety.hpp @@ -23,6 +23,16 @@ namespace fggl::util { + /** + * A type-safe opaque handle. + * + * Lots of low-level libaries we use pass around handles as some primative type. It's fairly easy to accidentally + * mix these up. This wrapper's job is to make sure that mixing up handle types is impossible (and results in + * compiler errors). + * + * @tparam T the underling type of the handle. + * @tparam Tag a unique tag used to identify the handle type. + */ template<typename T, typename Tag> struct OpaqueName { private: diff --git a/tests/testfggl/CMakeLists.txt b/tests/testfggl/CMakeLists.txt index 13fa77df7212bcac817d883a71ef23e4ae993cb7..589fbb1e84a221193c5cf07ff684bcfcf1b2f44d 100644 --- a/tests/testfggl/CMakeLists.txt +++ b/tests/testfggl/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable( fggl_test # ecs3/easing.cpp # math/types.cpp util/guid.cpp + util/safety.cpp ) target_include_directories(fggl_test PUBLIC diff --git a/tests/testfggl/util/guid.cpp b/tests/testfggl/util/guid.cpp index 0d2baa97f9c69a423a135bf8a6a68b3145254b11..e4dedf7b8280a2c2eceb322f38030adb5120ef2e 100644 --- a/tests/testfggl/util/guid.cpp +++ b/tests/testfggl/util/guid.cpp @@ -17,8 +17,6 @@ // #include <gtest/gtest.h> -#include <gmock/gmock.h> - #include "fggl/util/guid.hpp" namespace { @@ -69,7 +67,6 @@ namespace { } // sanity checks - TEST(UtilHash32, RepeatsAreEqual) { auto value = fggl::util::hash_fnv1a_32("fggl::test::scoped"); auto value2 = fggl::util::hash_fnv1a_32("fggl::test::scoped"); @@ -82,4 +79,16 @@ namespace { EXPECT_EQ( value, value2 ); } + // GUID tests + TEST(GuidTest, GuidSuffix) { + auto guid = fggl::util::make_guid("test"); + auto guidSuffix = "test"_fid; + EXPECT_EQ(guid, guidSuffix); + } + + TEST(GuidTest, GuidToString) { + fggl::util::GUID guid = fggl::util::internString("test"); + EXPECT_EQ("test", fggl::util::guidToString(guid)); + } + } diff --git a/tests/testfggl/util/safety.cpp b/tests/testfggl/util/safety.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f88475d592ba4951068c5ab4bc04abe5d7042b4c --- /dev/null +++ b/tests/testfggl/util/safety.cpp @@ -0,0 +1,44 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 23/07/22. +// + +#include <gtest/gtest.h> +#include "fggl/util/safety.hpp" + +namespace { + + using TestType = fggl::util::OpaqueName<unsigned int, struct TestTag>; + + TEST(SafetyHandle, CheckZero) { + auto v1 = TestType::make(0); + auto v2 = TestType::make(0); + EXPECT_EQ(v1, v2); + } + + TEST(SafetyHandle, CheckValue) { + auto v1 = TestType::make(0x12345678); + auto v2 = TestType::make(0x12345678); + EXPECT_EQ(v1, v2); + } + + TEST(SafetyHandle, CheckValueNE) { + auto v1 = TestType::make(0x12345678); + auto v2 = TestType::make(0x87654321); + EXPECT_NE(v1, v2); + } + +} \ No newline at end of file