mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-08-13 14:21:57 -07:00
54 lines
1.7 KiB
C++
54 lines
1.7 KiB
C++
#pragma once
|
|||
|
|
|
||
|
|
#include <cstddef>
|
||
|
|
#include <memory>
|
||
|
|
#include <new>
|
||
|
|
#include <type_traits>
|
||
|
|
#include <utility>
|
||
|
|
|
||
|
|
// Nothrow versions of std::make_unique. Return nullptr on allocation failure
|
||
|
|
// instead of calling abort() (the default when exceptions are disabled on ESP32).
|
||
|
|
//
|
||
|
|
// Single object:
|
||
|
|
// auto obj = makeUniqueNoThrow<PNG>();
|
||
|
|
// if (!obj) { LOG_ERR("TAG", "OOM"); return false; }
|
||
|
|
//
|
||
|
|
// Array:
|
||
|
|
// auto buf = makeUniqueNoThrow<uint8_t[]>(size);
|
||
|
|
// if (!buf) { LOG_ERR("TAG", "OOM"); return false; }
|
||
|
|
// buf[0] = 0xFF;
|
||
|
|
// someApi(buf.get(), size);
|
||
|
|
//
|
||
|
|
|
||
|
|
template <typename T, typename... Args>
|
||
|
|
requires(!std::is_array_v<T>)
|
||
|
|
std::unique_ptr<T> makeUniqueNoThrow(Args&&... args) {
|
||
|
|
return std::unique_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename T>
|
||
|
|
requires std::is_unbounded_array_v<T>
|
||
|
|
std::unique_ptr<T> makeUniqueNoThrow(size_t count) {
|
||
|
|
using Elem = std::remove_extent_t<T>;
|
||
|
|
return std::unique_ptr<T>(new (std::nothrow) Elem[count]());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper struct to call a cleanup function on exit from any scope.
|
||
|
|
// Use with a lambda to avoid unnecessary allocations from std::function/std::bind:
|
||
|
|
// Example:
|
||
|
|
// auto jpeg = makeUniqueNoThrow<JPEGDEC>();
|
||
|
|
// ScopedCleanup cleanup{[&jpeg]{ jpeg->close(); }};
|
||
|
|
//
|
||
|
|
template <typename F>
|
||
|
|
struct [[nodiscard]] ScopedCleanup final {
|
||
|
|
const F fn;
|
||
|
|
explicit ScopedCleanup(F f) : fn{std::move(f)} {}
|
||
|
|
ScopedCleanup(const ScopedCleanup&) = delete;
|
||
|
|
ScopedCleanup& operator=(const ScopedCleanup&) = delete;
|
||
|
|
ScopedCleanup(ScopedCleanup&&) = delete;
|
||
|
|
ScopedCleanup& operator=(ScopedCleanup&&) = delete;
|
||
|
|
~ScopedCleanup() { fn(); }
|
||
|
|
};
|
||
|
|
|
||
|
|
template <typename F>
|
||
|
|
ScopedCleanup(F) -> ScopedCleanup<F>;
|