Files
nostalgia/deps/ox/src/ox/std/new.hpp
Gary Talent 9f338a7429
All checks were successful
Build / build (push) Successful in 3m18s
[ox] Run liccor
2025-01-08 23:03:05 -06:00

173 lines
3.9 KiB
C++

/*
* Copyright 2015 - 2025 gary@drinkingtea.net
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "error.hpp"
#include "defines.hpp"
#include "types.hpp"
#include "utility.hpp"
#if defined(_MSC_VER)
#include <malloc.h>
#elif OX_USE_STDLIB
#include <cstdlib>
#endif
#if __has_include(<new>)
#include <new>
#else
constexpr void *operator new(std::size_t, void *addr) noexcept {
return addr;
}
constexpr void *operator new[](std::size_t, void *addr) noexcept {
return addr;
}
#endif
namespace ox {
template<typename T, typename U = T, typename ...Args>
[[nodiscard]]
constexpr U *make(Args &&...args) noexcept {
#ifdef __cpp_exceptions
try {
return new T(ox::forward<Args>(args)...);
} catch (std::exception const&ex) {
oxPanic(ox::Error(1, ex.what()), ex.what());
return nullptr;
} catch (...) {
oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
return nullptr;
}
#else
return new T(ox::forward<Args>(args)...);
#endif
}
template<typename T, typename ...Args>
[[nodiscard]]
constexpr Result<T*> makeCatch(Args &&...args) noexcept {
#ifdef __cpp_exceptions
try {
return new T(ox::forward<Args>(args)...);
} catch (const ox::Exception &ex) {
return ex.toError();
} catch (...) {
return ox::Error(1, "Allocation or constructor failed");
}
#else
return new T(ox::forward<Args>(args)...);
#endif
}
constexpr auto MallocaStackLimit = defines::UseStdLib ? 1024 : 0;
/**
* MallocaPtr will automatically cleanup the pointed to address upon
* destruction if the size of the allocation is greater than MallocaStackLimit.
*/
template<typename T>
class MallocaPtr {
private:
bool m_onHeap = false;
T *m_val = nullptr;
public:
constexpr MallocaPtr() noexcept = default;
constexpr MallocaPtr(MallocaPtr &other) = delete;
constexpr MallocaPtr(const MallocaPtr &other) = delete;
constexpr MallocaPtr(MallocaPtr &&other) noexcept {
m_onHeap = other.m_onHeap;
m_val = other.m_val;
other.m_onHeap = false;
other.m_val = nullptr;
}
constexpr MallocaPtr(bool onHeap, T *val) noexcept {
m_onHeap = onHeap;
m_val = val;
}
constexpr ~MallocaPtr() noexcept {
m_val->~T();
if (m_onHeap && m_val) {
delete[] reinterpret_cast<uint8_t*>(m_val);
}
}
constexpr const T *get() const noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr T *get() noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr MallocaPtr &operator=(MallocaPtr &other) = delete;
constexpr MallocaPtr &operator=(const MallocaPtr &other) = delete;
constexpr MallocaPtr &operator=(MallocaPtr &&other) noexcept {
if (m_onHeap && m_val) {
delete[] reinterpret_cast<uint8_t*>(m_val);
}
m_onHeap = other.m_onHeap;
m_val = other.m_val;
other.m_onHeap = false;
other.m_val = nullptr;
return *this;
}
constexpr const T *operator->() const noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr T *operator->() noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr explicit operator const T*() const noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr explicit operator T*() noexcept {
return reinterpret_cast<T*>(m_val);
}
constexpr const T &operator*() const noexcept {
return *reinterpret_cast<T*>(m_val);
}
constexpr T &operator*() noexcept {
return *reinterpret_cast<T*>(m_val);
}
constexpr bool operator==(std::nullptr_t) const noexcept {
return m_val == nullptr;
}
constexpr bool operator==(const MallocaPtr<T> &other) const noexcept {
return m_val == other.m_val && m_onHeap == other.m_onHeap;
}
constexpr bool operator!=(const MallocaPtr<T> &other) const noexcept {
return m_val != other.m_val || m_onHeap != other.m_onHeap;
}
};
}