Added support for completely disabling noexcept using MIJIN_TEST_NO_NOEXCEPT (for testing).

This commit is contained in:
Patrick 2024-08-29 00:01:23 +02:00
parent a43f92fb58
commit 9ba097fc2f
41 changed files with 643 additions and 564 deletions

View File

@ -34,6 +34,12 @@ if env.get('MIJIN_ENABLE_OPENSSL'):
source/mijin/net/ssl.cpp
"""))
# CURL libs
if env.get('MIJIN_ENABLE_CURL'):
cppdefines.append('MIJIN_ENABLE_CURL=1')
mijin_sources.extend(Split("""
source/mijin/net/request.cpp
"""))
lib_mijin = env.UnityStaticLibrary(
target = env['LIB_DIR'] + '/mijin',

View File

@ -10,5 +10,9 @@
"openssl":
{
"condition": "getenv('MIJIN_ENABLE_OPENSSL')"
},
"curl":
{
"condition": "getenv('MIJIN_ENABLE_CURL')"
}
}

View File

@ -135,7 +135,7 @@ void MultiThreadedTaskLoop::workerThread(std::stop_token stopToken, std::size_t
// public functions
//
void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT
{
assertCorrectThread();
@ -153,7 +153,7 @@ void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
otherLoop.addStoredTask(std::move(storedTask));
}
void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT
{
storedTask.task->setLoop(this);
if (threadId_ == std::thread::id() || threadId_ == std::this_thread::get_id())
@ -174,7 +174,7 @@ void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
}
}
std::size_t SimpleTaskLoop::getActiveTasks() const noexcept
std::size_t SimpleTaskLoop::getActiveTasks() const MIJIN_NOEXCEPT
{
std::size_t sum = 0;
for (const StoredTask& task : mijin::chain(tasks_, newTasks_))
@ -188,7 +188,7 @@ std::size_t SimpleTaskLoop::getActiveTasks() const noexcept
return sum;
}
void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT
{
if (&otherLoop == this) {
return;
@ -204,7 +204,7 @@ void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
otherLoop.addStoredTask(std::move(storedTask));
}
void MultiThreadedTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
void MultiThreadedTaskLoop::addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT
{
storedTask.task->setLoop(this);

View File

@ -19,6 +19,7 @@
#include "./future.hpp"
#include "./message_queue.hpp"
#include "../container/optional.hpp"
#include "../internal/common.hpp"
#include "../util/flag.hpp"
#include "../util/iterators.hpp"
#include "../util/traits.hpp"
@ -68,28 +69,28 @@ private:
std::weak_ptr<struct TaskSharedState> state_;
public:
TaskHandle() = default;
explicit TaskHandle(std::weak_ptr<TaskSharedState> state) noexcept : state_(std::move(state)) {}
explicit TaskHandle(std::weak_ptr<TaskSharedState> state) MIJIN_NOEXCEPT : state_(std::move(state)) {}
TaskHandle(const TaskHandle&) = default;
TaskHandle(TaskHandle&&) = default;
TaskHandle& operator=(const TaskHandle&) = default;
TaskHandle& operator=(TaskHandle&&) = default;
bool operator==(const TaskHandle& other) const noexcept {
bool operator==(const TaskHandle& other) const MIJIN_NOEXCEPT {
return !state_.owner_before(other.state_) && !other.state_.owner_before(state_);
}
bool operator!=(const TaskHandle& other) const noexcept {
bool operator!=(const TaskHandle& other) const MIJIN_NOEXCEPT {
return !(*this == other);
}
[[nodiscard]] bool isValid() const noexcept
[[nodiscard]] bool isValid() const MIJIN_NOEXCEPT
{
return !state_.expired();
}
inline void cancel() const noexcept;
inline void cancel() const MIJIN_NOEXCEPT;
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
inline Optional<Stacktrace> getCreationStack() const noexcept;
inline Optional<Stacktrace> getCreationStack() const MIJIN_NOEXCEPT;
#endif
};
struct TaskSharedState
@ -110,11 +111,11 @@ struct TaskState
TaskState() = default;
TaskState(const TaskState&) = default;
TaskState(TaskState&&) noexcept = default;
inline TaskState(T _value, TaskStatus _status) noexcept : value(std::move(_value)), status(_status) {}
inline TaskState(std::exception_ptr _exception) noexcept : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
TaskState(TaskState&&) MIJIN_NOEXCEPT = default;
inline TaskState(T _value, TaskStatus _status) MIJIN_NOEXCEPT : value(std::move(_value)), status(_status) {}
inline TaskState(std::exception_ptr _exception) MIJIN_NOEXCEPT : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
TaskState& operator=(const TaskState&) = default;
TaskState& operator=(TaskState&&) noexcept = default;
TaskState& operator=(TaskState&&) MIJIN_NOEXCEPT = default;
};
template<>
@ -125,11 +126,11 @@ struct TaskState<void>
TaskState() = default;
TaskState(const TaskState&) = default;
TaskState(TaskState&&) noexcept = default;
inline TaskState(TaskStatus _status) noexcept : status(_status) {}
inline TaskState(std::exception_ptr _exception) noexcept : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
TaskState(TaskState&&) MIJIN_NOEXCEPT = default;
inline TaskState(TaskStatus _status) MIJIN_NOEXCEPT : status(_status) {}
inline TaskState(std::exception_ptr _exception) MIJIN_NOEXCEPT : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
TaskState& operator=(const TaskState&) = default;
TaskState& operator=(TaskState&&) noexcept = default;
TaskState& operator=(TaskState&&) MIJIN_NOEXCEPT = default;
};
namespace impl
@ -138,15 +139,15 @@ template<typename TReturn, typename TPromise>
struct TaskReturn
{
template<typename... TArgs>
constexpr void return_value(TArgs&&... args) noexcept {
constexpr void return_value(TArgs&&... args) MIJIN_NOEXCEPT {
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(TReturn(std::forward<TArgs>(args)...), TaskStatus::FINISHED);
}
constexpr void return_value(TReturn value) noexcept {
constexpr void return_value(TReturn value) MIJIN_NOEXCEPT {
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(TReturn(std::move(value)), TaskStatus::FINISHED);
}
constexpr void unhandled_exception() noexcept {
constexpr void unhandled_exception() MIJIN_NOEXCEPT {
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(std::current_exception());
}
};
@ -154,11 +155,11 @@ struct TaskReturn
template<typename TPromise>
struct TaskReturn<void, TPromise>
{
constexpr void return_void() noexcept {
constexpr void return_void() MIJIN_NOEXCEPT {
static_cast<TPromise&>(*this).state_.status = TaskStatus::FINISHED;
}
constexpr void unhandled_exception() noexcept {
constexpr void unhandled_exception() MIJIN_NOEXCEPT {
(static_cast<TPromise&>(*this).state_) = TaskState<void>(std::current_exception());
}
};
@ -169,8 +170,8 @@ struct TaskAwaitableFuture
{
FuturePtr<TValue> future;
[[nodiscard]] constexpr bool await_ready() const noexcept { return future->ready(); }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return future->ready(); }
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
constexpr TValue await_resume() const
{
impl::throwIfCancelled();
@ -188,8 +189,8 @@ struct TaskAwaitableSignal
{
std::shared_ptr<std::tuple<TArgs...>> data;
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
inline auto& await_resume() const
{
impl::throwIfCancelled();
@ -202,8 +203,8 @@ struct TaskAwaitableSignal<TSingleArg>
{
std::shared_ptr<TSingleArg> data;
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
constexpr auto& await_resume() const
{
impl::throwIfCancelled();
@ -214,8 +215,8 @@ struct TaskAwaitableSignal<TSingleArg>
template<>
struct TaskAwaitableSignal<>
{
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
inline void await_resume() const {
impl::throwIfCancelled();
}
@ -223,8 +224,8 @@ struct TaskAwaitableSignal<>
struct TaskAwaitableSuspend
{
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
inline void await_resume() const {
impl::throwIfCancelled();
}
@ -241,22 +242,22 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
std::shared_ptr<TaskSharedState> sharedState_ = std::make_shared<TaskSharedState>();
TaskLoop* loop_ = nullptr;
constexpr task_t get_return_object() noexcept { return task_t(handle_t::from_promise(*this)); }
constexpr TaskAwaitableSuspend initial_suspend() noexcept { return {}; }
constexpr std::suspend_always final_suspend() noexcept { return {}; }
constexpr task_t get_return_object() MIJIN_NOEXCEPT { return task_t(handle_t::from_promise(*this)); }
constexpr TaskAwaitableSuspend initial_suspend() MIJIN_NOEXCEPT { return {}; }
constexpr std::suspend_always final_suspend() noexcept { return {}; } // note: this must always be noexcept, no matter what
// template<typename TValue>
// constexpr std::suspend_always yield_value(TValue value) noexcept {
// constexpr std::suspend_always yield_value(TValue value) MIJIN_NOEXCEPT {
// *state_ = TaskState<result_t>(std::move(value), TaskStatus::YIELDED);
// return {};
// }
// TODO: implement yielding (can't use futures for this)
// constexpr void unhandled_exception() noexcept {}
// constexpr void unhandled_exception() MIJIN_NOEXCEPT {}
template<typename TValue>
auto await_transform(FuturePtr<TValue> future) noexcept
auto await_transform(FuturePtr<TValue> future) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(loop_ != nullptr, "Cannot await future outside of a loop!");
TaskAwaitableFuture<TValue> awaitable{future};
@ -272,7 +273,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
}
template<typename TResultOther>
auto await_transform(TaskBase<TResultOther> task) noexcept
auto await_transform(TaskBase<TResultOther> task) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(loop_ != nullptr, "Cannot await another task outside of a loop!"); // NOLINT(clang-analyzer-core.UndefinedBinaryOperatorResult)
auto future = delayEvaluation<TResultOther>(loop_)->addTask(std::move(task), &sharedState_->subTask); // hackidyhack: delay evaluation of the type of loop_ as it is only forward-declared here
@ -280,7 +281,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
}
template<typename TFirstArg, typename TSecondArg, typename... TArgs>
auto await_transform(Signal<TFirstArg, TSecondArg, TArgs...>& signal) noexcept
auto await_transform(Signal<TFirstArg, TSecondArg, TArgs...>& signal) MIJIN_NOEXCEPT
{
auto data = std::make_shared<std::tuple<TFirstArg, TSecondArg, TArgs...>>();
signal.connect([this, data](TFirstArg arg0, TSecondArg arg1, TArgs... args) mutable
@ -294,7 +295,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
}
template<typename TFirstArg>
auto await_transform(Signal<TFirstArg>& signal) noexcept
auto await_transform(Signal<TFirstArg>& signal) MIJIN_NOEXCEPT
{
auto data = std::make_shared<TFirstArg>();
signal.connect([this, data](TFirstArg arg0) mutable
@ -307,7 +308,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
return awaitable;
}
auto await_transform(Signal<>& signal) noexcept
auto await_transform(Signal<>& signal) MIJIN_NOEXCEPT
{
signal.connect([this]()
{
@ -318,17 +319,17 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
return awaitable;
}
std::suspend_always await_transform(std::suspend_always) noexcept
std::suspend_always await_transform(std::suspend_always) MIJIN_NOEXCEPT
{
state_.status = TaskStatus::SUSPENDED;
return std::suspend_always();
}
std::suspend_never await_transform(std::suspend_never) noexcept {
std::suspend_never await_transform(std::suspend_never) MIJIN_NOEXCEPT {
return std::suspend_never();
}
TaskAwaitableSuspend await_transform(TaskAwaitableSuspend) noexcept
TaskAwaitableSuspend await_transform(TaskAwaitableSuspend) MIJIN_NOEXCEPT
{
state_.status = TaskStatus::SUSPENDED;
return TaskAwaitableSuspend();
@ -352,7 +353,7 @@ public:
private:
handle_t handle_;
public:
constexpr explicit TaskBase(handle_t handle) noexcept : handle_(handle) {
constexpr explicit TaskBase(handle_t handle) MIJIN_NOEXCEPT : handle_(handle) {
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
if (Result<Stacktrace> stacktrace = captureStacktrace(2); stacktrace.isSuccess())
{
@ -361,12 +362,12 @@ public:
#endif
}
TaskBase(const TaskBase&) = delete;
TaskBase(TaskBase&& other) noexcept : handle_(std::exchange(other.handle_, nullptr))
TaskBase(TaskBase&& other) MIJIN_NOEXCEPT : handle_(std::exchange(other.handle_, nullptr))
{}
~TaskBase() noexcept;
~TaskBase() MIJIN_NOEXCEPT;
public:
TaskBase& operator=(const TaskBase&) = delete;
TaskBase& operator=(TaskBase&& other) noexcept
TaskBase& operator=(TaskBase&& other) MIJIN_NOEXCEPT
{
if (handle_) {
handle_.destroy();
@ -376,13 +377,13 @@ public:
}
[[nodiscard]]
constexpr bool operator==(const TaskBase& other) const noexcept { return handle_ == other.handle_; }
constexpr bool operator==(const TaskBase& other) const MIJIN_NOEXCEPT { return handle_ == other.handle_; }
[[nodiscard]]
constexpr bool operator!=(const TaskBase& other) const noexcept { return handle_ != other.handle_; }
constexpr bool operator!=(const TaskBase& other) const MIJIN_NOEXCEPT { return handle_ != other.handle_; }
public:
[[nodiscard]]
constexpr TaskState<TResult>& state() noexcept
constexpr TaskState<TResult>& state() MIJIN_NOEXCEPT
{
return handle_.promise().state_;
}
@ -392,19 +393,19 @@ public:
handle_.resume();
return state();
}
constexpr std::shared_ptr<TaskSharedState>& sharedState() noexcept
constexpr std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT
{
return handle_.promise().sharedState_;
}
private:
[[nodiscard]]
constexpr handle_t handle() const noexcept { return handle_; }
constexpr handle_t handle() const MIJIN_NOEXCEPT { return handle_; }
[[nodiscard]]
constexpr TaskLoop* getLoop() noexcept
constexpr TaskLoop* getLoop() MIJIN_NOEXCEPT
{
return handle_.promise().loop_;
}
constexpr void setLoop(TaskLoop* loop) noexcept
constexpr void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT
{
// MIJIN_ASSERT(handle_.promise().loop_ == nullptr
// || handle_.promise().loop_ == loop
@ -423,14 +424,14 @@ class WrappedTaskBase
public:
virtual ~WrappedTaskBase() = default;
public:
virtual TaskStatus status() noexcept = 0;
virtual std::exception_ptr exception() noexcept = 0;
// virtual std::any result() noexcept = 0;
virtual TaskStatus status() MIJIN_NOEXCEPT = 0;
virtual std::exception_ptr exception() MIJIN_NOEXCEPT = 0;
// virtual std::any result() MIJIN_NOEXCEPT = 0;
virtual void resume() = 0;
virtual void* raw() noexcept = 0;
virtual std::coroutine_handle<> handle() noexcept = 0;
virtual void setLoop(TaskLoop* loop) noexcept = 0;
virtual std::shared_ptr<TaskSharedState>& sharedState() noexcept = 0;
virtual void* raw() MIJIN_NOEXCEPT = 0;
virtual std::coroutine_handle<> handle() MIJIN_NOEXCEPT = 0;
virtual void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT = 0;
virtual std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT = 0;
[[nodiscard]] inline bool canResume() {
const TaskStatus stat = status();
@ -444,16 +445,16 @@ class WrappedTask : public WrappedTaskBase
private:
TTask task_;
public:
constexpr explicit WrappedTask(TTask&& task) noexcept : task_(std::move(task)) {}
constexpr explicit WrappedTask(TTask&& task) MIJIN_NOEXCEPT : task_(std::move(task)) {}
WrappedTask(const WrappedTask&) = delete;
WrappedTask(WrappedTask&&) noexcept = default;
WrappedTask(WrappedTask&&) MIJIN_NOEXCEPT = default;
public:
WrappedTask& operator=(const WrappedTask&) = delete;
WrappedTask& operator=(WrappedTask&&) noexcept = default;
WrappedTask& operator=(WrappedTask&&) MIJIN_NOEXCEPT = default;
public:
TaskStatus status() noexcept override { return task_.state().status; }
std::exception_ptr exception() noexcept override { return task_.state().exception; }
// std::any result() noexcept override
TaskStatus status() MIJIN_NOEXCEPT override { return task_.state().status; }
std::exception_ptr exception() MIJIN_NOEXCEPT override { return task_.state().exception; }
// std::any result() MIJIN_NOEXCEPT
// {
// if constexpr (std::is_same_v<typename TTask::result_t, void>) {
// return {};
@ -463,14 +464,14 @@ public:
// }
// }
void resume() override { task_.resume(); }
void* raw() noexcept override { return &task_; }
std::coroutine_handle<> handle() noexcept override { return task_.handle(); }
void setLoop(TaskLoop* loop) noexcept override { task_.setLoop(loop); }
virtual std::shared_ptr<TaskSharedState>& sharedState() noexcept override { return task_.sharedState(); }
void* raw() MIJIN_NOEXCEPT override { return &task_; }
std::coroutine_handle<> handle() MIJIN_NOEXCEPT override { return task_.handle(); }
void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT override { task_.setLoop(loop); }
virtual std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT override { return task_.sharedState(); }
};
template<typename TTask>
std::unique_ptr<WrappedTask<TTask>> wrapTask(TTask&& task) noexcept
std::unique_ptr<WrappedTask<TTask>> wrapTask(TTask&& task) MIJIN_NOEXCEPT
{
return std::make_unique<WrappedTask<TTask>>(std::forward<TTask>(task));
}
@ -499,29 +500,29 @@ protected:
exception_handler_t uncaughtExceptionHandler_;
public:
TaskLoop() = default;
TaskLoop() MIJIN_NOEXCEPT = default;
TaskLoop(const TaskLoop&) = delete;
TaskLoop(TaskLoop&&) = delete;
virtual ~TaskLoop() = default;
virtual ~TaskLoop() MIJIN_NOEXCEPT = default;
TaskLoop& operator=(const TaskLoop&) = delete;
TaskLoop& operator=(TaskLoop&&) = delete;
void setUncaughtExceptionHandler(exception_handler_t handler) noexcept { uncaughtExceptionHandler_ = std::move(handler); }
void setUncaughtExceptionHandler(exception_handler_t handler) MIJIN_NOEXCEPT { uncaughtExceptionHandler_ = std::move(handler); }
template<typename TResult>
inline FuturePtr<TResult> addTask(TaskBase<TResult> task, TaskHandle* outHandle = nullptr) noexcept;
inline FuturePtr<TResult> addTask(TaskBase<TResult> task, TaskHandle* outHandle = nullptr) MIJIN_NOEXCEPT;
virtual void transferCurrentTask(TaskLoop& otherLoop) noexcept = 0;
virtual void addStoredTask(StoredTask&& storedTask) noexcept = 0;
virtual void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT = 0;
virtual void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT = 0;
[[nodiscard]] static TaskLoop& current() noexcept;
[[nodiscard]] static TaskLoop& current() MIJIN_NOEXCEPT;
protected:
inline TaskStatus tickTask(StoredTask& task);
protected:
static inline TaskLoop*& currentLoopStorage() noexcept;
static inline TaskLoop*& currentLoopStorage() MIJIN_NOEXCEPT;
template<typename TResult>
static inline void setFutureHelper(StoredTask& storedTask) noexcept;
static inline void setFutureHelper(StoredTask& storedTask) MIJIN_NOEXCEPT;
};
template<typename TResult = void>
@ -537,17 +538,17 @@ private:
std::thread::id threadId_;
public: // TaskLoop implementation
void transferCurrentTask(TaskLoop& otherLoop) noexcept override;
void addStoredTask(StoredTask&& storedTask) noexcept override;
void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT override;
void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT override;
public: // public interface
[[nodiscard]] constexpr bool empty() const noexcept { return tasks_.empty() && newTasks_.empty(); }
[[nodiscard]] constexpr std::size_t getNumTasks() const noexcept { return tasks_.size() + newTasks_.size(); }
[[nodiscard]] std::size_t getActiveTasks() const noexcept;
[[nodiscard]] constexpr bool empty() const MIJIN_NOEXCEPT { return tasks_.empty() && newTasks_.empty(); }
[[nodiscard]] constexpr std::size_t getNumTasks() const MIJIN_NOEXCEPT { return tasks_.size() + newTasks_.size(); }
[[nodiscard]] std::size_t getActiveTasks() const MIJIN_NOEXCEPT;
inline CanContinue tick();
inline void runUntilDone(IgnoreWaiting ignoreWaiting = IgnoreWaiting::NO);
inline void cancelAllTasks() noexcept;
[[nodiscard]] inline std::vector<TaskHandle> getAllTasks() const noexcept;
inline void cancelAllTasks() MIJIN_NOEXCEPT;
[[nodiscard]] inline std::vector<TaskHandle> getAllTasks() const MIJIN_NOEXCEPT;
private:
inline void assertCorrectThread() { MIJIN_ASSERT(threadId_ == std::thread::id() || threadId_ == std::this_thread::get_id(), "Unsafe to TaskLoop from different thread!"); }
};
@ -563,8 +564,8 @@ private:
std::vector<std::jthread> workerThreads_;
public: // TaskLoop implementation
void transferCurrentTask(TaskLoop& otherLoop) noexcept override;
void addStoredTask(StoredTask&& storedTask) noexcept override;
void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT override;
void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT override;
public: // public interface
void start(std::size_t numWorkerThreads);
@ -591,7 +592,7 @@ inline void throwIfCancelled()
}
}
void TaskHandle::cancel() const noexcept
void TaskHandle::cancel() const MIJIN_NOEXCEPT
{
if (std::shared_ptr<TaskSharedState> state = state_.lock())
{
@ -601,7 +602,7 @@ void TaskHandle::cancel() const noexcept
}
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
Optional<Stacktrace> TaskHandle::getCreationStack() const noexcept
Optional<Stacktrace> TaskHandle::getCreationStack() const MIJIN_NOEXCEPT
{
if (std::shared_ptr<TaskSharedState> state = state_.lock())
{
@ -612,7 +613,7 @@ Optional<Stacktrace> TaskHandle::getCreationStack() const noexcept
#endif // MIJIN_COROUTINE_ENABLE_DEBUG_INFO
template<typename TResult>
TaskBase<TResult>::~TaskBase() noexcept
TaskBase<TResult>::~TaskBase() MIJIN_NOEXCEPT
{
if (handle_)
{
@ -621,7 +622,7 @@ TaskBase<TResult>::~TaskBase() noexcept
}
template<typename TResult>
inline FuturePtr<TResult> TaskLoop::addTask(TaskBase<TResult> task, TaskHandle* outHandle) noexcept
inline FuturePtr<TResult> TaskLoop::addTask(TaskBase<TResult> task, TaskHandle* outHandle) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!task.getLoop(), "Attempting to add task that already has a loop!");
task.setLoop(this);
@ -685,20 +686,20 @@ inline TaskStatus TaskLoop::tickTask(StoredTask& task)
return status;
}
/* static */ inline auto TaskLoop::current() noexcept -> TaskLoop&
/* static */ inline auto TaskLoop::current() MIJIN_NOEXCEPT -> TaskLoop&
{
MIJIN_ASSERT(currentLoopStorage() != nullptr, "Attempting to fetch current loop while no coroutine is running!");
return *currentLoopStorage();
}
/* static */ auto TaskLoop::currentLoopStorage() noexcept -> TaskLoop*&
/* static */ auto TaskLoop::currentLoopStorage() MIJIN_NOEXCEPT -> TaskLoop*&
{
static thread_local TaskLoop* storage = nullptr;
return storage;
}
template<typename TResult>
/* static */ inline void TaskLoop::setFutureHelper(StoredTask& storedTask) noexcept
/* static */ inline void TaskLoop::setFutureHelper(StoredTask& storedTask) MIJIN_NOEXCEPT
{
TaskBase<TResult>& task = *static_cast<TaskBase<TResult>*>(storedTask.task->raw());
auto future = std::any_cast<FuturePtr<TResult>>(storedTask.resultData);
@ -801,7 +802,7 @@ inline void SimpleTaskLoop::runUntilDone(IgnoreWaiting ignoreWaiting)
}
}
inline void SimpleTaskLoop::cancelAllTasks() noexcept
inline void SimpleTaskLoop::cancelAllTasks() MIJIN_NOEXCEPT
{
for (StoredTask& task : mijin::chain(tasks_, newTasks_))
{
@ -814,7 +815,7 @@ inline void SimpleTaskLoop::cancelAllTasks() noexcept
}
}
inline std::vector<TaskHandle> SimpleTaskLoop::getAllTasks() const noexcept
inline std::vector<TaskHandle> SimpleTaskLoop::getAllTasks() const MIJIN_NOEXCEPT
{
std::vector<TaskHandle> result;
for (const StoredTask& task : mijin::chain(tasks_, newTasks_))
@ -848,7 +849,7 @@ Task<> c_allDone(const TCollection<FuturePtr<TType>, TTemplateArgs...>& futures)
} while (!allDone);
}
[[nodiscard]] inline TaskHandle getCurrentTask() noexcept
[[nodiscard]] inline TaskHandle getCurrentTask() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(impl::gCurrentTask != nullptr, "Attempt to call getCurrentTask() outside of task.");
return TaskHandle(impl::gCurrentTask->task->sharedState());

View File

@ -8,8 +8,9 @@
#include <memory>
#include <type_traits>
#include "./signal.hpp"
#include "../debug/assert.hpp"
#include "../container/optional.hpp"
#include "../debug/assert.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -36,8 +37,8 @@ struct FutureStorage
{
Optional<TValue> value;
void setValue(TValue value_) noexcept { value = std::move(value_); }
[[nodiscard]] TValue& getValue() noexcept { return value.get(); }
void setValue(TValue value_) MIJIN_NOEXCEPT { value = std::move(value_); }
[[nodiscard]] TValue& getValue() MIJIN_NOEXCEPT { return value.get(); }
};
@ -46,8 +47,8 @@ struct FutureStorage
// {
// Optional<TValue*> value;
//
// void setValue(TValue& value_) noexcept { value = &value_; }
// [[nodiscard]] TValue& getValue() const noexcept { return *value.get(); }
// void setValue(TValue& value_) MIJIN_NOEXCEPT { value = &value_; }
// [[nodiscard]] TValue& getValue() const MIJIN_NOEXCEPT { return *value.get(); }
// };
template<>
@ -65,19 +66,19 @@ private:
public:
Future() = default;
Future(const Future&) = delete;
Future(Future&&) noexcept = default;
Future(Future&&) MIJIN_NOEXCEPT = default;
public:
Future& operator=(const Future&) = delete;
Future& operator=(Future&&) noexcept = default;
Future& operator=(Future&&) MIJIN_NOEXCEPT = default;
[[nodiscard]]
constexpr explicit operator bool() const noexcept { return ready(); }
constexpr explicit operator bool() const MIJIN_NOEXCEPT { return ready(); }
[[nodiscard]]
constexpr bool operator!() const noexcept { return !ready(); }
constexpr bool operator!() const MIJIN_NOEXCEPT { return !ready(); }
public: // access
[[nodiscard]]
constexpr decltype(auto) get() noexcept
constexpr decltype(auto) get() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isSet_, "Attempting to get from future that is not ready.");
if constexpr(std::is_same_v<TValue, void>) {
@ -88,7 +89,7 @@ public: // access
}
}
[[nodiscard]]
constexpr decltype(auto) get() const noexcept
constexpr decltype(auto) get() const MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isSet_, "Attempting to get from future that is not ready.");
if constexpr(std::is_same_v<TValue, void>) {
@ -99,20 +100,20 @@ public: // access
}
}
[[nodiscard]]
constexpr bool ready() const noexcept
constexpr bool ready() const MIJIN_NOEXCEPT
{
return isSet_;
}
public: // modification
template<typename TArg> requires (!std::is_same_v<TValue, void>)
constexpr void set(TArg&& value) noexcept
constexpr void set(TArg&& value) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isSet_, "Trying to set a future twice!");
value_.setValue(std::move(value));
isSet_ = true;
sigSet.emit();
}
constexpr void set() noexcept
constexpr void set() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isSet_, "Trying to set a future twice!");
isSet_ = true;

View File

@ -8,6 +8,7 @@
#include <atomic>
#include <optional>
#include <thread>
#include "../internal/common.hpp"
#include "../util/bitarray.hpp"
namespace mijin
@ -37,7 +38,7 @@ private:
std::optional<value_type> message_;
public:
MessageQueueIterator() = default;
explicit MessageQueueIterator(TMessageQueue& queue) noexcept : queue_(&queue) {
explicit MessageQueueIterator(TMessageQueue& queue) MIJIN_NOEXCEPT : queue_(&queue) {
message_ = queue_->tryPop();
}
MessageQueueIterator(const MessageQueueIterator&) = delete;
@ -46,26 +47,26 @@ public:
MessageQueueIterator& operator=(const MessageQueueIterator&) = delete;
MessageQueueIterator& operator=(MessageQueueIterator&&) = default;
bool operator==(const MessageQueueIterator& other) noexcept
bool operator==(const MessageQueueIterator& other) MIJIN_NOEXCEPT
{
return message_.has_value() == other.message_.has_value();
}
bool operator!=(const MessageQueueIterator& other) noexcept
bool operator!=(const MessageQueueIterator& other) MIJIN_NOEXCEPT
{
return !(*this == other);
}
reference operator*() noexcept
reference operator*() MIJIN_NOEXCEPT
{
return message_.value();
}
pointer operator->() noexcept
pointer operator->() MIJIN_NOEXCEPT
{
return &message_.value();
}
MessageQueueIterator& operator++() noexcept
MessageQueueIterator& operator++() MIJIN_NOEXCEPT
{
message_ = queue_->tryPop();
return *this;
@ -86,10 +87,10 @@ private:
public:
MessageQueue() = default;
MessageQueue(const MessageQueue&) = delete;
MessageQueue(MessageQueue&&) noexcept = delete;
MessageQueue(MessageQueue&&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
MessageQueue& operator=(MessageQueue&&) noexcept = delete;
MessageQueue& operator=(MessageQueue&&) = delete;
[[nodiscard]] bool tryPushMaybeMove(TMessage& message);
[[nodiscard]] bool tryPush(TMessage message) {
@ -99,8 +100,8 @@ public:
[[nodiscard]] std::optional<TMessage> tryPop();
[[nodiscard]] TMessage wait();
iterator_t begin() noexcept { return iterator_t(*this); }
iterator_t end() noexcept { return iterator_t(); }
iterator_t begin() MIJIN_NOEXCEPT { return iterator_t(*this); }
iterator_t end() MIJIN_NOEXCEPT { return iterator_t(); }
};
template<typename TRequest, typename TResponse, std::size_t requestBufferSize = 32, std::size_t responseBufferSize = 32>

View File

@ -10,6 +10,7 @@
#include <memory>
#include <mutex>
#include <vector>
#include "../internal/common.hpp"
#include "../util/flag.hpp"
namespace mijin
@ -54,17 +55,17 @@ private:
public:
Signal() = default;
Signal(const Signal&) = delete;
Signal(Signal&&) noexcept = default;
Signal(Signal&&) MIJIN_NOEXCEPT = default;
public:
Signal& operator=(const Signal&) = delete;
Signal& operator=(Signal&&) noexcept = default;
Signal& operator=(Signal&&) MIJIN_NOEXCEPT = default;
public:
template<typename THandler, typename TWeak = void>
inline token_t connect(THandler handler, Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) noexcept;
inline token_t connect(THandler handler, Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) MIJIN_NOEXCEPT;
template<typename TObject, typename TWeak = void>
inline token_t connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) noexcept;
inline void disconnect(token_t token) noexcept;
inline void emit(TArgs&&... args) noexcept;
inline token_t connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) MIJIN_NOEXCEPT;
inline void disconnect(token_t token) MIJIN_NOEXCEPT;
inline void emit(TArgs&&... args) MIJIN_NOEXCEPT;
};
//
@ -73,7 +74,7 @@ public:
template<typename... TArgs>
template<typename THandler, typename TWeak>
inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::weak_ptr<TWeak> referenced) noexcept -> token_t
inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::weak_ptr<TWeak> referenced) MIJIN_NOEXCEPT -> token_t
{
std::lock_guard lock(handlersMutex_);
@ -90,7 +91,7 @@ inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::we
template<typename... TArgs>
template<typename TObject, typename TWeak>
inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot, std::weak_ptr<TWeak> referenced) noexcept -> token_t
inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot, std::weak_ptr<TWeak> referenced) MIJIN_NOEXCEPT -> token_t
{
std::lock_guard lock(handlersMutex_);
@ -109,7 +110,7 @@ inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)
}
template<typename... TArgs>
inline void Signal<TArgs...>::disconnect(token_t token) noexcept
inline void Signal<TArgs...>::disconnect(token_t token) MIJIN_NOEXCEPT
{
std::lock_guard lock(handlersMutex_);
@ -121,7 +122,7 @@ inline void Signal<TArgs...>::disconnect(token_t token) noexcept
}
template<typename... TArgs>
inline void Signal<TArgs...>::emit(TArgs&&... args) noexcept
inline void Signal<TArgs...>::emit(TArgs&&... args) MIJIN_NOEXCEPT
{
std::lock_guard lock(handlersMutex_);

View File

@ -5,6 +5,7 @@
#define MIJIN_ASYNC_TASK_MUTEX_HPP_INCLUDED 1
#include "./coroutine.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -14,13 +15,13 @@ private:
class TaskMutex* mutex_;
public:
explicit TaskMutexLock(class TaskMutex* mutex) noexcept : mutex_(mutex) {}
explicit TaskMutexLock(class TaskMutex* mutex) MIJIN_NOEXCEPT : mutex_(mutex) {}
TaskMutexLock(const TaskMutexLock&) = delete;
TaskMutexLock(TaskMutexLock&& other) noexcept : mutex_(std::exchange(other.mutex_, nullptr)) {}
TaskMutexLock(TaskMutexLock&& other) MIJIN_NOEXCEPT : mutex_(std::exchange(other.mutex_, nullptr)) {}
TaskMutexLock& operator=(const TaskMutexLock&) = delete;
inline TaskMutexLock& operator=(TaskMutexLock&& other) noexcept;
inline ~TaskMutexLock() noexcept;
inline TaskMutexLock& operator=(TaskMutexLock&& other) MIJIN_NOEXCEPT;
inline ~TaskMutexLock() MIJIN_NOEXCEPT;
};
class TaskMutex
@ -37,12 +38,12 @@ public:
locked_ = true;
co_return TaskMutexLock(this);
}
[[nodiscard]] inline bool isLocked() const noexcept { return locked_; }
[[nodiscard]] inline bool isLocked() const MIJIN_NOEXCEPT { return locked_; }
friend class TaskMutexLock;
};
TaskMutexLock::~TaskMutexLock() noexcept
TaskMutexLock::~TaskMutexLock() MIJIN_NOEXCEPT
{
if (mutex_)
{
@ -50,7 +51,7 @@ TaskMutexLock::~TaskMutexLock() noexcept
}
}
TaskMutexLock& TaskMutexLock::operator=(TaskMutexLock&& other) noexcept
TaskMutexLock& TaskMutexLock::operator=(TaskMutexLock&& other) MIJIN_NOEXCEPT
{
if (mutex_)
{

View File

@ -8,6 +8,8 @@
#include <cstdlib>
#include <source_location>
#include "../internal/common.hpp"
#ifdef _WIN32
#pragma comment(lib, "kernel32")
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
@ -139,7 +141,7 @@ constexpr AssertionResult handleAssert(const char* /* condition */,
#ifdef MIJIN_USE_CUSTOM_ERROR_HANDLER
ErrorHandling handleError(const char* message, const std::source_location& location);
#else
inline ErrorHandling handleError(const char* message, const std::source_location& location) noexcept
inline ErrorHandling handleError(const char* message, const std::source_location& location) MIJIN_NOEXCEPT
{
std::puts(message);
std::printf("Function: %s\n", location.function_name());

View File

@ -75,7 +75,7 @@ thread_local backtrace_state* gBacktraceState = nullptr;
// public functions
//
Result<Stacktrace> captureStacktrace(unsigned skipFrames) noexcept
Result<Stacktrace> captureStacktrace(unsigned skipFrames) MIJIN_NOEXCEPT
{
#if MIJIN_USE_LIBBACKTRACE
BacktraceData btData;
@ -104,7 +104,7 @@ Result<Stacktrace> captureStacktrace(unsigned skipFrames) noexcept
#endif // MIJIN_USE_LIBBACKTRACE
}
const Optional<Stacktrace>& getExceptionStacktrace() noexcept
const Optional<Stacktrace>& getExceptionStacktrace() MIJIN_NOEXCEPT
{
return gCurrentExceptionStackTrace;
}

View File

@ -11,6 +11,7 @@
# include <fmt/format.h>
#endif
#include "./symbol_info.hpp"
#include "../internal/common.hpp"
#include "../types/result.hpp"
#include "../util/iterators.hpp"
@ -45,20 +46,20 @@ public:
Stacktrace() = default;
Stacktrace(const Stacktrace&) = default;
Stacktrace(Stacktrace&&) = default;
explicit Stacktrace(std::vector<Stackframe> frames) noexcept : frames_(std::move(frames)) {}
explicit Stacktrace(std::vector<Stackframe> frames) MIJIN_NOEXCEPT : frames_(std::move(frames)) {}
Stacktrace& operator=(const Stacktrace&) = default;
Stacktrace& operator=(Stacktrace&&) = default;
[[nodiscard]] const std::vector<Stackframe>& getFrames() const noexcept { return frames_; }
[[nodiscard]] const std::vector<Stackframe>& getFrames() const MIJIN_NOEXCEPT { return frames_; }
};
//
// public functions
//
[[nodiscard]] Result<Stacktrace> captureStacktrace(unsigned skipFrames = 0) noexcept;
[[nodiscard]] const Optional<Stacktrace>& getExceptionStacktrace() noexcept;
[[nodiscard]] Result<Stacktrace> captureStacktrace(unsigned skipFrames = 0) MIJIN_NOEXCEPT;
[[nodiscard]] const Optional<Stacktrace>& getExceptionStacktrace() MIJIN_NOEXCEPT;
template<typename TStream>
TStream& operator<<(TStream& stream, const Stackframe& stackframe)

View File

@ -0,0 +1,4 @@
#pragma once
#include "./exception.hpp"

View File

@ -0,0 +1,31 @@
#pragma once
#if !defined(MIJIN_INTERNAL_EXCEPTION_HPP_INCLUDED)
#define MIJIN_INTERNAL_EXCEPTION_HPP_INCLUDED 1
#if !defined(MIJIN_WITH_EXCEPTIONS)
#define MIJIN_WITH_EXCEPTIONS 0
#endif
#if MIJIN_WITH_EXCEPTIONS
#error "Maybe someday"
#else
#if defined(MIJIN_TEST_NO_NOEXCEPT) // only use for testing
#define MIJIN_NOEXCEPT
#define MIJIN_THROWS
#define MIJIN_CONDITIONAL_NOEXCEPT(...)
#else
#define MIJIN_NOEXCEPT noexcept
#define MIJIN_THROWS noexcept
#define MIJIN_CONDITIONAL_NOEXCEPT(...) noexcept(__VA_ARGS__)
#endif
#define MIJIN_EXCEPT_CHOOSE(noexceptType, exceptType) noexceptType
#define MIJIN_THROW_OR_RETURN(value, exception) return (value)
#define MIJIN_RETURN_SUCCESS(value) return (value)
#endif
#define MIJIN_ERROR_BOOL MIJIN_EXCEPT_CHOOSE([[nodiscard]] bool, void)
#define MIJIN_THROW_OR_RETURN_STD(value, message) MIJIN_THROW_OR_RETURN(value, std::runtime_error(message))
#endif // !defined(MIJIN_INTERNAL_EXCEPTION_HPP_INCLUDED)

View File

@ -140,7 +140,7 @@ StreamFeatures ProcessStream::getFeatures()
return {};
}
std::string shellEscape(const std::string& arg) noexcept
std::string shellEscape(const std::string& arg) MIJIN_NOEXCEPT
{
std::ostringstream oss;
const bool requiresQuotes = std::any_of(arg.begin(), arg.end(), [&](const char chr) { return std::isspace(chr); });
@ -168,7 +168,7 @@ std::string shellEscape(const std::string& arg) noexcept
return oss.str();
}
std::string makeShellCommand(const std::vector<std::string>& args) noexcept
std::string makeShellCommand(const std::vector<std::string>& args) MIJIN_NOEXCEPT
{
using namespace mijin::pipe;
return args

View File

@ -5,6 +5,7 @@
#include <vector>
#include "./stream.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -35,8 +36,8 @@ public:
StreamFeatures getFeatures() override;
};
[[nodiscard]] std::string shellEscape(const std::string& arg) noexcept;
[[nodiscard]] std::string makeShellCommand(const std::vector<std::string>& args) noexcept;
[[nodiscard]] std::string shellEscape(const std::string& arg) MIJIN_NOEXCEPT;
[[nodiscard]] std::string makeShellCommand(const std::vector<std::string>& args) MIJIN_NOEXCEPT;
StreamError ProcessStream::open(const std::vector<std::string>& args, FileOpenMode mode_)
{

View File

@ -12,6 +12,7 @@
#include <string>
#include "../async/coroutine.hpp"
#include "../container/typeless_buffer.hpp"
#include "../internal/common.hpp"
#include "../types/result.hpp"
#include "../util/exception.hpp"
@ -421,7 +422,7 @@ mijin::Task<StreamError> Stream::c_readAsString(std::basic_string<TChar>& outStr
}
inline const char* errorName(StreamError error) noexcept
inline const char* errorName(StreamError error) MIJIN_NOEXCEPT
{
switch (error)
{

View File

@ -2,6 +2,7 @@
#pragma once
#include "../../detect.hpp"
#include "../../internal/common.hpp"
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
#include <fcntl.h>
@ -18,9 +19,9 @@
namespace mijin::detail
{
#if MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
bool initWSA() noexcept;
StreamError translateWSAError() noexcept;
StreamError translateWinError(DWORD error) noexcept;
StreamError translateWinError() noexcept;
bool initWSA() MIJIN_NOEXCEPT;
StreamError translateWSAError() MIJIN_NOEXCEPT;
StreamError translateWinError(DWORD error) MIJIN_NOEXCEPT;
StreamError translateWinError() MIJIN_NOEXCEPT;
#endif // MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
}// namespace mijin::detail

View File

@ -35,7 +35,7 @@ namespace mijin
namespace
{
inline constexpr std::size_t CONTENT_LENGTH_LIMIT = 100 << 20; // 100MiB
bool parseHTTPVersion(std::string_view version, HTTPVersion& outVersion) noexcept
bool parseHTTPVersion(std::string_view version, HTTPVersion& outVersion) MIJIN_NOEXCEPT
{
std::vector<std::string_view> parts = split(version, ".");
if (parts.size() != 2)
@ -46,7 +46,7 @@ bool parseHTTPVersion(std::string_view version, HTTPVersion& outVersion) noexcep
}
}
Task<StreamResult<HTTPResponse>> HTTPStream::c_request(HTTPRequest request) noexcept
Task<StreamResult<HTTPResponse>> HTTPStream::c_request(HTTPRequest request) MIJIN_NOEXCEPT
{
if (const StreamError error = co_await c_writeRequest(request); error != StreamError::SUCCESS)
{
@ -55,7 +55,7 @@ Task<StreamResult<HTTPResponse>> HTTPStream::c_request(HTTPRequest request) noex
co_return co_await c_readResponse();
}
Task<StreamError> HTTPStream::c_writeRequest(const mijin::HTTPRequest& request) noexcept
Task<StreamError> HTTPStream::c_writeRequest(const mijin::HTTPRequest& request) MIJIN_NOEXCEPT
{
std::map<std::string, std::string> moreHeaders;
if (!request.body.empty())
@ -94,7 +94,7 @@ Task<StreamError> HTTPStream::c_writeRequest(const mijin::HTTPRequest& request)
co_return StreamError::SUCCESS;
}
Task<StreamResult<HTTPResponse>> HTTPStream::c_readResponse() noexcept
Task<StreamResult<HTTPResponse>> HTTPStream::c_readResponse() MIJIN_NOEXCEPT
{
std::string line;
MIJIN_HTTP_READLINE(line);
@ -162,7 +162,7 @@ Task<StreamResult<HTTPResponse>> HTTPStream::c_readResponse() noexcept
}
Task<StreamResult<HTTPResponse>> HTTPClient::c_request(ip_address_t address, std::uint16_t port, bool https,
HTTPRequest request) noexcept
HTTPRequest request) MIJIN_NOEXCEPT
{
std::string hostname;
if (auto it = request.headers.find("host"); it != request.headers.end())
@ -190,7 +190,7 @@ Task<StreamResult<HTTPResponse>> HTTPClient::c_request(ip_address_t address, std
co_return response;
}
Task<StreamResult<HTTPResponse>> HTTPClient::c_request(const URL& url, HTTPRequest request) noexcept
Task<StreamResult<HTTPResponse>> HTTPClient::c_request(const URL& url, HTTPRequest request) MIJIN_NOEXCEPT
{
if (url.getHost().empty())
{
@ -241,7 +241,7 @@ Task<StreamResult<HTTPResponse>> HTTPClient::c_request(const URL& url, HTTPReque
co_return co_await c_request(*ipAddress, port, https, std::move(request));
}
void HTTPClient::disconnect() noexcept
void HTTPClient::disconnect() MIJIN_NOEXCEPT
{
if (socket_ == nullptr)
{
@ -251,7 +251,7 @@ void HTTPClient::disconnect() noexcept
socket_ = nullptr;
}
StreamError HTTPClient::createSocket(ip_address_t address, const std::string& hostname, std::uint16_t port, bool https) noexcept
StreamError HTTPClient::createSocket(ip_address_t address, const std::string& hostname, std::uint16_t port, bool https) MIJIN_NOEXCEPT
{
if (socket_ != nullptr && address == lastIP_ && port == lastPort_ && https == lastWasHttps_)
{
@ -282,6 +282,7 @@ StreamError HTTPClient::createSocket(ip_address_t address, const std::string& ho
sslStream_ = std::move(sslStream);
stream_.construct(*sslStream_);
#else
(void) hostname;
return StreamError::NOT_SUPPORTED;
#endif
}

View File

@ -10,6 +10,7 @@
#include "./socket.hpp"
#include "./url.hpp"
#include "../container/boxed_object.hpp"
#include "../internal/common.hpp"
#include "../io/stream.hpp"
namespace mijin
@ -43,14 +44,14 @@ class HTTPStream
private:
Stream* base_;
public:
HTTPStream(Stream& base) noexcept : base_(&base)
HTTPStream(Stream& base) MIJIN_NOEXCEPT : base_(&base)
{
MIJIN_ASSERT(base_ != nullptr, "Invalid parameter for base.");
}
Task<StreamResult<HTTPResponse>> c_request(HTTPRequest request) noexcept;
Task<StreamResult<HTTPResponse>> c_request(HTTPRequest request) MIJIN_NOEXCEPT;
private:
Task<StreamError> c_writeRequest(const HTTPRequest& request) noexcept;
Task<StreamResult<HTTPResponse>> c_readResponse() noexcept;
Task<StreamError> c_writeRequest(const HTTPRequest& request) MIJIN_NOEXCEPT;
Task<StreamResult<HTTPResponse>> c_readResponse() MIJIN_NOEXCEPT;
};
class HTTPClient
@ -63,12 +64,12 @@ private:
std::uint16_t lastPort_ = 0;
bool lastWasHttps_ = false;
public:
~HTTPClient() noexcept { disconnect(); }
Task<StreamResult<HTTPResponse>> c_request(ip_address_t address, std::uint16_t port, bool https, HTTPRequest request) noexcept;
Task<StreamResult<HTTPResponse>> c_request(const URL& url, HTTPRequest request = {}) noexcept;
void disconnect() noexcept;
~HTTPClient() MIJIN_NOEXCEPT { disconnect(); }
Task<StreamResult<HTTPResponse>> c_request(ip_address_t address, std::uint16_t port, bool https, HTTPRequest request) MIJIN_NOEXCEPT;
Task<StreamResult<HTTPResponse>> c_request(const URL& url, HTTPRequest request = {}) MIJIN_NOEXCEPT;
void disconnect() MIJIN_NOEXCEPT;
private:
StreamError createSocket(ip_address_t address, const std::string& hostname, std::uint16_t port, bool https) noexcept;
StreamError createSocket(ip_address_t address, const std::string& hostname, std::uint16_t port, bool https) MIJIN_NOEXCEPT;
};
}

View File

@ -32,7 +32,7 @@ StreamError translateGAIError(int error)
return StreamError::UNKNOWN_ERROR;
}
StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& handle) noexcept
StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& handle) MIJIN_NOEXCEPT
{
handle.item = {.ar_name = hostname.c_str()};
@ -44,12 +44,12 @@ StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& han
return StreamError::SUCCESS;
}
bool osResolveDone(os_resolve_handle_t& handle) noexcept
bool osResolveDone(os_resolve_handle_t& handle) MIJIN_NOEXCEPT
{
return gai_error(&handle.item) != EAI_INPROGRESS;
}
StreamResult<std::vector<ip_address_t>> osResolveResult(os_resolve_handle_t& handle) noexcept
StreamResult<std::vector<ip_address_t>> osResolveResult(os_resolve_handle_t& handle) MIJIN_NOEXCEPT
{
if (const int error = gai_error(&handle.item); error != 0)
{
@ -112,7 +112,7 @@ struct WSAQueryContext
};
using os_resolve_handle_t = WSAQueryContext;
void WINAPI getAddrComplete(DWORD error, DWORD bytes, LPOVERLAPPED overlapped) noexcept
void WINAPI getAddrComplete(DWORD error, DWORD bytes, LPOVERLAPPED overlapped) MIJIN_NOEXCEPT
{
(void) bytes;
@ -153,7 +153,7 @@ void WINAPI getAddrComplete(DWORD error, DWORD bytes, LPOVERLAPPED overlapped) n
queryContext.result = std::move(resultAddresses);
}
StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& queryContext) noexcept
StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& queryContext) MIJIN_NOEXCEPT
{
if (!detail::initWSA())
{
@ -181,12 +181,12 @@ StreamError osBeginResolve(const std::string& hostname, os_resolve_handle_t& que
return StreamError::SUCCESS;
}
bool osResolveDone(os_resolve_handle_t& queryContext) noexcept
bool osResolveDone(os_resolve_handle_t& queryContext) MIJIN_NOEXCEPT
{
return !queryContext.result.isEmpty();
}
StreamResult<std::vector<ip_address_t>> osResolveResult(os_resolve_handle_t& queryContext) noexcept
StreamResult<std::vector<ip_address_t>> osResolveResult(os_resolve_handle_t& queryContext) MIJIN_NOEXCEPT
{
return queryContext.result;
}
@ -204,7 +204,7 @@ std::string IPv6Address::toString() const
hextets[5], hextets[6], hextets[7]);
}
Optional<IPv4Address> IPv4Address::fromString(std::string_view stringView) noexcept
Optional<IPv4Address> IPv4Address::fromString(std::string_view stringView) MIJIN_NOEXCEPT
{
std::vector<std::string_view> parts = split(stringView, ".", {.limitParts = 4});
if (parts.size() != 4) {
@ -221,7 +221,7 @@ Optional<IPv4Address> IPv4Address::fromString(std::string_view stringView) noexc
return address;
}
Optional<IPv6Address> IPv6Address::fromString(std::string_view stringView) noexcept
Optional<IPv6Address> IPv6Address::fromString(std::string_view stringView) MIJIN_NOEXCEPT
{
// very specific edge case
if (stringView.contains(":::"))
@ -275,7 +275,7 @@ Optional<IPv6Address> IPv6Address::fromString(std::string_view stringView) noexc
return address;
}
Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string hostname) noexcept
Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string hostname) MIJIN_NOEXCEPT
{
os_resolve_handle_t resolveHandle;
if (StreamError error = osBeginResolve(hostname, resolveHandle); error != StreamError::SUCCESS)

View File

@ -7,6 +7,7 @@
#include <variant>
#include "../async/coroutine.hpp"
#include "../container/optional.hpp"
#include "../internal/common.hpp"
#include "../io/stream.hpp" // TODO: rename Stream{Error,Result} to IO{*}
namespace mijin
@ -15,29 +16,29 @@ struct IPv4Address
{
std::array<std::uint8_t, 4> octets;
auto operator<=>(const IPv4Address&) const noexcept = default;
auto operator<=>(const IPv4Address&) const MIJIN_NOEXCEPT = default;
[[nodiscard]] std::string toString() const;
[[nodiscard]]
static Optional<IPv4Address> fromString(std::string_view stringView) noexcept;
static Optional<IPv4Address> fromString(std::string_view stringView) MIJIN_NOEXCEPT;
};
struct IPv6Address
{
std::array<std::uint16_t, 8> hextets;
auto operator<=>(const IPv6Address&) const noexcept = default;
auto operator<=>(const IPv6Address&) const MIJIN_NOEXCEPT = default;
[[nodiscard]] std::string toString() const;
[[nodiscard]]
static Optional<IPv6Address> fromString(std::string_view stringView) noexcept;
static Optional<IPv6Address> fromString(std::string_view stringView) MIJIN_NOEXCEPT;
};
using ip_address_t = std::variant<IPv4Address, IPv6Address>;
[[nodiscard]]
inline std::string ipAddressToString(const ip_address_t& address) noexcept
inline std::string ipAddressToString(const ip_address_t& address) MIJIN_NOEXCEPT
{
if (address.valueless_by_exception())
{
@ -47,7 +48,7 @@ inline std::string ipAddressToString(const ip_address_t& address) noexcept
}
[[nodiscard]]
inline Optional<ip_address_t> ipAddressFromString(std::string_view stringView) noexcept
inline Optional<ip_address_t> ipAddressFromString(std::string_view stringView) MIJIN_NOEXCEPT
{
if (Optional<IPv4Address> ipv4Address = IPv4Address::fromString(stringView); !ipv4Address.empty())
{
@ -61,16 +62,16 @@ inline Optional<ip_address_t> ipAddressFromString(std::string_view stringView) n
}
[[nodiscard]]
Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string hostname) noexcept;
Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string hostname) MIJIN_NOEXCEPT;
[[nodiscard]]
inline Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string_view hostname) noexcept
inline Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(std::string_view hostname) MIJIN_NOEXCEPT
{
return c_resolveHostname(std::string(hostname.begin(), hostname.end()));
}
[[nodiscard]]
inline Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(const char* hostname) noexcept
inline Task<StreamResult<std::vector<ip_address_t>>> c_resolveHostname(const char* hostname) MIJIN_NOEXCEPT
{
return c_resolveHostname(std::string(hostname));
}

View File

@ -13,6 +13,7 @@
#include <openssl/x509_vfy.h>
#include "../debug/assert.hpp"
#include "../internal/common.hpp"
#include "../types/result.hpp"
namespace ossl
@ -34,10 +35,10 @@ struct [[nodiscard]] Error
std::vector<ErrorFrame> frames;
[[nodiscard]]
bool isSuccess() const noexcept { return sslError == SSL_ERROR_NONE; }
bool isSuccess() const MIJIN_NOEXCEPT { return sslError == SSL_ERROR_NONE; }
static inline Error current(int sslError = -1) noexcept;
static inline Error current(SSL* handle, int result) noexcept { return current(SSL_get_error(handle, result)); }
static inline Error current(int sslError = -1) MIJIN_NOEXCEPT;
static inline Error current(SSL* handle, int result) MIJIN_NOEXCEPT { return current(SSL_get_error(handle, result)); }
};
template<typename TSuccess>
using Result = mijin::ResultBase<TSuccess, Error>;
@ -53,24 +54,24 @@ protected:
THandle handle_ = nullptr;
protected:
explicit Base(THandle handle) noexcept : handle_(handle) {}
explicit Base(THandle handle) MIJIN_NOEXCEPT : handle_(handle) {}
public:
Base() noexcept = default;
Base(const Base& other) noexcept : handle_(other.handle_)
Base() MIJIN_NOEXCEPT = default;
Base(const Base& other) MIJIN_NOEXCEPT : handle_(other.handle_)
{
if (handle_)
{
TActual::upReferences(handle_);
}
}
Base(Base&& other) noexcept : handle_(std::exchange(other.handle_, {})) {}
Base(Base&& other) MIJIN_NOEXCEPT : handle_(std::exchange(other.handle_, {})) {}
~Base() noexcept
~Base() MIJIN_NOEXCEPT
{
static_cast<TActual&>(*this).free();
}
TActual& operator=(const Base& other) noexcept
TActual& operator=(const Base& other) MIJIN_NOEXCEPT
{
if (this == &other)
{
@ -85,7 +86,7 @@ public:
return static_cast<TActual&>(*this);
}
TActual& operator=(Base&& other) noexcept
TActual& operator=(Base&& other) MIJIN_NOEXCEPT
{
if (this == &other)
{
@ -95,22 +96,22 @@ public:
handle_ = std::exchange(other.handle_, {});
return static_cast<TActual&>(*this);
}
auto operator<=>(const Base&) const noexcept = default;
operator bool() const noexcept { return static_cast<bool>(handle_); }
bool operator!() const noexcept { return !static_cast<bool>(handle_); }
auto operator<=>(const Base&) const MIJIN_NOEXCEPT = default;
operator bool() const MIJIN_NOEXCEPT { return static_cast<bool>(handle_); }
bool operator!() const MIJIN_NOEXCEPT { return !static_cast<bool>(handle_); }
[[nodiscard]]
THandle getHandle() const noexcept { return handle_; }
THandle getHandle() const MIJIN_NOEXCEPT { return handle_; }
[[nodiscard]]
THandle releaseHandle() noexcept { return std::exchange(handle_, nullptr); }
THandle releaseHandle() MIJIN_NOEXCEPT { return std::exchange(handle_, nullptr); }
};
class X509Store : public Base<X509Store, X509_STORE*>
{
public:
using Base::Base;
Error create() noexcept
Error create() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(handle_ == nullptr, "X509 Store already created.");
ERR_clear_error();
@ -122,7 +123,7 @@ public:
return {};
}
void free() noexcept
void free() MIJIN_NOEXCEPT
{
if (handle_ != nullptr)
{
@ -131,7 +132,7 @@ public:
}
}
Error loadFile(const char* file) const noexcept
Error loadFile(const char* file) const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (!X509_STORE_load_file(handle_, file))
@ -141,7 +142,7 @@ public:
return {};
}
static void upReferences(X509_STORE* handle) noexcept
static void upReferences(X509_STORE* handle) MIJIN_NOEXCEPT
{
X509_STORE_up_ref(handle);
}
@ -150,7 +151,7 @@ public:
class Context : public Base<Context, SSL_CTX*>
{
public:
Error create(const SSL_METHOD* method) noexcept
Error create(const SSL_METHOD* method) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(handle_ == nullptr, "Context already created.");
ERR_clear_error();
@ -162,7 +163,7 @@ public:
return {};
}
void free() noexcept
void free() MIJIN_NOEXCEPT
{
if (handle_ == nullptr)
{
@ -172,17 +173,17 @@ public:
handle_ = nullptr;
}
void setVerify(int mode, verify_callback_t callback = nullptr) const noexcept
void setVerify(int mode, verify_callback_t callback = nullptr) const MIJIN_NOEXCEPT
{
SSL_CTX_set_verify(handle_, mode, callback);
}
void setCertStore(X509Store store) const noexcept
void setCertStore(X509Store store) const MIJIN_NOEXCEPT
{
SSL_CTX_set_cert_store(handle_, store.releaseHandle());
}
Error setMinProtoVersion(int version) const noexcept
Error setMinProtoVersion(int version) const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (!SSL_CTX_set_min_proto_version(handle_, version))
@ -192,7 +193,7 @@ public:
return {};
}
static void upReferences(SSL_CTX* handle) noexcept
static void upReferences(SSL_CTX* handle) MIJIN_NOEXCEPT
{
SSL_CTX_up_ref(handle);
}
@ -201,7 +202,7 @@ public:
class Bio : public Base<Bio, BIO*>
{
public:
Error createPair(Bio& otherBio, std::size_t writeBuf = 0, std::size_t otherWriteBuf = 0) noexcept
Error createPair(Bio& otherBio, std::size_t writeBuf = 0, std::size_t otherWriteBuf = 0) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(handle_ == nullptr, "Ssl already created.");
MIJIN_ASSERT(otherBio.handle_ == nullptr, "Ssl already created.");
@ -213,7 +214,7 @@ public:
return {};
}
void free() noexcept
void free() MIJIN_NOEXCEPT
{
if (handle_ == nullptr)
{
@ -224,18 +225,18 @@ public:
}
[[nodiscard]]
std::size_t ctrlPending() const noexcept
std::size_t ctrlPending() const MIJIN_NOEXCEPT
{
return BIO_ctrl_pending(handle_);
}
[[nodiscard]]
std::size_t ctrlWPending() const noexcept
std::size_t ctrlWPending() const MIJIN_NOEXCEPT
{
return BIO_ctrl_wpending(handle_);
}
Result<int> write(const void* data, int length) const noexcept
Result<int> write(const void* data, int length) const MIJIN_NOEXCEPT
{
ERR_clear_error();
const int result = BIO_write(handle_, data, length);
@ -246,7 +247,7 @@ public:
return result;
}
Result<int> read(void* data, int length) const noexcept
Result<int> read(void* data, int length) const MIJIN_NOEXCEPT
{
ERR_clear_error();
const int result = BIO_read(handle_, data, length);
@ -258,24 +259,24 @@ public:
}
[[nodiscard]]
int getReadRequest() const noexcept
int getReadRequest() const MIJIN_NOEXCEPT
{
return BIO_get_read_request(handle_);
}
[[nodiscard]]
int getWriteGuarantee() const noexcept
int getWriteGuarantee() const MIJIN_NOEXCEPT
{
return BIO_get_write_guarantee(handle_);
}
[[nodiscard]]
int getWritePending() const noexcept
int getWritePending() const MIJIN_NOEXCEPT
{
return BIO_wpending(handle_);
}
Error flush() const noexcept
Error flush() const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (!BIO_flush(handle_))
@ -285,7 +286,7 @@ public:
return {};
}
static void upReferences(BIO* handle) noexcept
static void upReferences(BIO* handle) MIJIN_NOEXCEPT
{
BIO_up_ref(handle);
}
@ -294,7 +295,7 @@ public:
class Ssl : public Base<Ssl, SSL*>
{
public:
Error create(const Context& context) noexcept
Error create(const Context& context) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(handle_ == nullptr, "Ssl already created.");
ERR_clear_error();
@ -306,7 +307,7 @@ public:
return {};
}
void free() noexcept
void free() MIJIN_NOEXCEPT
{
if (handle_ == nullptr)
{
@ -316,18 +317,18 @@ public:
handle_ = nullptr;
}
void setBio(Bio readBio, Bio writeBio) const noexcept
void setBio(Bio readBio, Bio writeBio) const MIJIN_NOEXCEPT
{
SSL_set_bio(handle_, readBio.releaseHandle(), writeBio.releaseHandle());
}
void setBio(Bio&& bio) const noexcept
void setBio(Bio&& bio) const MIJIN_NOEXCEPT
{
BIO* bioHandle = bio.releaseHandle();
SSL_set_bio(handle_, bioHandle, bioHandle);
}
Error setTLSExtHostname(const char* hostname) const noexcept
Error setTLSExtHostname(const char* hostname) const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (const int result = SSL_set_tlsext_host_name(handle_, hostname); result != 1)
@ -337,7 +338,7 @@ public:
return {};
}
Error setHost(const char* hostname) const noexcept
Error setHost(const char* hostname) const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (const int result = SSL_set1_host(handle_, hostname); result != 1)
@ -347,7 +348,7 @@ public:
return {};
}
Error connect() const noexcept
Error connect() const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (const int result = SSL_connect(handle_); result != 1)
@ -357,7 +358,7 @@ public:
return {};
}
Error shutdown() const noexcept
Error shutdown() const MIJIN_NOEXCEPT
{
ERR_clear_error();
if (const int result = SSL_shutdown(handle_); result != 1)
@ -372,12 +373,12 @@ public:
}
[[nodiscard]]
long getVerifyResult() const noexcept
long getVerifyResult() const MIJIN_NOEXCEPT
{
return SSL_get_verify_result(handle_);
}
Result<int> write(const void* data, int length) const noexcept
Result<int> write(const void* data, int length) const MIJIN_NOEXCEPT
{
ERR_clear_error();
const int result = SSL_write(handle_, data, length);
@ -388,7 +389,7 @@ public:
return result;
}
Result<int> read(void* data, int length) const noexcept
Result<int> read(void* data, int length) const MIJIN_NOEXCEPT
{
ERR_clear_error();
const int result = SSL_read(handle_, data, length);
@ -400,18 +401,18 @@ public:
}
[[nodiscard]]
int pending() const noexcept
int pending() const MIJIN_NOEXCEPT
{
return SSL_pending(handle_);
}
static void upReferences(SSL* handle) noexcept
static void upReferences(SSL* handle) MIJIN_NOEXCEPT
{
SSL_up_ref(handle);
}
};
Error Error::current(int sslError_) noexcept
Error Error::current(int sslError_) MIJIN_NOEXCEPT
{
Error error = {
.sslError = sslError_

View File

@ -3,6 +3,7 @@
#include "./detail/net_common.hpp"
#include "../detect.hpp"
#include "../internal/common.hpp"
#include "../util/variant.hpp"
namespace mijin
@ -10,7 +11,7 @@ namespace mijin
namespace
{
inline constexpr int LISTEN_BACKLOG = 3;
StreamError translateErrno() noexcept
StreamError translateErrno() MIJIN_NOEXCEPT
{
switch (errno)
{
@ -30,7 +31,7 @@ int readFlags(const ReadOptions& options)
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
const int SOCKOPT_ONE = 1;
bool appendSocketFlags(int handle, int flags) noexcept
bool appendSocketFlags(int handle, int flags) MIJIN_NOEXCEPT
{
const int currentFlags = fcntl(handle, F_GETFL);
if (currentFlags < 0)
@ -40,7 +41,7 @@ bool appendSocketFlags(int handle, int flags) noexcept
return fcntl(handle, F_SETFL, currentFlags | flags) >= 0;
}
bool removeSocketFlags(int handle, int flags) noexcept
bool removeSocketFlags(int handle, int flags) MIJIN_NOEXCEPT
{
const int currentFlags = fcntl(handle, F_GETFL);
if (currentFlags < 0)
@ -50,32 +51,32 @@ bool removeSocketFlags(int handle, int flags) noexcept
return fcntl(handle, F_SETFL, currentFlags & ~flags) >= 0;
}
long osRecv(int socket, std::span<std::uint8_t> buffer, int flags)
long osRecv(int socket, std::span<std::uint8_t> buffer, int flags) MIJIN_NOEXCEPT
{
return static_cast<long>(recv(socket, buffer.data(), buffer.size(), flags));
}
long osSend(int socket, std::span<const std::uint8_t> buffer, int flags)
long osSend(int socket, std::span<const std::uint8_t> buffer, int flags) MIJIN_NOEXCEPT
{
return static_cast<long>(send(socket, buffer.data(), buffer.size(), flags));
}
int osCreateSocket(int domain, int type, int protocol)
int osCreateSocket(int domain, int type, int protocol) MIJIN_NOEXCEPT
{
return socket(domain, type, protocol);
}
int osCloseSocket(int socket)
int osCloseSocket(int socket) MIJIN_NOEXCEPT
{
return ::close(socket);
}
bool osIsSocketValid(int socket)
bool osIsSocketValid(int socket) MIJIN_NOEXCEPT
{
return socket >= 0;
}
bool osSetSocketNonBlocking(int socket, bool blocking)
bool osSetSocketNonBlocking(int socket, bool blocking) MIJIN_NOEXCEPT
{
if (blocking)
{
@ -95,7 +96,7 @@ thread_local bool gWsaInited = false;
class WSAGuard
{
public:
~WSAGuard() noexcept
~WSAGuard() MIJIN_NOEXCEPT
{
if (gWsaInited)
{
@ -104,17 +105,17 @@ public:
}
} thread_local [[maybe_unused]] gWsaGuard;
long osRecv(SOCKET socket, std::span<std::uint8_t> buffer, int flags)
long osRecv(SOCKET socket, std::span<std::uint8_t> buffer, int flags) MIJIN_NOEXCEPT
{
return recv(socket, reinterpret_cast<char*>(buffer.data()), static_cast<int>(buffer.size()), flags);
}
long osSend(SOCKET socket, std::span<const std::uint8_t> buffer, int flags)
long osSend(SOCKET socket, std::span<const std::uint8_t> buffer, int flags) MIJIN_NOEXCEPT
{
return send(socket, reinterpret_cast<const char*>(buffer.data()), static_cast<int>(buffer.size()), flags);
}
SOCKET osCreateSocket(int addressFamily, int type, int protocol)
SOCKET osCreateSocket(int addressFamily, int type, int protocol) MIJIN_NOEXCEPT
{
if (!detail::initWSA())
{
@ -123,17 +124,17 @@ SOCKET osCreateSocket(int addressFamily, int type, int protocol)
return socket(addressFamily, type, protocol);
}
int osCloseSocket(SOCKET socket)
int osCloseSocket(SOCKET socket) MIJIN_NOEXCEPT
{
return closesocket(socket);
}
bool osIsSocketValid(SOCKET socket)
bool osIsSocketValid(SOCKET socket) MIJIN_NOEXCEPT
{
return socket != INVALID_SOCKET;
}
bool osSetSocketNonBlocking(SOCKET socket, bool blocking)
bool osSetSocketNonBlocking(SOCKET socket, bool blocking) MIJIN_NOEXCEPT
{
u_long value = blocking ? 0 : 1;
return ioctlsocket(socket, FIONBIO, &value) == NO_ERROR;
@ -144,7 +145,7 @@ bool osSetSocketNonBlocking(SOCKET socket, bool blocking)
namespace detail
{
#if MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
bool initWSA() noexcept
bool initWSA() MIJIN_NOEXCEPT
{
if (gWsaInited)
{
@ -160,20 +161,20 @@ bool initWSA() noexcept
return true;
}
StreamError translateWSAError() noexcept
StreamError translateWSAError() MIJIN_NOEXCEPT
{
// TODO
return StreamError::UNKNOWN_ERROR;
}
StreamError translateWinError(DWORD error) noexcept
StreamError translateWinError(DWORD error) MIJIN_NOEXCEPT
{
// TODO
(void) error;
return StreamError::UNKNOWN_ERROR;
}
StreamError translateWinError() noexcept
StreamError translateWinError() MIJIN_NOEXCEPT
{
return translateWinError(GetLastError());
}
@ -327,7 +328,7 @@ StreamFeatures TCPStream::getFeatures()
};
}
StreamError TCPStream::open(ip_address_t address, std::uint16_t port) noexcept
StreamError TCPStream::open(ip_address_t address, std::uint16_t port) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isOpen(), "Socket is already open.");
@ -375,19 +376,19 @@ StreamError TCPStream::open(ip_address_t address, std::uint16_t port) noexcept
return StreamError::SUCCESS;
}
void TCPStream::close() noexcept
void TCPStream::close() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isOpen(), "Socket is not open.");
osCloseSocket(handle_);
handle_ = INVALID_SOCKET_HANDLE;
}
TCPStream& TCPSocket::getStream() noexcept
TCPStream& TCPSocket::getStream() MIJIN_NOEXCEPT
{
return stream_;
}
StreamError TCPServerSocket::setup(ip_address_t address, std::uint16_t port) noexcept
StreamError TCPServerSocket::setup(ip_address_t address, std::uint16_t port) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isListening(), "Socket is already listening.");
@ -440,7 +441,7 @@ StreamError TCPServerSocket::setup(ip_address_t address, std::uint16_t port) noe
return StreamError::SUCCESS;
}
void TCPServerSocket::close() noexcept
void TCPServerSocket::close() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isListening(), "Socket is not listening.");
@ -448,7 +449,7 @@ void TCPServerSocket::close() noexcept
handle_ = INVALID_SOCKET_HANDLE;
}
Task<StreamResult<std::unique_ptr<Socket>>> TCPServerSocket::c_waitForConnection() noexcept
Task<StreamResult<std::unique_ptr<Socket>>> TCPServerSocket::c_waitForConnection() MIJIN_NOEXCEPT
{
while (isListening())
{

View File

@ -30,32 +30,32 @@ inline constexpr socket_handle_t INVALID_SOCKET_HANDLE = -1;
class Socket
{
protected:
Socket() noexcept = default;
Socket(const Socket&) noexcept = default;
Socket(Socket&&) noexcept = default;
Socket() MIJIN_NOEXCEPT = default;
Socket(const Socket&) MIJIN_NOEXCEPT = default;
Socket(Socket&&) MIJIN_NOEXCEPT = default;
Socket& operator=(const Socket&) noexcept = default;
Socket& operator=(Socket&&) noexcept = default;
Socket& operator=(const Socket&) MIJIN_NOEXCEPT = default;
Socket& operator=(Socket&&) MIJIN_NOEXCEPT = default;
public:
virtual ~Socket() noexcept = default;
virtual ~Socket() MIJIN_NOEXCEPT = default;
virtual Stream& getStream() noexcept = 0;
virtual Stream& getStream() MIJIN_NOEXCEPT = 0;
};
class ServerSocket
{
protected:
ServerSocket() noexcept = default;
ServerSocket(const ServerSocket&) noexcept = default;
ServerSocket(ServerSocket&&) noexcept = default;
ServerSocket() MIJIN_NOEXCEPT = default;
ServerSocket(const ServerSocket&) MIJIN_NOEXCEPT = default;
ServerSocket(ServerSocket&&) MIJIN_NOEXCEPT = default;
ServerSocket& operator=(const ServerSocket&) noexcept = default;
ServerSocket& operator=(ServerSocket&&) noexcept = default;
ServerSocket& operator=(const ServerSocket&) MIJIN_NOEXCEPT = default;
ServerSocket& operator=(ServerSocket&&) MIJIN_NOEXCEPT = default;
public:
virtual ~ServerSocket() noexcept = default;
virtual ~ServerSocket() MIJIN_NOEXCEPT = default;
virtual void close() noexcept = 0;
virtual Task<StreamResult<std::unique_ptr<Socket>>> c_waitForConnection() noexcept = 0;
virtual void close() MIJIN_NOEXCEPT = 0;
virtual Task<StreamResult<std::unique_ptr<Socket>>> c_waitForConnection() MIJIN_NOEXCEPT = 0;
};
class TCPStream : public Stream
@ -74,9 +74,9 @@ public:
bool isAtEnd() override;
StreamFeatures getFeatures() override;
StreamError open(ip_address_t address, std::uint16_t port) noexcept;
void close() noexcept;
[[nodiscard]] bool isOpen() const noexcept { return handle_ != INVALID_SOCKET_HANDLE; }
StreamError open(ip_address_t address, std::uint16_t port) MIJIN_NOEXCEPT;
void close() MIJIN_NOEXCEPT;
[[nodiscard]] bool isOpen() const MIJIN_NOEXCEPT { return handle_ != INVALID_SOCKET_HANDLE; }
private:
void setNoblock(bool async);
@ -88,10 +88,10 @@ class TCPSocket : public Socket
private:
TCPStream stream_;
public:
TCPStream& getStream() noexcept override;
TCPStream& getStream() MIJIN_NOEXCEPT override;
StreamError open(ip_address_t address, std::uint16_t port) noexcept { return stream_.open(address, port); }
StreamError open(std::string_view addressText, std::uint16_t port) noexcept
StreamError open(ip_address_t address, std::uint16_t port) MIJIN_NOEXCEPT { return stream_.open(address, port); }
StreamError open(std::string_view addressText, std::uint16_t port) MIJIN_NOEXCEPT
{
if (Optional<ip_address_t> address = ipAddressFromString(addressText); !address.empty())
{
@ -99,8 +99,8 @@ public:
}
return StreamError::UNKNOWN_ERROR;
}
void close() noexcept { stream_.close(); }
[[nodiscard]] bool isOpen() const noexcept { return stream_.isOpen(); }
void close() MIJIN_NOEXCEPT { stream_.close(); }
[[nodiscard]] bool isOpen() const MIJIN_NOEXCEPT { return stream_.isOpen(); }
friend class TCPServerSocket;
};
@ -110,8 +110,8 @@ class TCPServerSocket : public ServerSocket
private:
socket_handle_t handle_ = INVALID_SOCKET_HANDLE;
public:
StreamError setup(ip_address_t address, std::uint16_t port) noexcept;
StreamError setup(std::string_view addressText, std::uint16_t port) noexcept
StreamError setup(ip_address_t address, std::uint16_t port) MIJIN_NOEXCEPT;
StreamError setup(std::string_view addressText, std::uint16_t port) MIJIN_NOEXCEPT
{
if (Optional<ip_address_t> address = ipAddressFromString(addressText); !address.empty())
{
@ -119,10 +119,10 @@ public:
}
return StreamError::UNKNOWN_ERROR;
}
void close() noexcept override;
[[nodiscard]] bool isListening() const noexcept { return handle_ >= 0; }
void close() MIJIN_NOEXCEPT override;
[[nodiscard]] bool isListening() const MIJIN_NOEXCEPT { return handle_ >= 0; }
Task<StreamResult<std::unique_ptr<Socket>>> c_waitForConnection() noexcept override;
Task<StreamResult<std::unique_ptr<Socket>>> c_waitForConnection() MIJIN_NOEXCEPT override;
};
}

View File

@ -9,7 +9,7 @@ namespace mijin
namespace
{
inline constexpr int BIO_BUFFER_SIZE = 4096;
ossl::Result<ossl::Context*> getSSLContext() noexcept
ossl::Result<ossl::Context*> getSSLContext() MIJIN_NOEXCEPT
{
static ossl::Context context;
static std::mutex contextMutex;
@ -52,7 +52,7 @@ ossl::Result<ossl::Context*> getSSLContext() noexcept
}
}
StreamError SSLStream::open(Stream& base, const std::string& hostname) noexcept
StreamError SSLStream::open(Stream& base, const std::string& hostname) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(base_ == nullptr, "SSL stream is already open.");
@ -112,7 +112,7 @@ StreamError SSLStream::open(Stream& base, const std::string& hostname) noexcept
return StreamError::SUCCESS;
}
void SSLStream::close() noexcept
void SSLStream::close() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(base_ != nullptr, "SSL stream is not open.");
base_ = nullptr;
@ -233,7 +233,7 @@ StreamFeatures SSLStream::getFeatures()
};
}
StreamError SSLStream::bioToBase() noexcept
StreamError SSLStream::bioToBase() MIJIN_NOEXCEPT
{
std::array<std::uint8_t, BIO_BUFFER_SIZE> buffer;
std::size_t bytes = std::min(externalBio_.ctrlPending(), buffer.size());
@ -254,7 +254,7 @@ StreamError SSLStream::bioToBase() noexcept
return StreamError::SUCCESS;
}
StreamError SSLStream::baseToBio() noexcept
StreamError SSLStream::baseToBio() MIJIN_NOEXCEPT
{
std::array<std::uint8_t, BIO_BUFFER_SIZE> buffer;
std::size_t toRead = externalBio_.getWriteGuarantee();

View File

@ -11,6 +11,7 @@
#include <memory>
#include "./openssl_wrappers.hpp"
#include "../internal/common.hpp"
#include "../io/stream.hpp"
namespace mijin
@ -22,15 +23,15 @@ private:
ossl::Ssl ssl_;
ossl::Bio externalBio_;
public:
~SSLStream() noexcept override
~SSLStream() MIJIN_NOEXCEPT override
{
if (base_ != nullptr)
{
close();
}
}
StreamError open(Stream& base, const std::string& hostname) noexcept;
void close() noexcept;
StreamError open(Stream& base, const std::string& hostname) MIJIN_NOEXCEPT;
void close() MIJIN_NOEXCEPT;
StreamError readRaw(std::span<std::uint8_t> buffer, const ReadOptions& options, std::size_t* outBytesRead) override;
StreamError writeRaw(std::span<const std::uint8_t> buffer) override;
@ -40,8 +41,8 @@ public:
bool isAtEnd() override;
StreamFeatures getFeatures() override;
private:
StreamError bioToBase() noexcept;
StreamError baseToBio() noexcept;
StreamError bioToBase() MIJIN_NOEXCEPT;
StreamError baseToBio() MIJIN_NOEXCEPT;
template<typename TFunc, typename... TArgs>

View File

@ -7,6 +7,7 @@
#include <cstdint>
#include <string>
#include "../internal/common.hpp"
#include "../util/string.hpp"
namespace mijin
@ -28,37 +29,38 @@ private:
string_view_t pathQueryFragment_;
std::uint16_t port_ = 0;
public:
constexpr URLBase() noexcept = default;
constexpr URLBase() MIJIN_NOEXCEPT = default;
constexpr URLBase(const URLBase&) = default;
constexpr URLBase(URLBase&&) noexcept = default;
constexpr URLBase(string_t base) noexcept : base_(std::move(base)) { parse(); }
constexpr URLBase(URLBase&&) MIJIN_NOEXCEPT = default;
constexpr URLBase(string_t base) MIJIN_NOEXCEPT : base_(std::move(base)) { parse(); }
constexpr URLBase(string_view_t base) : URLBase(string_t(base.begin(), base.end())) {}
constexpr URLBase(const TChar* base) : URLBase(string_t(base)) {}
constexpr URLBase& operator=(const URLBase&) = default;
constexpr URLBase& operator=(URLBase&&) noexcept = default;
constexpr URLBase& operator=(URLBase&&) MIJIN_NOEXCEPT = default;
[[nodiscard]] constexpr bool isValid() const noexcept { return !base_.empty(); }
[[nodiscard]] constexpr string_view_t getScheme() const noexcept { return scheme_; }
[[nodiscard]] constexpr string_view_t getUserInfo() const noexcept { return userinfo_; }
[[nodiscard]] constexpr string_view_t getHost() const noexcept { return host_; }
[[nodiscard]] constexpr string_view_t getPath() const noexcept { return path_; }
[[nodiscard]] constexpr string_view_t getQuery() const noexcept { return query_; }
[[nodiscard]] constexpr string_view_t getFragment() const noexcept { return fragment_; }
[[nodiscard]] constexpr string_view_t getPathQueryFragment() const noexcept { return pathQueryFragment_; }
[[nodiscard]] constexpr std::uint16_t getPort() const noexcept { return port_; }
[[nodiscard]] constexpr bool isValid() const MIJIN_NOEXCEPT { return !base_.empty(); }
[[nodiscard]] constexpr const string_t& getBase() const MIJIN_NOEXCEPT { return base_; }
[[nodiscard]] constexpr string_view_t getScheme() const MIJIN_NOEXCEPT { return scheme_; }
[[nodiscard]] constexpr string_view_t getUserInfo() const MIJIN_NOEXCEPT { return userinfo_; }
[[nodiscard]] constexpr string_view_t getHost() const MIJIN_NOEXCEPT { return host_; }
[[nodiscard]] constexpr string_view_t getPath() const MIJIN_NOEXCEPT { return path_; }
[[nodiscard]] constexpr string_view_t getQuery() const MIJIN_NOEXCEPT { return query_; }
[[nodiscard]] constexpr string_view_t getFragment() const MIJIN_NOEXCEPT { return fragment_; }
[[nodiscard]] constexpr string_view_t getPathQueryFragment() const MIJIN_NOEXCEPT { return pathQueryFragment_; }
[[nodiscard]] constexpr std::uint16_t getPort() const MIJIN_NOEXCEPT { return port_; }
constexpr void clear() noexcept;
constexpr void clear() MIJIN_NOEXCEPT;
private:
constexpr void parse() noexcept;
constexpr bool parseAuthority(string_view_t authority) noexcept;
constexpr void parse() MIJIN_NOEXCEPT;
constexpr bool parseAuthority(string_view_t authority) MIJIN_NOEXCEPT;
};
using URL = URLBase<char>;
template<typename TChar, typename TTraits, typename TAllocator>
constexpr void URLBase<TChar, TTraits, TAllocator>::clear() noexcept
constexpr void URLBase<TChar, TTraits, TAllocator>::clear() MIJIN_NOEXCEPT
{
base_.clear();
scheme_ = {};
@ -71,7 +73,7 @@ constexpr void URLBase<TChar, TTraits, TAllocator>::clear() noexcept
}
template<typename TChar, typename TTraits, typename TAllocator>
constexpr void URLBase<TChar, TTraits, TAllocator>::parse() noexcept
constexpr void URLBase<TChar, TTraits, TAllocator>::parse() MIJIN_NOEXCEPT
{
if (base_.empty())
{
@ -135,7 +137,7 @@ constexpr void URLBase<TChar, TTraits, TAllocator>::parse() noexcept
}
template<typename TChar, typename TTraits, typename TAllocator>
constexpr bool URLBase<TChar, TTraits, TAllocator>::parseAuthority(string_view_t authority) noexcept
constexpr bool URLBase<TChar, TTraits, TAllocator>::parseAuthority(string_view_t authority) MIJIN_NOEXCEPT
{
string_view_t toParse = authority;
typename string_view_t::size_type pos = toParse.find(TChar('@'));

View File

@ -9,6 +9,7 @@
#if __has_include(<fmt/format.h>)
# include <fmt/format.h>
#endif
#include "../internal/common.hpp"
namespace mijin
{
@ -37,8 +38,8 @@ public:
Name& operator=(const Name&) = default;
auto operator<=>(const Name&) const = default;
constexpr operator bool() const noexcept { return id_ != std::numeric_limits<std::size_t>::max(); }
constexpr bool operator!() const noexcept { return !static_cast<bool>(*this); }
constexpr operator bool() const MIJIN_NOEXCEPT { return id_ != std::numeric_limits<std::size_t>::max(); }
constexpr bool operator!() const MIJIN_NOEXCEPT { return !static_cast<bool>(*this); }
[[nodiscard]] std::string_view stringView() const;
[[nodiscard]] const char* c_str() const {
@ -57,7 +58,7 @@ public:
template<>
struct std::hash<mijin::Name> : hash<std::size_t>
{
std::size_t operator()(mijin::Name name) const noexcept {
std::size_t operator()(mijin::Name name) const MIJIN_NOEXCEPT {
return hash<std::size_t>::operator()(name.getID());
}
};

View File

@ -7,6 +7,8 @@
#include <string>
#include <variant>
#include "../internal/common.hpp"
namespace mijin
{
@ -30,32 +32,32 @@ private:
std::variant<Empty, TSuccess, TError> state_;
public:
ResultBase() = default;
ResultBase(const ResultBase&) = default;
ResultBase(ResultBase&&) = default;
ResultBase(TSuccess successValue) noexcept : state_(std::move(successValue)) {}
ResultBase(TError errorValue) noexcept : state_(std::move(errorValue)) {}
ResultBase() MIJIN_NOEXCEPT = default;
ResultBase(const ResultBase&) MIJIN_NOEXCEPT = default;
ResultBase(ResultBase&&) MIJIN_NOEXCEPT = default;
ResultBase(TSuccess successValue) MIJIN_NOEXCEPT : state_(std::move(successValue)) {}
ResultBase(TError errorValue) MIJIN_NOEXCEPT : state_(std::move(errorValue)) {}
ResultBase& operator=(const ResultBase&) = default;
ResultBase& operator=(ResultBase&&) = default;
bool operator==(const ResultBase& other) const noexcept { return state_ == other.state_; }
bool operator!=(const ResultBase& other) const noexcept { return state_ != other.state_; }
operator bool() const noexcept { return isSuccess(); }
bool operator!() const noexcept { return !isSuccess(); }
TSuccess& operator*() noexcept { return getValue(); }
const TSuccess& operator*() const noexcept { return getValue(); }
TSuccess* operator->() noexcept { return &getValue(); }
const TSuccess* operator->() const noexcept { return &getValue(); }
bool operator==(const ResultBase& other) const MIJIN_NOEXCEPT { return state_ == other.state_; }
bool operator!=(const ResultBase& other) const MIJIN_NOEXCEPT { return state_ != other.state_; }
operator bool() const MIJIN_NOEXCEPT { return isSuccess(); }
bool operator!() const MIJIN_NOEXCEPT { return !isSuccess(); }
TSuccess& operator*() MIJIN_NOEXCEPT { return getValue(); }
const TSuccess& operator*() const MIJIN_NOEXCEPT { return getValue(); }
TSuccess* operator->() MIJIN_NOEXCEPT { return &getValue(); }
const TSuccess* operator->() const MIJIN_NOEXCEPT { return &getValue(); }
[[nodiscard]] bool isEmpty() const noexcept { return std::holds_alternative<Empty>(state_); }
[[nodiscard]] bool isSuccess() const noexcept { return std::holds_alternative<TSuccess>(state_); }
[[nodiscard]] bool isError() const noexcept { return std::holds_alternative<TError>(state_); }
[[nodiscard]] bool isEmpty() const MIJIN_NOEXCEPT { return std::holds_alternative<Empty>(state_); }
[[nodiscard]] bool isSuccess() const MIJIN_NOEXCEPT { return std::holds_alternative<TSuccess>(state_); }
[[nodiscard]] bool isError() const MIJIN_NOEXCEPT { return std::holds_alternative<TError>(state_); }
[[nodiscard]] TSuccess& getValue() noexcept { return std::get<TSuccess>(state_); }
[[nodiscard]] TError& getError() noexcept { return std::get<TError>(state_); }
[[nodiscard]] const TSuccess& getValue() const noexcept { return std::get<TSuccess>(state_); }
[[nodiscard]] const TError& getError() const noexcept { return std::get<TError>(state_); }
[[nodiscard]] TSuccess& getValue() MIJIN_NOEXCEPT { return std::get<TSuccess>(state_); }
[[nodiscard]] TError& getError() MIJIN_NOEXCEPT { return std::get<TError>(state_); }
[[nodiscard]] const TSuccess& getValue() const MIJIN_NOEXCEPT { return std::get<TSuccess>(state_); }
[[nodiscard]] const TError& getError() const MIJIN_NOEXCEPT { return std::get<TError>(state_); }
};
struct ResultError
@ -64,11 +66,11 @@ struct ResultError
ResultError() : message("Unknown error") {}
ResultError(const ResultError&) = default;
ResultError(ResultError&&) noexcept = default;
ResultError(std::string msg) noexcept : message(std::move(msg)) {}
ResultError(ResultError&&) MIJIN_NOEXCEPT = default;
ResultError(std::string msg) MIJIN_NOEXCEPT : message(std::move(msg)) {}
ResultError& operator=(const ResultError&) = default;
ResultError& operator=(ResultError&&) noexcept = default;
ResultError& operator=(ResultError&&) MIJIN_NOEXCEPT = default;
};
template<typename TSuccess>

View File

@ -11,6 +11,7 @@
#include <vector>
#include "../container/optional.hpp"
#include "../internal/common.hpp"
#include "../util/traits.hpp"
#include "../util/variant.hpp"
@ -73,14 +74,14 @@ public:
private:
base_t base_ = UndefinedValue();
public:
ScriptValue() noexcept = default;
ScriptValue(const ScriptValue&) noexcept = default;
ScriptValue(ScriptValue&&) noexcept = default;
ScriptValue() MIJIN_NOEXCEPT = default;
ScriptValue(const ScriptValue&) MIJIN_NOEXCEPT = default;
ScriptValue(ScriptValue&&) MIJIN_NOEXCEPT = default;
template<typename TValue>
ScriptValue(TValue&& value);
ScriptValue& operator=(const ScriptValue&) = default;
ScriptValue& operator=(ScriptValue&&) noexcept = default;
ScriptValue& operator=(ScriptValue&&) MIJIN_NOEXCEPT = default;
std::partial_ordering operator<=>(const ScriptValue& other) const = default;
@ -91,7 +92,7 @@ public:
}
[[nodiscard]]
Optional<script_int_t> toInt() const noexcept
Optional<script_int_t> toInt() const MIJIN_NOEXCEPT
{
return visit([&](auto&& value) -> Optional<script_int_t>
{
@ -118,7 +119,7 @@ public:
}
[[nodiscard]]
Optional<script_float_t> toFloat() const noexcept
Optional<script_float_t> toFloat() const MIJIN_NOEXCEPT
{
return visit([&](auto&& value) -> Optional<script_float_t>
{
@ -145,7 +146,7 @@ public:
}
[[nodiscard]]
Optional<std::string> toString() const noexcept
Optional<std::string> toString() const MIJIN_NOEXCEPT
{
return visit([](auto&& value) -> Optional<std::string>
{
@ -175,7 +176,7 @@ public:
template<typename T>
[[nodiscard]]
Optional<std::decay_t<T>> to() const noexcept
Optional<std::decay_t<T>> to() const MIJIN_NOEXCEPT
{
using type_t = std::decay_t<T>;
if constexpr (std::is_same_v<type_t, script_int_t>)

View File

@ -5,6 +5,7 @@
#define MIJIN_TYPES_TYPEDEF_HPP_INCLUDED 1
#include <utility>
#include "../internal/common.hpp"
namespace mijin
{
@ -48,9 +49,9 @@ public:
return *this;
}
explicit constexpr operator const TBase&() const noexcept { return value; }
explicit constexpr operator TBase&() noexcept { return value; }
auto operator<=>(const TypeDef&) const noexcept = default;
explicit constexpr operator const TBase&() const MIJIN_NOEXCEPT { return value; }
explicit constexpr operator TBase&() MIJIN_NOEXCEPT { return value; }
auto operator<=>(const TypeDef&) const MIJIN_NOEXCEPT = default;
};
template<typename TBase, typename TTag> requires (!std::is_fundamental_v<TBase>)

View File

@ -4,10 +4,12 @@
#if !defined(MIJIN_UTIL_ALIGN_HPP_INCLUDED)
#define MIJIN_UTIL_ALIGN_HPP_INCLUDED 1
#include "../internal/common.hpp"
namespace mijin
{
template<typename T>
constexpr T alignUp(T value, T alignTo) noexcept
constexpr T alignUp(T value, T alignTo) MIJIN_NOEXCEPT
{
if (value % alignTo != 0)
{

View File

@ -7,6 +7,7 @@
#include <cstdint>
#include "./traits.hpp"
#include "./types.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -15,23 +16,23 @@ namespace mijin
// public defines
//
#define MIJIN_DEFINE_FLAG(name) \
struct name : mijin::Flag \
{ \
private: \
struct Proxy_ { \
uint8_t value; \
}; \
public: \
constexpr name() = default; \
constexpr name(const name&) = default; \
constexpr name(Proxy_ proxy) \
: Flag(proxy.value) {} \
constexpr explicit name(bool value) noexcept \
: Flag(value) {} \
name& operator=(const name&) = default; \
static constexpr Proxy_ YES{1}; \
static constexpr Proxy_ NO{0}; \
#define MIJIN_DEFINE_FLAG(name) \
struct name : mijin::Flag \
{ \
private: \
struct Proxy_ { \
uint8_t value; \
}; \
public: \
constexpr name() = default; \
constexpr name(const name&) = default; \
constexpr name(Proxy_ proxy) MIJIN_NOEXCEPT \
: Flag(proxy.value) {} \
constexpr explicit name(bool value) MIJIN_NOEXCEPT \
: Flag(value) {} \
name& operator=(const name&) = default; \
static constexpr Proxy_ YES{1}; \
static constexpr Proxy_ NO{0}; \
}
//
@ -48,23 +49,23 @@ struct Flag
Flag() = default;
Flag(const Flag&) = default;
explicit constexpr Flag(uint8_t value) noexcept : value(value) {}
explicit constexpr Flag(uint8_t value) MIJIN_NOEXCEPT : value(value) {}
Flag& operator=(const Flag&) = default;
constexpr bool operator ==(const Flag& other) const noexcept
constexpr bool operator ==(const Flag& other) const MIJIN_NOEXCEPT
{
return value == other.value;
}
constexpr bool operator !=(const Flag& other) const noexcept
constexpr bool operator !=(const Flag& other) const MIJIN_NOEXCEPT
{
return value != other.value;
}
constexpr bool operator !() const noexcept
constexpr bool operator !() const MIJIN_NOEXCEPT
{
return !value;
}
constexpr operator bool() const noexcept
constexpr operator bool() const MIJIN_NOEXCEPT
{
return value != 0;
}
@ -89,7 +90,7 @@ private:
using base_t = FlagSetStorage<offset + 1, TMore...>;
static constexpr typename base_t::data_t BIT = (1 << offset);
public:
constexpr void set(TFirst value) noexcept
constexpr void set(TFirst value) MIJIN_NOEXCEPT
{
if (value)
{
@ -100,7 +101,7 @@ public:
base_t::data_ &= ~BIT;
}
}
constexpr bool get(TFirst) noexcept
constexpr bool get(TFirst) MIJIN_NOEXCEPT
{
return (base_t::data_ & BIT) != 0;
}
@ -134,19 +135,19 @@ public:
public:
FlagSet& operator=(const FlagSet&) = default;
template<FlagType T> requires is_any_type_v<T, TFlags...>
FlagSet& operator=(T flag) noexcept
FlagSet& operator=(T flag) MIJIN_NOEXCEPT
{
reset(flag);
return *this;
}
template<FlagType T> requires is_any_type_v<T, TFlags...>
FlagSet& operator|=(T flag) noexcept
FlagSet& operator|=(T flag) MIJIN_NOEXCEPT
{
set(flag);
return *this;
}
template<FlagType T> requires is_any_type_v<T, TFlags...>
FlagSet& operator&=(T flag) noexcept
FlagSet& operator&=(T flag) MIJIN_NOEXCEPT
{
unset(flag);
}

View File

@ -11,6 +11,7 @@
#include <tuple>
#include <variant>
#include "../container/optional.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -96,50 +97,50 @@ struct EnumeratingIterator
TIdx idx;
TIterator base;
EnumeratingIterator(TIdx idx_, TIterator base_) noexcept : idx(idx_), base(base_) {}
EnumeratingIterator(const EnumeratingIterator&) noexcept = default;
EnumeratingIterator(TIdx idx_, TIterator base_) MIJIN_NOEXCEPT : idx(idx_), base(base_) {}
EnumeratingIterator(const EnumeratingIterator&) MIJIN_NOEXCEPT = default;
EnumeratingIterator& operator=(const EnumeratingIterator&) noexcept = default;
EnumeratingIterator& operator=(const EnumeratingIterator&) MIJIN_NOEXCEPT = default;
auto operator*() const noexcept
auto operator*() const MIJIN_NOEXCEPT
{
return std::tie(idx, *base);
}
EnumeratingIterator& operator++() noexcept
EnumeratingIterator& operator++() MIJIN_NOEXCEPT
{
++idx;
++base;
return *this;
}
EnumeratingIterator operator++(int) noexcept
EnumeratingIterator operator++(int) MIJIN_NOEXCEPT
{
EnumeratingIterator copy(*this);
++(*this);
return copy;
}
EnumeratingIterator& operator--() noexcept
EnumeratingIterator& operator--() MIJIN_NOEXCEPT
{
--idx;
--base;
return *this;
}
EnumeratingIterator operator--(int) noexcept
EnumeratingIterator operator--(int) MIJIN_NOEXCEPT
{
EnumeratingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const EnumeratingIterator& other) const noexcept
bool operator==(const EnumeratingIterator& other) const MIJIN_NOEXCEPT
{
return base == other.base; // note: ignoring idx so we don't have to find it out for end()
}
bool operator!=(const EnumeratingIterator& other) const noexcept
bool operator!=(const EnumeratingIterator& other) const MIJIN_NOEXCEPT
{
return base != other.base; // note: ignoring idx so we don't have to find it out for end()
}
@ -152,12 +153,12 @@ struct Enumeratable : RangeAdapter
{
RangeRef<TIterable> base;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return EnumeratingIterator(TIdx(0), base.begin());
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return EnumeratingIterator(TIdx(0), base.end());
}
@ -175,50 +176,50 @@ struct ZippingIterator
TFirstIterator first;
TSecondIterator second;
ZippingIterator(TFirstIterator first_, TSecondIterator second_) noexcept : first(first_), second(second_) {}
ZippingIterator(const ZippingIterator&) noexcept = default;
ZippingIterator(TFirstIterator first_, TSecondIterator second_) MIJIN_NOEXCEPT : first(first_), second(second_) {}
ZippingIterator(const ZippingIterator&) MIJIN_NOEXCEPT = default;
ZippingIterator& operator=(const ZippingIterator&) noexcept = default;
ZippingIterator& operator=(const ZippingIterator&) MIJIN_NOEXCEPT = default;
decltype(auto) operator*() const noexcept
decltype(auto) operator*() const MIJIN_NOEXCEPT
{
return std::tie(*first, *second);
}
ZippingIterator& operator++() noexcept
ZippingIterator& operator++() MIJIN_NOEXCEPT
{
++first;
++second;
return *this;
}
ZippingIterator operator++(int) noexcept
ZippingIterator operator++(int) MIJIN_NOEXCEPT
{
ZippingIterator copy(*this);
++(*this);
return copy;
}
ZippingIterator& operator--() noexcept
ZippingIterator& operator--() MIJIN_NOEXCEPT
{
--first;
--second;
return *this;
}
ZippingIterator operator--(int) noexcept
ZippingIterator operator--(int) MIJIN_NOEXCEPT
{
ZippingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const ZippingIterator& other) const noexcept
bool operator==(const ZippingIterator& other) const MIJIN_NOEXCEPT
{
return first == other.first || second == other.second; // note: this uses or so reaching the end on one range also ends the zipped one.
}
bool operator!=(const ZippingIterator& other) const noexcept
bool operator!=(const ZippingIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -232,12 +233,12 @@ struct ZippingRange : RangeAdapter
RangeRef<TFirst> first;
RangeRef<TSecond> second;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return ZippingIterator(first.begin(), second.begin());
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return ZippingIterator(first.end(), second.end());
}
@ -262,12 +263,12 @@ struct ReplacingIterator
value_type what;
value_type with;
ReplacingIterator(TIterator base_, value_type what_, value_type with_) noexcept : base(base_), what(what_), with(with_) {}
ReplacingIterator(const ReplacingIterator&) noexcept = default;
ReplacingIterator(TIterator base_, value_type what_, value_type with_) MIJIN_NOEXCEPT : base(base_), what(what_), with(with_) {}
ReplacingIterator(const ReplacingIterator&) MIJIN_NOEXCEPT = default;
ReplacingIterator& operator=(const ReplacingIterator&) noexcept = default;
ReplacingIterator& operator=(const ReplacingIterator&) MIJIN_NOEXCEPT = default;
pointer operator->() const noexcept
pointer operator->() const MIJIN_NOEXCEPT
{
if (*base == what) {
return &with;
@ -275,7 +276,7 @@ struct ReplacingIterator
return &*base;
}
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
if (*base == what) {
return with;
@ -283,38 +284,38 @@ struct ReplacingIterator
return *base;
}
ReplacingIterator& operator++() noexcept
ReplacingIterator& operator++() MIJIN_NOEXCEPT
{
++base;
return *this;
}
ReplacingIterator operator++(int) noexcept
ReplacingIterator operator++(int) MIJIN_NOEXCEPT
{
ReplacingIterator copy(*this);
++(*this);
return copy;
}
ReplacingIterator& operator--() noexcept
ReplacingIterator& operator--() MIJIN_NOEXCEPT
{
--base;
return *this;
}
ReplacingIterator operator--(int) noexcept
ReplacingIterator operator--(int) MIJIN_NOEXCEPT
{
ReplacingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const ReplacingIterator& other) const noexcept
bool operator==(const ReplacingIterator& other) const MIJIN_NOEXCEPT
{
return what == other.what && with == other.with && base == other.base;
}
bool operator!=(const ReplacingIterator& other) const noexcept
bool operator!=(const ReplacingIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -329,12 +330,12 @@ struct ReplacingRange : RangeAdapter
value_type what;
value_type with;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return ReplacingIterator(base.begin(), what, with);
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return ReplacingIterator(base.end(), what, with);
}
@ -368,14 +369,14 @@ struct MappingIterator
TFunctor functor;
mutable Optional<value_type> result;
MappingIterator(TIterator base_, TFunctor functor_) noexcept : base(base_), functor(std::move(functor_)) {}
MappingIterator(const MappingIterator&) noexcept = default;
MappingIterator(MappingIterator&&) noexcept = default;
MappingIterator(TIterator base_, TFunctor functor_) MIJIN_NOEXCEPT : base(base_), functor(std::move(functor_)) {}
MappingIterator(const MappingIterator&) MIJIN_NOEXCEPT = default;
MappingIterator(MappingIterator&&) MIJIN_NOEXCEPT = default;
MappingIterator& operator=(const MappingIterator&) noexcept = default;
MappingIterator& operator=(MappingIterator&&) noexcept = default;
MappingIterator& operator=(const MappingIterator&) MIJIN_NOEXCEPT = default;
MappingIterator& operator=(MappingIterator&&) MIJIN_NOEXCEPT = default;
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
if (result.empty()) {
result = std::invoke(functor, *base);
@ -383,40 +384,40 @@ struct MappingIterator
return *result;
}
MappingIterator& operator++() noexcept
MappingIterator& operator++() MIJIN_NOEXCEPT
{
++base;
result.reset();
return *this;
}
MappingIterator operator++(int) noexcept
MappingIterator operator++(int) MIJIN_NOEXCEPT
{
MappingIterator copy(*this);
++(*this);
return copy;
}
MappingIterator& operator--() noexcept
MappingIterator& operator--() MIJIN_NOEXCEPT
{
--base;
result.reset();
return *this;
}
MappingIterator operator--(int) noexcept
MappingIterator operator--(int) MIJIN_NOEXCEPT
{
MappingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const MappingIterator& other) const noexcept
bool operator==(const MappingIterator& other) const MIJIN_NOEXCEPT
{
return base == other.base; // TODO: compare functor? -> doesn't always work and may be useless
}
bool operator!=(const MappingIterator& other) const noexcept
bool operator!=(const MappingIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -431,17 +432,17 @@ struct MappingRange : RangeAdapter
RangeRef<TIterable> base;
TFunctor functor;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return MappingIterator(base.begin(), functor);
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return MappingIterator(base.end(), functor);
}
[[nodiscard]] bool empty() const noexcept {
[[nodiscard]] bool empty() const MIJIN_NOEXCEPT {
return base.begin() == base.end();
}
};
@ -472,7 +473,7 @@ struct OptionalMappingIterator
TFunctor functor;
mutable optional_type result; // must be mutable so dereferencing can stay const, not nice :/
OptionalMappingIterator(TIterator base_, TIterator end_, TFunctor functor_) noexcept : base(base_), end(end_), functor(std::move(functor_)) {
OptionalMappingIterator(TIterator base_, TIterator end_, TFunctor functor_) MIJIN_NOEXCEPT : base(base_), end(end_), functor(std::move(functor_)) {
if (base != end)
{
result = functor(*base);
@ -481,18 +482,18 @@ struct OptionalMappingIterator
}
}
}
OptionalMappingIterator(const OptionalMappingIterator&) noexcept = default;
OptionalMappingIterator(OptionalMappingIterator&&) noexcept = default;
OptionalMappingIterator(const OptionalMappingIterator&) MIJIN_NOEXCEPT = default;
OptionalMappingIterator(OptionalMappingIterator&&) MIJIN_NOEXCEPT = default;
OptionalMappingIterator& operator=(const OptionalMappingIterator&) noexcept = default;
OptionalMappingIterator& operator=(OptionalMappingIterator&&) noexcept = default;
OptionalMappingIterator& operator=(const OptionalMappingIterator&) MIJIN_NOEXCEPT = default;
OptionalMappingIterator& operator=(OptionalMappingIterator&&) MIJIN_NOEXCEPT = default;
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
return *result;
}
OptionalMappingIterator& operator++() noexcept
OptionalMappingIterator& operator++() MIJIN_NOEXCEPT
{
do
{
@ -502,19 +503,19 @@ struct OptionalMappingIterator
return *this;
}
OptionalMappingIterator operator++(int) noexcept
OptionalMappingIterator operator++(int) MIJIN_NOEXCEPT
{
OptionalMappingIterator copy(*this);
++(*this);
return copy;
}
bool operator==(const OptionalMappingIterator& other) const noexcept
bool operator==(const OptionalMappingIterator& other) const MIJIN_NOEXCEPT
{
return base == other.base && end == other.end; // TODO: compare functor? -> doesn't always work and may be useless
}
bool operator!=(const OptionalMappingIterator& other) const noexcept
bool operator!=(const OptionalMappingIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -529,12 +530,12 @@ struct OptionalMappingRange : RangeAdapter
RangeRef<TIterable> base;
TFunctor functor;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return OptionalMappingIterator(base.begin(), base.end(), functor);
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return OptionalMappingIterator(base.end(), base.end(), functor);
}
@ -561,23 +562,23 @@ struct FilteringIterator
TIterator end;
TPredicate predicate;
FilteringIterator(TIterator base_, TIterator end_, TPredicate predicate_) noexcept : base(base_), end(end_), predicate(std::move(predicate_)) {
FilteringIterator(TIterator base_, TIterator end_, TPredicate predicate_) MIJIN_NOEXCEPT : base(base_), end(end_), predicate(std::move(predicate_)) {
if (base != end && !predicate(*base)) {
++(*this);
}
}
FilteringIterator(const FilteringIterator&) noexcept = default;
FilteringIterator(FilteringIterator&&) noexcept = default;
FilteringIterator(const FilteringIterator&) MIJIN_NOEXCEPT = default;
FilteringIterator(FilteringIterator&&) MIJIN_NOEXCEPT = default;
FilteringIterator& operator=(const FilteringIterator&) noexcept = default;
FilteringIterator& operator=(FilteringIterator&&) noexcept = default;
FilteringIterator& operator=(const FilteringIterator&) MIJIN_NOEXCEPT = default;
FilteringIterator& operator=(FilteringIterator&&) MIJIN_NOEXCEPT = default;
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
return *base;
}
FilteringIterator& operator++() noexcept
FilteringIterator& operator++() MIJIN_NOEXCEPT
{
do
{
@ -586,19 +587,19 @@ struct FilteringIterator
return *this;
}
FilteringIterator operator++(int) noexcept
FilteringIterator operator++(int) MIJIN_NOEXCEPT
{
FilteringIterator copy(*this);
++(*this);
return copy;
}
bool operator==(const FilteringIterator& other) const noexcept
bool operator==(const FilteringIterator& other) const MIJIN_NOEXCEPT
{
return base == other.base && end == other.end; // TODO: compare predicate?
}
bool operator!=(const FilteringIterator& other) const noexcept
bool operator!=(const FilteringIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -613,12 +614,12 @@ struct FilteringRange : RangeAdapter
RangeRef<TIterable> base;
TPredicate predicate;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return FilteringIterator(base.begin(), base.end(), predicate);
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return FilteringIterator(base.end(), base.end(), predicate);
}
@ -647,13 +648,13 @@ struct ChainingIterator
TSecondIterator secondBase;
TSecondIterator secondBegin;
ChainingIterator(TFirstIterator firstBase_, TFirstIterator firstEnd_, TSecondIterator secondBase_, TSecondIterator secondBegin_) noexcept
ChainingIterator(TFirstIterator firstBase_, TFirstIterator firstEnd_, TSecondIterator secondBase_, TSecondIterator secondBegin_) MIJIN_NOEXCEPT
: firstBase(firstBase_), firstEnd(firstEnd_), secondBase(secondBase_), secondBegin(secondBegin_) {}
ChainingIterator(const ChainingIterator&) noexcept = default;
ChainingIterator(const ChainingIterator&) MIJIN_NOEXCEPT = default;
ChainingIterator& operator=(const ChainingIterator&) noexcept = default;
ChainingIterator& operator=(const ChainingIterator&) MIJIN_NOEXCEPT = default;
pointer operator->() const noexcept
pointer operator->() const MIJIN_NOEXCEPT
{
if (firstBase == firstEnd)
{
@ -662,7 +663,7 @@ struct ChainingIterator
return &*firstBase;
}
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
if (firstBase == firstEnd)
{
@ -671,7 +672,7 @@ struct ChainingIterator
return *firstBase;
}
ChainingIterator& operator++() noexcept
ChainingIterator& operator++() MIJIN_NOEXCEPT
{
if (firstBase == firstEnd) {
++secondBase;
@ -682,14 +683,14 @@ struct ChainingIterator
return *this;
}
ChainingIterator operator++(int) noexcept
ChainingIterator operator++(int) MIJIN_NOEXCEPT
{
ChainingIterator copy(*this);
++(*this);
return copy;
}
ChainingIterator& operator--() noexcept
ChainingIterator& operator--() MIJIN_NOEXCEPT
{
if (secondBase == secondBegin) {
--firstBase;
@ -700,19 +701,19 @@ struct ChainingIterator
return *this;
}
ChainingIterator operator--(int) noexcept
ChainingIterator operator--(int) MIJIN_NOEXCEPT
{
ChainingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const ChainingIterator& other) const noexcept
bool operator==(const ChainingIterator& other) const MIJIN_NOEXCEPT
{
return firstBase == other.firstBase && secondBase == other.secondBase; // should be enough
}
bool operator!=(const ChainingIterator& other) const noexcept
bool operator!=(const ChainingIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -726,12 +727,12 @@ struct ChainedRange : RangeAdapter
RangeRef<TFirstRange> first;
RangeRef<TSecondRange> second;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return ChainingIterator(first.begin(), first.end(), second.begin(), second.begin());
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return ChainingIterator(first.end(), first.end(), second.end(), second.begin());
}
@ -764,23 +765,23 @@ struct TypeFilteringIterator
TIterator base;
TIterator end;
TypeFilteringIterator(TIterator base_, TIterator end_) noexcept : base(base_), end(end_) {
TypeFilteringIterator(TIterator base_, TIterator end_) MIJIN_NOEXCEPT : base(base_), end(end_) {
if (base != end && !isCastable()) {
++(*this);
}
}
TypeFilteringIterator(const TypeFilteringIterator&) noexcept = default;
TypeFilteringIterator(TypeFilteringIterator&&) noexcept = default;
TypeFilteringIterator(const TypeFilteringIterator&) MIJIN_NOEXCEPT = default;
TypeFilteringIterator(TypeFilteringIterator&&) MIJIN_NOEXCEPT = default;
TypeFilteringIterator& operator=(const TypeFilteringIterator&) noexcept = default;
TypeFilteringIterator& operator=(TypeFilteringIterator&&) noexcept = default;
TypeFilteringIterator& operator=(const TypeFilteringIterator&) MIJIN_NOEXCEPT = default;
TypeFilteringIterator& operator=(TypeFilteringIterator&&) MIJIN_NOEXCEPT = default;
reference operator*() const noexcept
reference operator*() const MIJIN_NOEXCEPT
{
return static_cast<reference>(*base);
}
TypeFilteringIterator& operator++() noexcept
TypeFilteringIterator& operator++() MIJIN_NOEXCEPT
{
do
{
@ -789,19 +790,19 @@ struct TypeFilteringIterator
return *this;
}
TypeFilteringIterator operator++(int) noexcept
TypeFilteringIterator operator++(int) MIJIN_NOEXCEPT
{
FilteringIterator copy(*this);
++(*this);
return copy;
}
bool operator==(const TypeFilteringIterator& other) const noexcept
bool operator==(const TypeFilteringIterator& other) const MIJIN_NOEXCEPT
{
return base == other.base && end == other.end;
}
bool operator!=(const TypeFilteringIterator& other) const noexcept
bool operator!=(const TypeFilteringIterator& other) const MIJIN_NOEXCEPT
{
return !(*this == other);
}
@ -827,12 +828,12 @@ struct TypeFilteringRange : RangeAdapter
RangeRef<TIterable> iterable;
auto begin() const noexcept
auto begin() const MIJIN_NOEXCEPT
{
return TypeFilteringIterator<TType, decltype(iterable.begin())>(iterable.begin(), iterable.end());
}
auto end() const noexcept
auto end() const MIJIN_NOEXCEPT
{
return TypeFilteringIterator<TType, decltype(iterable.begin())>(iterable.end(), iterable.end());
}

View File

@ -47,7 +47,7 @@ std::mutex gDlErrorMutex; // dlerror may not be thread-safe
// public functions
//
Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) noexcept
Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) MIJIN_NOEXCEPT
{
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
const std::unique_lock dlErrorLock(gDlErrorMutex);
@ -67,7 +67,7 @@ Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) noexcept
#endif
}
bool closeSharedLibrary(const LibraryHandle library) noexcept
bool closeSharedLibrary(const LibraryHandle library) MIJIN_NOEXCEPT
{
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
return dlclose(library.data) == 0;
@ -77,7 +77,7 @@ bool closeSharedLibrary(const LibraryHandle library) noexcept
#endif
}
void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName) noexcept
void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName) MIJIN_NOEXCEPT
{
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
return dlsym(library.data, symbolName);
@ -88,7 +88,7 @@ void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName)
#endif
}
void setCurrentThreadName(const char* threadName) noexcept
void setCurrentThreadName(const char* threadName) MIJIN_NOEXCEPT
{
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
pthread_setname_np(pthread_self(), threadName);
@ -97,7 +97,7 @@ void setCurrentThreadName(const char* threadName) noexcept
#endif
}
[[nodiscard]] std::string makeLibraryFilename(std::string_view libraryName) noexcept
[[nodiscard]] std::string makeLibraryFilename(std::string_view libraryName) MIJIN_NOEXCEPT
{
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
return "lib" + std::string(libraryName) + ".so";

View File

@ -9,6 +9,7 @@
#include <string_view>
#include <utility>
#include "../detect.hpp"
#include "../internal/common.hpp"
#include "../types/result.hpp"
namespace mijin
@ -39,8 +40,8 @@ struct LibraryHandle
{
void* data = nullptr;
constexpr operator bool() const noexcept { return data != nullptr; }
constexpr bool operator!() const noexcept { return data == nullptr; }
constexpr operator bool() const MIJIN_NOEXCEPT { return data != nullptr; }
constexpr bool operator!() const MIJIN_NOEXCEPT { return data == nullptr; }
};
class SharedLibrary
@ -48,43 +49,43 @@ class SharedLibrary
private:
LibraryHandle mHandle;
public:
SharedLibrary() noexcept = default;
SharedLibrary() MIJIN_NOEXCEPT = default;
SharedLibrary(const SharedLibrary&) = delete;
SharedLibrary(SharedLibrary&& other) noexcept : mHandle(std::exchange(other.mHandle, {})) {}
inline ~SharedLibrary() noexcept;
SharedLibrary(SharedLibrary&& other) MIJIN_NOEXCEPT : mHandle(std::exchange(other.mHandle, {})) {}
inline ~SharedLibrary() MIJIN_NOEXCEPT;
SharedLibrary& operator=(const SharedLibrary&) = delete;
SharedLibrary& operator=(SharedLibrary&& other) noexcept
SharedLibrary& operator=(SharedLibrary&& other) MIJIN_NOEXCEPT
{
mHandle = std::exchange(other.mHandle, {});
return *this;
}
constexpr operator bool() const noexcept { return static_cast<bool>(mHandle); }
constexpr bool operator!() const noexcept { return !mHandle; }
constexpr operator bool() const MIJIN_NOEXCEPT { return static_cast<bool>(mHandle); }
constexpr bool operator!() const MIJIN_NOEXCEPT { return !mHandle; }
[[nodiscard]] inline Result<bool> open(std::string_view libraryFile) noexcept;
inline bool close() noexcept;
[[nodiscard]] inline void* loadSymbol(const char* symbolName) noexcept;
[[nodiscard]] inline Result<bool> open(std::string_view libraryFile) MIJIN_NOEXCEPT;
inline bool close() MIJIN_NOEXCEPT;
[[nodiscard]] inline void* loadSymbol(const char* symbolName) MIJIN_NOEXCEPT;
};
//
// public functions
//
[[nodiscard]] Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) noexcept;
bool closeSharedLibrary(const LibraryHandle library) noexcept;
[[nodiscard]] void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName) noexcept;
void setCurrentThreadName(const char* threadName) noexcept;
[[nodiscard]] Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) MIJIN_NOEXCEPT;
bool closeSharedLibrary(const LibraryHandle library) MIJIN_NOEXCEPT;
[[nodiscard]] void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName) MIJIN_NOEXCEPT;
void setCurrentThreadName(const char* threadName) MIJIN_NOEXCEPT;
[[nodiscard]] std::string makeLibraryFilename(std::string_view libraryName) noexcept;
[[nodiscard]] std::string makeLibraryFilename(std::string_view libraryName) MIJIN_NOEXCEPT;
SharedLibrary::~SharedLibrary() noexcept
SharedLibrary::~SharedLibrary() MIJIN_NOEXCEPT
{
close();
}
Result<bool> SharedLibrary::open(std::string_view libraryFile) noexcept
Result<bool> SharedLibrary::open(std::string_view libraryFile) MIJIN_NOEXCEPT
{
close();
Result<LibraryHandle> openResult = openSharedLibrary(libraryFile);
@ -96,7 +97,7 @@ Result<bool> SharedLibrary::open(std::string_view libraryFile) noexcept
return ResultError(openResult.getError());
}
bool SharedLibrary::close() noexcept
bool SharedLibrary::close() MIJIN_NOEXCEPT
{
if (mHandle)
{
@ -105,7 +106,7 @@ bool SharedLibrary::close() noexcept
return false;
}
void* SharedLibrary::loadSymbol(const char* symbolName) noexcept
void* SharedLibrary::loadSymbol(const char* symbolName) MIJIN_NOEXCEPT
{
return loadSymbolFromLibrary(mHandle, symbolName);
}

View File

@ -7,6 +7,7 @@
#include <memory>
#include <utility>
#include "../debug/assert.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -27,7 +28,7 @@ public:
using get_t = TGet;
using set_t = TSet;
virtual ~PropertyStorage() noexcept = default;
virtual ~PropertyStorage() MIJIN_NOEXCEPT = default;
[[nodiscard]] virtual TGet getValue() = 0;
virtual void setValue(TSet value) = 0;
@ -39,15 +40,15 @@ class SimplePropertyStorage : public PropertyStorage<T>
private:
T value_;
public:
SimplePropertyStorage() noexcept = default;
SimplePropertyStorage(const SimplePropertyStorage& other) noexcept(noexcept(T(other.value_))) = default;
SimplePropertyStorage(SimplePropertyStorage&& other) noexcept(noexcept(T(std::move(other.value_)))) = default;
explicit SimplePropertyStorage(T value) noexcept(noexcept(T(std::move(value)))) : value_(std::move(value)) {}
SimplePropertyStorage() MIJIN_NOEXCEPT = default;
SimplePropertyStorage(const SimplePropertyStorage& other) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(T(other.value_))) = default;
SimplePropertyStorage(SimplePropertyStorage&& other) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(T(std::move(other.value_)))) = default;
explicit SimplePropertyStorage(T value) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(T(std::move(value)))) : value_(std::move(value)) {}
SimplePropertyStorage& operator=(const SimplePropertyStorage& other) noexcept(noexcept(value_ = other.value_)) = default;
SimplePropertyStorage& operator=(SimplePropertyStorage&& other) noexcept(noexcept(value_ = std::move(other.value_))) = default;
SimplePropertyStorage& operator=(const SimplePropertyStorage& other) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(value_ = other.value_)) = default;
SimplePropertyStorage& operator=(SimplePropertyStorage&& other) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(value_ = std::move(other.value_))) = default;
const T& getValue() noexcept override { return value_; }
const T& getValue() MIJIN_NOEXCEPT override { return value_; }
void setValue(T value) override { value_ = std::move(value); }
};
@ -65,30 +66,30 @@ public:
private:
Property* base_;
public:
explicit PropertyProxy(Property* base) noexcept : base_(base) {}
explicit PropertyProxy(Property* base) MIJIN_NOEXCEPT : base_(base) {}
operator TGet() noexcept { return base_->get(); }
PropertyProxy& operator=(TSet value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
operator TGet() MIJIN_NOEXCEPT { return base_->get(); }
PropertyProxy& operator=(TSet value) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(std::declval<T&>() = std::move(value)))
{
base_->set(std::move(value));
return *this;
}
};
Property() noexcept = default;
explicit Property(storage_ptr_t storage) noexcept : storage_(std::move(storage)) {}
Property(Property&&) noexcept = default;
Property() MIJIN_NOEXCEPT = default;
explicit Property(storage_ptr_t storage) MIJIN_NOEXCEPT : storage_(std::move(storage)) {}
Property(Property&&) MIJIN_NOEXCEPT = default;
Property& operator=(Property&&) noexcept = default;
PropertyProxy operator*() noexcept { return PropertyProxy(this); }
std::remove_reference_t<TGet>* operator->() const noexcept { return &get(); }
Property& operator=(Property&&) MIJIN_NOEXCEPT = default;
PropertyProxy operator*() MIJIN_NOEXCEPT { return PropertyProxy(this); }
std::remove_reference_t<TGet>* operator->() const MIJIN_NOEXCEPT { return &get(); }
[[nodiscard]] TGet get() const noexcept
[[nodiscard]] TGet get() const MIJIN_NOEXCEPT
{
MIJIN_ASSERT_FATAL(storage_ != nullptr, "Cannot get value from an unset property.");
return storage_->getValue();
}
void set(TSet value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
void set(TSet value) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(std::declval<T&>() = std::move(value)))
{
MIJIN_ASSERT_FATAL(storage_ != nullptr, "Cannot set value of an unset property.");
storage_->setValue(std::move<TSet>(value));
@ -99,7 +100,7 @@ template<typename TStorage>
Property(std::unique_ptr<TStorage>) -> Property<typename TStorage::value_t, typename TStorage::get_t, typename TStorage::set_t>;
template<typename T>
Property<T> makeSimpleProperty(T value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
Property<T> makeSimpleProperty(T value) MIJIN_CONDITIONAL_NOEXCEPT(noexcept(std::declval<T&>() = std::move(value)))
{
return Property(std::make_unique<SimplePropertyStorage<T>>(std::move(value)));
}

View File

@ -5,6 +5,7 @@
#include <functional>
#include "./common_macros.hpp"
#include "../internal/common.hpp"
#define MIJIN_SCOPE_EXIT_NAMED(name) \
const mijin::ScopeExitGuard name = [&]()
@ -19,20 +20,20 @@ private:
mutable std::function<void(void)> func; // variable is declared const to make clang-tidy happy, but we still want to be able to reset()
public:
template<typename TFunc>
inline ScopeExitGuard(TFunc&& func_) noexcept : func(std::forward<TFunc>(func_)) {}
ScopeExitGuard(const ScopeExitGuard&) noexcept = delete;
ScopeExitGuard(ScopeExitGuard&&) noexcept = delete;
inline ~ScopeExitGuard() noexcept
inline ScopeExitGuard(TFunc&& func_) MIJIN_NOEXCEPT : func(std::forward<TFunc>(func_)) {}
ScopeExitGuard(const ScopeExitGuard&) = delete;
ScopeExitGuard(ScopeExitGuard&&) = delete;
inline ~ScopeExitGuard() MIJIN_NOEXCEPT
{
if (func) {
func();
}
}
ScopeExitGuard& operator=(const ScopeExitGuard&) noexcept = delete;
ScopeExitGuard& operator=(ScopeExitGuard&&) noexcept = delete;
ScopeExitGuard& operator=(const ScopeExitGuard&) = delete;
ScopeExitGuard& operator=(ScopeExitGuard&&) = delete;
inline void reset() const noexcept
inline void reset() const MIJIN_NOEXCEPT
{
func = {};
}

View File

@ -16,6 +16,7 @@
#include <vector>
#include "./iterators.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -144,7 +145,7 @@ std::vector<std::basic_string_view<TChar, TTraits>> splitImpl(std::basic_string_
}
template<typename TChar, typename TTraitsA, typename TTraitsB>
bool equalsIgnoreCaseImpl(std::basic_string_view<TChar, TTraitsA> stringA, std::basic_string_view<TChar, TTraitsB> stringB) noexcept
bool equalsIgnoreCaseImpl(std::basic_string_view<TChar, TTraitsA> stringA, std::basic_string_view<TChar, TTraitsB> stringB) MIJIN_NOEXCEPT
{
if (stringA.size() != stringB.size())
{
@ -243,7 +244,7 @@ auto trim(TString&& string)
}
template<typename TLeft, typename TRight>
[[nodiscard]] bool equalsIgnoreCase(TLeft&& left, TRight&& right) noexcept
[[nodiscard]] bool equalsIgnoreCase(TLeft&& left, TRight&& right) MIJIN_NOEXCEPT
{
return detail::equalsIgnoreCaseImpl(std::string_view(left), std::string_view(right));
}
@ -287,7 +288,7 @@ constexpr auto toUpper(TArgs&&... args)
template<typename TNumber>
[[nodiscard]]
constexpr bool toNumber(std::string_view stringView, TNumber& outNumber, int base = 10) noexcept
constexpr bool toNumber(std::string_view stringView, TNumber& outNumber, int base = 10) MIJIN_NOEXCEPT
{
const char* start = &*stringView.begin();
const char* end = start + stringView.size();
@ -297,7 +298,7 @@ constexpr bool toNumber(std::string_view stringView, TNumber& outNumber, int bas
template<typename TChar, typename TTraits, typename TNumber>
[[nodiscard]]
constexpr bool toNumber(std::basic_string_view<TChar, TTraits> stringView, TNumber& outNumber, int base = 10) noexcept requires (!std::is_same_v<TChar, char>)
constexpr bool toNumber(std::basic_string_view<TChar, TTraits> stringView, TNumber& outNumber, int base = 10) MIJIN_NOEXCEPT requires (!std::is_same_v<TChar, char>)
{
std::string asString;
asString.resize(stringView.size());
@ -312,7 +313,7 @@ struct Join
{
const char* delimiter;
explicit Join(const char* delimiter_) noexcept : delimiter(delimiter_) {}
explicit Join(const char* delimiter_) MIJIN_NOEXCEPT : delimiter(delimiter_) {}
};
template<typename TIterable>

View File

@ -12,6 +12,7 @@
#include <vector>
#include "../container/optional.hpp"
#include "../io/stream.hpp"
#include "../internal/common.hpp"
#include "../util/hash.hpp"
namespace fs = std::filesystem;
@ -52,16 +53,16 @@ public:
PathReference() = default;
PathReference(const PathReference&) = default;
PathReference(PathReference&&) = default;
PathReference(class FileSystemAdapter* adapter, fs::path path) noexcept : adapter_(adapter), path_(std::move(path)) {}
PathReference(class FileSystemAdapter* adapter, fs::path path) MIJIN_NOEXCEPT : adapter_(adapter), path_(std::move(path)) {}
PathReference& operator=(const PathReference&) = default;
PathReference& operator=(PathReference&&) = default;
PathReference& operator=(PathReference&&) MIJIN_NOEXCEPT = default;
auto operator<=>(const PathReference& other) const noexcept = default;
auto operator<=>(const PathReference& other) const MIJIN_NOEXCEPT = default;
[[nodiscard]] bool empty() const noexcept { return adapter_ == nullptr; }
[[nodiscard]] bool empty() const MIJIN_NOEXCEPT { return adapter_ == nullptr; }
[[nodiscard]] class FileSystemAdapter* getAdapter() const noexcept { return adapter_; }
[[nodiscard]] const fs::path& getPath() const noexcept { return path_; }
[[nodiscard]] const fs::path& getPath() const MIJIN_NOEXCEPT { return path_; }
[[nodiscard]] inline FileInfo getInfo() const;
[[nodiscard]] inline Optional<fs::path> getNativePath() const;
[[nodiscard]] inline StreamError open(FileOpenMode mode, std::unique_ptr<Stream>& outStream) const;
@ -79,7 +80,7 @@ public:
[[nodiscard]] virtual Optional<fs::path> getNativePath(const fs::path& /* file */) { return NULL_OPTIONAL; }
[[nodiscard]] virtual StreamError open(const fs::path& path, FileOpenMode mode, std::unique_ptr<Stream>& outStream) = 0;
[[nodiscard]] PathReference getPath(fs::path path) noexcept { return PathReference(this, std::move(path)); }
[[nodiscard]] PathReference getPath(fs::path path) MIJIN_NOEXCEPT { return PathReference(this, std::move(path)); }
};
class OSFileSystemAdapter : public FileSystemAdapter
@ -151,7 +152,7 @@ inline std::string formatFileSize(std::size_t sizeInBytes)
template<>
struct std::hash<mijin::PathReference>
{
std::size_t operator()(const mijin::PathReference& pathRef) const noexcept
std::size_t operator()(const mijin::PathReference& pathRef) const MIJIN_NOEXCEPT
{
std::size_t hash = 0;
mijin::hashCombine(hash, pathRef.getAdapter());

View File

@ -5,6 +5,7 @@
#define MIJIN_VIRTUAL_FILESYSTEM_RELATIVE_HPP_INCLUDED 1
#include "./filesystem.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@ -32,10 +33,10 @@ public:
explicit RelativeFileSystemAdapter(fs::path root, TArgs&&... args)
: wrapped_(std::forward<TArgs>(args)...), root_(std::move(root)) {}
RelativeFileSystemAdapter(const RelativeFileSystemAdapter&) = default;
RelativeFileSystemAdapter(RelativeFileSystemAdapter&&) noexcept = default;
RelativeFileSystemAdapter(RelativeFileSystemAdapter&&) MIJIN_NOEXCEPT = default;
RelativeFileSystemAdapter& operator=(const RelativeFileSystemAdapter&) = default;
RelativeFileSystemAdapter& operator=(RelativeFileSystemAdapter&&) noexcept = default;
RelativeFileSystemAdapter& operator=(RelativeFileSystemAdapter&&) MIJIN_NOEXCEPT = default;
std::vector<fs::path> getRoots() override;
fs::path getHomeFolder() override;
@ -44,7 +45,7 @@ public:
Optional<fs::path> getNativePath(const fs::path& file) override;
StreamError open(const fs::path& path, FileOpenMode mode, std::unique_ptr<Stream>& outStream) override;
private:
fs::path appendPath(const fs::path& other) const noexcept;
fs::path appendPath(const fs::path& other) const MIJIN_NOEXCEPT;
};
//
@ -94,7 +95,7 @@ StreamError RelativeFileSystemAdapter<TWrapped>::open(const fs::path& path, File
}
template<typename TWrapped>
fs::path RelativeFileSystemAdapter<TWrapped>::appendPath(const fs::path& other) const noexcept
fs::path RelativeFileSystemAdapter<TWrapped>::appendPath(const fs::path& other) const MIJIN_NOEXCEPT
{
fs::path combinedPath = root_;
if (other.is_absolute()) {