220 lines
4.5 KiB
C++
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 {}
|