Files
nostalgia/deps/ox/src/ox/std/error.hpp

220 lines
4.5 KiB
C++

/*
* Copyright 2015 - 2022 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
#if __has_include(<exception>)
#include <exception>
#else
namespace std {
class exception {
public:
virtual ~exception() = default;
[[nodiscard]]
virtual const char *what() const noexcept {
return "";
}
};
}
#endif
#include "def.hpp"
#include "defines.hpp"
#include "strongint.hpp"
#include "typetraits.hpp"
#include "utility.hpp"
#define OxError(...) ox::Error(__FILE__, __LINE__, __VA_ARGS__)
#define OxException(...) ox::Exception(__FILE__, __LINE__, __VA_ARGS__)
namespace ox {
using ErrorCode = uint16_t;
struct [[nodiscard]] Error {
const char *msg = nullptr;
const char *file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0;
constexpr Error() noexcept = default;
explicit constexpr Error(ErrorCode ec) noexcept: errCode(ec) {
}
explicit constexpr Error(const char *file, uint32_t line, ErrorCode errCode, const char *msg = nullptr) noexcept {
this->file = file;
this->line = line;
this->msg = msg;
this->errCode = errCode;
}
constexpr Error(const Error &o) noexcept {
this->msg = o.msg;
this->file = o.file;
this->line = o.line;
this->errCode = o.errCode;
}
constexpr Error &operator=(const Error &o) noexcept {
this->msg = o.msg;
this->file = o.file;
this->line = o.line;
this->errCode = o.errCode;
return *this;
}
constexpr operator uint64_t() const noexcept {
return errCode;
}
};
[[nodiscard]]
constexpr auto errCode(const Error &err) noexcept {
return err.errCode;
}
template<typename T=const char*>
[[nodiscard]]
constexpr auto toStr(const Error &err) noexcept {
return err.msg ? T(err.msg) : "";
}
struct Exception: public std::exception {
const char *msg = nullptr;
const char *file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0;
explicit inline Exception(const char *file, uint32_t line, ErrorCode errCode, const char *msg = "") noexcept {
this->file = file;
this->line = line;
this->msg = msg;
this->errCode = errCode;
}
inline explicit Exception(const Error &err) {
if (err.msg) {
this->msg = err.msg;
} else {
this->msg = "";
}
this->file = err.file;
this->line = err.line;
this->errCode = err.errCode;
}
constexpr Error toError() const noexcept {
return Error(file, line, errCode, msg);
}
[[nodiscard]]
const char *what() const noexcept override {
return msg;
}
};
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept;
template<typename T>
struct [[nodiscard]] Result {
using type = typename remove_reference<T>::type;
T value;
Error error;
constexpr Result() noexcept: error(0) {
}
template<typename U>
constexpr Result(const Result<U> &other) noexcept: value(other.value), error(other.error) {
}
template<typename U>
constexpr Result(const Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
}
constexpr Result(const Error &error) noexcept: error(error) {
}
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(const_cast<type&>(value)), error(error) {
}
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(ox::forward<type>(value)), error(error) {
}
constexpr ~Result() noexcept = default;
explicit constexpr operator const type&() const noexcept {
return value;
}
explicit constexpr operator type&() noexcept {
return value;
}
[[nodiscard]]
constexpr bool ok() const noexcept {
return error == 0;
}
constexpr Error get(type *val) const noexcept {
*val = value;
return error;
}
constexpr Error get(type *val) noexcept {
*val = value;
return error;
}
constexpr Error moveTo(type *val) noexcept {
if (!error) [[likely]] {
*val = std::move(value);
}
return error;
}
constexpr auto &unwrap() noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
}
return value;
}
constexpr const auto &unwrap() const noexcept {
if (error) [[unlikely]] {
oxPanic(error, "Failed unwrap");
}
return value;
}
};
namespace detail {
constexpr Error toError(const Error &e) noexcept {
return e;
}
template<typename T>
constexpr Error toError(const Result<T> &ve) noexcept {
return ve.error;
}
}
}
constexpr void oxIgnoreError(const ox::Error&) noexcept {}
template<typename T>
constexpr void oxIgnoreError(const ox::Result<T>&) noexcept {}