diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-04 22:55:46 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-04 22:55:46 +0100 |
commit | b53fc9038f4579974c9eea28e82b693a7fd66522 (patch) | |
tree | 4b411286ee139c3649eae90a6d3ae19f7db036df /asl | |
parent | b62e554e9763497e53bae0a3d5a895c1cdbf40de (diff) |
Add copy to status
Diffstat (limited to 'asl')
-rw-r--r-- | asl/status.cpp | 21 | ||||
-rw-r--r-- | asl/status.hpp | 35 | ||||
-rw-r--r-- | asl/tests/status_tests.cpp | 45 |
3 files changed, 90 insertions, 11 deletions
diff --git a/asl/status.cpp b/asl/status.cpp index eb26111..c081f33 100644 --- a/asl/status.cpp +++ b/asl/status.cpp @@ -3,6 +3,7 @@ #include "asl/string.hpp" #include "asl/atomic.hpp" +// @Todo Use custom allocator using Allocator = asl::DefaultAllocator; static Allocator g_allocator{}; @@ -11,13 +12,12 @@ namespace struct StatusInternal { - // @Todo Use custom allocator - asl::string<> msg; + asl::string<Allocator> msg; asl::status_code code; asl::atomic<int32_t> ref_count; constexpr StatusInternal(asl::string_view msg_, asl::status_code code_) - : msg{msg_} + : msg{msg_, g_allocator} , code{code_} { atomic_store(&ref_count, 1); @@ -32,10 +32,23 @@ asl::status::status(status_code code, string_view msg) asl::status_code asl::status::code_internal() const { - ASL_ASSERT(m_payload && (bit_cast<uintptr_t>(m_payload) & 1) == 0); + ASL_ASSERT(!is_inline()); return reinterpret_cast<const StatusInternal*>(m_payload)->code; } +asl::string_view asl::status::message_internal() const +{ + ASL_ASSERT(!is_inline()); + return reinterpret_cast<const StatusInternal*>(m_payload)->msg; +} + +void asl::status::ref() +{ + ASL_ASSERT(!is_inline()); + auto* internal = reinterpret_cast<StatusInternal*>(m_payload); + atomic_fetch_increment(&internal->ref_count, memory_order::relaxed); +} + void asl::status::unref() { ASL_ASSERT(!is_inline()); diff --git a/asl/status.hpp b/asl/status.hpp index c494759..4d54b61 100644 --- a/asl/status.hpp +++ b/asl/status.hpp @@ -49,7 +49,9 @@ class status } status_code code_internal() const; + string_view message_internal() const; + void ref(); void unref(); public: @@ -57,10 +59,7 @@ public: constexpr ~status() { - if (!is_inline()) - { - unref(); - } + if (!is_inline()) { unref(); } } explicit constexpr status(status_code code) @@ -69,10 +68,27 @@ public: status(status_code code, string_view msg); + constexpr status(const status& other) + : m_payload{other.m_payload} + { + if (!is_inline()) { ref(); } + } + constexpr status(status&& other) : m_payload{exchange(other.m_payload, nullptr)} {} + constexpr status& operator=(const status& other) + { + if (&other != this) + { + if (!is_inline()) { unref(); } + m_payload = other.m_payload; + if (!is_inline()) { ref(); } + } + return *this; + } + constexpr status& operator=(status&& other) { if (&other != this) @@ -82,8 +98,6 @@ public: return *this; } - // @Todo Copy constructor & assignment - constexpr bool ok() const { return m_payload == nullptr || code() == status_code::ok; @@ -96,6 +110,15 @@ public: { return is_inline() ? code_inline() : code_internal(); } + + constexpr string_view message() const + { + if (!is_inline()) + { + return message_internal(); + } + return {}; + } }; } // namespace asl diff --git a/asl/tests/status_tests.cpp b/asl/tests/status_tests.cpp index edfb65d..aa7dad1 100644 --- a/asl/tests/status_tests.cpp +++ b/asl/tests/status_tests.cpp @@ -15,6 +15,7 @@ ASL_TEST(simple_code) ASL_TEST_ASSERT(!s); ASL_TEST_ASSERT(!s.ok()); ASL_TEST_ASSERT(s.code() == asl::status_code::runtime); + ASL_TEST_ASSERT(s.message() == ""_sv); } ASL_TEST(with_message) @@ -23,5 +24,47 @@ ASL_TEST(with_message) ASL_TEST_ASSERT(!s); ASL_TEST_ASSERT(!s.ok()); ASL_TEST_ASSERT(s.code() == asl::status_code::internal); - // @Todo test message + ASL_TEST_ASSERT(s.message() == "We done goofed"_sv); +} + +ASL_TEST(copy_inline) +{ + asl::status s{asl::status_code::ok}; + asl::status s2{asl::status_code::internal}; + + asl::status s3 = s; + ASL_TEST_ASSERT(s3.code() == asl::status_code::ok); + + s3 = s2; + ASL_TEST_ASSERT(s3.code() == asl::status_code::internal); +} + +ASL_TEST(copy_message) +{ + asl::status s2; + + { + asl::status s{asl::status_code::internal, "Oh no!"}; + ASL_TEST_ASSERT(!s); + ASL_TEST_ASSERT(!s.ok()); + ASL_TEST_ASSERT(s.code() == asl::status_code::internal); + ASL_TEST_ASSERT(s.message() == "Oh no!"_sv); + + const asl::status s3{s}; // NOLINT + ASL_TEST_ASSERT(!s3); + ASL_TEST_ASSERT(!s3.ok()); + ASL_TEST_ASSERT(s3.code() == asl::status_code::internal); + ASL_TEST_ASSERT(s3.message() == "Oh no!"_sv); + + s2 = s; + ASL_TEST_ASSERT(!s2); + ASL_TEST_ASSERT(!s2.ok()); + ASL_TEST_ASSERT(s2.code() == asl::status_code::internal); + ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv); + } + + ASL_TEST_ASSERT(!s2); + ASL_TEST_ASSERT(!s2.ok()); + ASL_TEST_ASSERT(s2.code() == asl::status_code::internal); + ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv); } |