summaryrefslogtreecommitdiff
path: root/deimos/core/status.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deimos/core/status.cpp')
-rw-r--r--deimos/core/status.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/deimos/core/status.cpp b/deimos/core/status.cpp
new file mode 100644
index 0000000..ed1a665
--- /dev/null
+++ b/deimos/core/status.cpp
@@ -0,0 +1,70 @@
+#include "deimos/core/status.h"
+
+#include "deimos/core/api_registry.h"
+#include "deimos/core/allocator.h"
+
+static deimos::AllocatorApi* allocator_api;
+
+namespace deimos
+{
+
+Status::Status(StatusCode code, StringView message)
+{
+ if (code == StatusCode::kOk)
+ {
+ m_rep = CodeToRep(StatusCode::kOk);
+ }
+ else
+ {
+ void* ptr = allocator_api->system->Allocate((int64_t)sizeof(StatusRep) + message.size() + 1);
+ auto* rep = new(ptr) StatusRep;
+
+ char* message_ptr = (char*)ptr + sizeof(StatusRep); // NOLINT
+ MemoryCopy(message_ptr, message.data(), message.size());
+ message_ptr[message.size()] = '\0'; // NOLINT
+
+ rep->ref_count = 1;
+ rep->code = code;
+ rep->message = StringView(message_ptr, message.size());
+
+ m_rep = std::bit_cast<uintptr_t>(rep);
+ Ensures((m_rep & 1U) == 0);
+ }
+}
+
+void Status::Ref() const
+{
+ if (!IsInline())
+ {
+ auto* rep = std::bit_cast<StatusRep*>(m_rep);
+
+ Expects(rep->ref_count > 0);
+ rep->ref_count += 1;
+ }
+}
+
+void Status::Unref() const
+{
+ if (!IsInline())
+ {
+ auto* rep = std::bit_cast<StatusRep*>(m_rep);
+
+ Expects(rep->ref_count > 0);
+ rep->ref_count -= 1;
+
+ if (rep->ref_count == 0)
+ {
+ deimos_StaticAssert(std::is_trivially_destructible_v<StatusRep>);
+ allocator_api->system->Free(
+ rep, (int64_t)sizeof(StatusRep) + rep->message.size() + 1);
+ }
+ }
+}
+
+void InitializeStatus(ApiRegistry* api_registry)
+{
+ allocator_api = api_registry->Get<AllocatorApi>();
+}
+
+} // namespace deimos
+