173 lines
3.9 KiB
C++
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;
|
|
}
|
|
|
|
};
|
|
|
|
}
|