diff options
Diffstat (limited to 'c++')
110 files changed, 0 insertions, 13277 deletions
diff --git a/c++/SConscript b/c++/SConscript deleted file mode 100644 index 8da5a3d..0000000 --- a/c++/SConscript +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/false - -Import('env') - -# Export to other libs -Export('env'); -SConscript('core/SConscript'); -SConscript('async/SConscript'); diff --git a/c++/async/.nix/derivation.nix b/c++/async/.nix/derivation.nix deleted file mode 100644 index aad258f..0000000 --- a/c++/async/.nix/derivation.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-async"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/async/SConscript b/c++/async/SConscript deleted file mode 100644 index 69f8950..0000000 --- a/c++/async/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -async_env = env.Clone(); - -async_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -async_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += async_env.sources; -env.headers += async_env.headers; - -## Shared lib -objects_shared = [] -async_env.add_source_files(objects_shared, async_env.sources, shared=True); -async_env.library_shared = async_env.SharedLibrary('#build/forstio-async', [objects_shared]); - -## Static lib -objects_static = [] -async_env.add_source_files(objects_static, async_env.sources, shared=False); -async_env.library_static = async_env.StaticLibrary('#build/forstio-async', [objects_static]); - -# Set Alias -env.Alias('library_async', [async_env.library_shared, async_env.library_static]); - -env.targets += ['library_async']; - -# Install -env.Install('$prefix/lib/', [async_env.library_shared, async_env.library_static]); -env.Install('$prefix/include/forstio/async/', [async_env.headers]); diff --git a/c++/async/SConstruct b/c++/async/SConstruct deleted file mode 100644 index 0d7b7c6..0000000 --- a/c++/async/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-core']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/async/async.cpp b/c++/async/async.cpp deleted file mode 100644 index 360e455..0000000 --- a/c++/async/async.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include "async.h" -#include <forstio/core/common.h> -#include <forstio/core/error.h> - -#include <algorithm> -#include <cassert> - -namespace saw { -namespace { -thread_local event_loop *local_loop = nullptr; - -event_loop ¤t_event_loop() { - event_loop *loop = local_loop; - assert(loop); - return *loop; -} -} // namespace - -conveyor_node::conveyor_node() {} - -conveyor_node_with_child_mixin::conveyor_node_with_child_mixin( - own<conveyor_node> &&child_, conveyor_node &owner) - : child{std::move(child_)} { - assert(child); - - child->notify_parent_attached(owner); -} - -error_or<own<conveyor_node>> -conveyor_node_with_child_mixin::swap_child(own<conveyor_node> &&swapee) { - SAW_ASSERT(child) { - return make_error<err::invalid_state>("Child should exist if this function is called"); - } - own<conveyor_node> old_child = std::move(child); - - /** - * We need the parent of the old_child's next storage - */ - conveyor_storage *old_storage = old_child->next_storage(); - conveyor_storage *old_storage_parent = - old_storage ? old_storage->get_parent() : nullptr; - - /** - * Swap in the new child - */ - if (swapee) { - child = std::move(swapee); - - /** - * Then we need to set the new child's storage parent since the next - * storage has a nullptr set And if the old_storage_parent is a nullptr, - * then it doesn't matter. So we don't check for it - */ - conveyor_storage *swapee_storage = child->next_storage(); - if (swapee_storage) { - swapee_storage->set_parent(old_storage_parent); - } - } - - return old_child; -} - -conveyor_storage::conveyor_storage() {} - -conveyor_storage::~conveyor_storage() {} - -conveyor_storage *conveyor_storage::get_parent() const { return parent_; } - -void conveyor_event_storage::set_parent(conveyor_storage *p) { - /* - * parent check isn't needed, but is used - * for the assert, because the storage should - * be armed if there was an element present - * and a valid parent - */ - if (/*!parent && */ p && !is_armed() && queued() > 0) { - assert(!parent_); - if (p->space() > 0) { - arm_later(); - } - } - - parent_ = p; -} - -conveyor_event_storage::conveyor_event_storage() : conveyor_storage{} {} - -conveyor_base::conveyor_base(own<conveyor_node> &&node_p) - : node_{std::move(node_p)} {} - -error propagate_error::operator()(const error &error) const { - return error.copy_error(); -} - -error propagate_error::operator()(error &&err) { return std::move(err); } - -event::event() : event(current_event_loop()) {} - -event::event(event_loop &loop) : loop_{loop} {} - -event::~event() { disarm(); } - -void event::arm_next() { - assert(&loop_ == local_loop); - if (prev_ == nullptr) { - // Push the next_insert_point back by one - // and inserts itself before that - next_ = *loop_.next_insert_point_; - prev_ = loop_.next_insert_point_; - *prev_ = this; - if (next_) { - next_->prev_ = &next_; - } - - // Set the new insertion ptr location to next - loop_.next_insert_point_ = &next_; - - // Pushes back the later insert point if it was pointing at the - // previous event - if (loop_.later_insert_point_ == prev_) { - loop_.later_insert_point_ = &next_; - } - - // If tail_ points at the same location then - // we are at the end and have to update tail_ then. - // Technically should be possible by checking if - // next is a `nullptr` - if (loop_.tail_ == prev_) { - loop_.tail_ = &next_; - } - - loop_.set_runnable(true); - } -} - -void event::arm_later() { - assert(&loop_ == local_loop); - - if (prev_ == nullptr) { - next_ = *loop_.later_insert_point_; - prev_ = loop_.later_insert_point_; - *prev_ = this; - if (next_) { - next_->prev_ = &next_; - } - - loop_.later_insert_point_ = &next_; - if (loop_.tail_ == prev_) { - loop_.tail_ = &next_; - } - - loop_.set_runnable(true); - } -} - -void event::arm_last() { - assert(&loop_ == local_loop); - - if (prev_ == nullptr) { - next_ = *loop_.later_insert_point_; - prev_ = loop_.later_insert_point_; - *prev_ = this; - if (next_) { - next_->prev_ = &next_; - } - - if (loop_.tail_ == prev_) { - loop_.tail_ = &next_; - } - - loop_.set_runnable(true); - } -} - -void event::disarm() { - if (prev_ != nullptr) { - if (loop_.tail_ == &next_) { - loop_.tail_ = prev_; - } - - if (loop_.next_insert_point_ == &next_) { - loop_.next_insert_point_ = prev_; - } - - *prev_ = next_; - if (next_) { - next_->prev_ = prev_; - } - - prev_ = nullptr; - next_ = nullptr; - } -} - -bool event::is_armed() const { return prev_ != nullptr; } - -conveyor_sink::conveyor_sink() : node_{nullptr} {} - -conveyor_sink::conveyor_sink(own<conveyor_node> &&node_p) - : node_{std::move(node_p)} {} - -void event_loop::set_runnable(bool runnable) { is_runnable_ = runnable; } - -event_loop::event_loop() {} - -event_loop::event_loop(own<class event_port> &&ep) - : event_port_{std::move(ep)} {} - -event_loop::~event_loop() { assert(local_loop != this); } - -void event_loop::enter_scope() { - assert(!local_loop); - local_loop = this; -} - -void event_loop::leave_scope() { - assert(local_loop == this); - local_loop = nullptr; -} - -bool event_loop::turn_loop() { - size_t turn_step = 0; - while (head_ && turn_step < 65536) { - if (!turn()) { - return false; - } - ++turn_step; - } - return true; -} - -bool event_loop::turn() { - event *event = head_; - - if (!event) { - return false; - } - - head_ = event->next_; - if (head_) { - head_->prev_ = &head_; - } - - next_insert_point_ = &head_; - if (later_insert_point_ == &event->next_) { - later_insert_point_ = &head_; - } - if (tail_ == &event->next_) { - tail_ = &head_; - } - - event->next_ = nullptr; - event->prev_ = nullptr; - - next_insert_point_ = &head_; - - event->fire(); - - return true; -} - -bool event_loop::wait(const std::chrono::steady_clock::duration &duration) { - if (event_port_) { - event_port_->wait(duration); - } - - return turn_loop(); -} - -bool event_loop::wait(const std::chrono::steady_clock::time_point &time_point) { - if (event_port_) { - event_port_->wait(time_point); - } - - return turn_loop(); -} - -bool event_loop::wait() { - if (event_port_) { - event_port_->wait(); - } - - return turn_loop(); -} - -bool event_loop::poll() { - if (event_port_) { - event_port_->poll(); - } - - return turn_loop(); -} - -event_port *event_loop::get_event_port() { return event_port_.get(); } - -conveyor_sink_set &event_loop::daemon() { - if (!daemon_sink_) { - daemon_sink_ = heap<conveyor_sink_set>(); - } - return *daemon_sink_; -} - -wait_scope::wait_scope(event_loop &loop) : loop_{loop} { loop_.enter_scope(); } - -wait_scope::~wait_scope() { loop_.leave_scope(); } - -void wait_scope::wait() { loop_.wait(); } - -void wait_scope::wait(const std::chrono::steady_clock::duration &duration) { - loop_.wait(duration); -} - -void wait_scope::wait(const std::chrono::steady_clock::time_point &time_point) { - loop_.wait(time_point); -} - -void wait_scope::poll() { loop_.poll(); } - -error_or<own<conveyor_node>> -convert_conveyor_node_base::swap_child(own<conveyor_node> &&swapee) noexcept { - return child_mixin_.swap_child(std::move(swapee)); -} - -conveyor_storage *convert_conveyor_node_base::next_storage() noexcept { - if (!child_mixin_.child) { - return nullptr; - } - return child_mixin_.child->next_storage(); -} - -immediate_conveyor_node_base::immediate_conveyor_node_base() - : conveyor_event_storage{} {} - -merge_conveyor_node_base::merge_conveyor_node_base() - : conveyor_event_storage{} {} - -error_or<own<conveyor_node>> queue_buffer_conveyor_node_base::swap_child( - own<conveyor_node> &&swapee_) noexcept { - return child_mixin_.swap_child(std::move(swapee_)); -} - -void conveyor_sink_set::destroy_sink_conveyor_node(conveyor_node &node) { - if (!is_armed()) { - arm_last(); - } - - delete_nodes_.push(&node); -} - -void conveyor_sink_set::fail(error &&error) { - /// @todo call error_handler -} - -conveyor_sink_set::conveyor_sink_set(event_loop &event_loop) - : event{event_loop} {} - -void conveyor_sink_set::add(conveyor<void> &&sink) { - auto nas = conveyor<void>::from_conveyor(std::move(sink)); - SAW_ASSERT(nas) { return; } - conveyor_storage *storage = nas->next_storage(); - - own<sink_conveyor_node> sink_node = nullptr; - try { - sink_node = heap<sink_conveyor_node>(std::move(nas), *this); - } catch (std::bad_alloc &) { - return; - } - if (storage) { - storage->set_parent(sink_node.get()); - } - - sink_nodes_.emplace_back(std::move(sink_node)); -} - -void conveyor_sink_set::fire() { - while (!delete_nodes_.empty()) { - conveyor_node *node = delete_nodes_.front(); - /*auto erased = */ std::remove_if(sink_nodes_.begin(), - sink_nodes_.end(), - [node](own<conveyor_node> &element) { - return node == element.get(); - }); - delete_nodes_.pop(); - } -} - -convert_conveyor_node_base::convert_conveyor_node_base(own<conveyor_node> &&dep) - : child_mixin_{std::move(dep), *this} {} - -void convert_conveyor_node_base::get_result(error_or_value &err_or_val) { - get_impl(err_or_val); -} - -void attach_conveyor_node_base::get_result( - error_or_value &err_or_val) noexcept { - if (child_mixin_.child) { - child_mixin_.child->get_result(err_or_val); - } -} - -error_or<own<conveyor_node>> -attach_conveyor_node_base::swap_child(own<conveyor_node> &&swapee_) noexcept { - return child_mixin_.swap_child(std::move(swapee_)); -} - -conveyor_storage *attach_conveyor_node_base::next_storage() noexcept { - if (!child_mixin_.child) { - return nullptr; - } - - return child_mixin_.child->next_storage(); -} - -void detach_conveyor(conveyor<void> &&conveyor) { - event_loop &loop = current_event_loop(); - conveyor_sink_set &sink = loop.daemon(); - sink.add(std::move(conveyor)); -} -} // namespace saw diff --git a/c++/async/async.h b/c++/async/async.h deleted file mode 100644 index 8190be0..0000000 --- a/c++/async/async.h +++ /dev/null @@ -1,1023 +0,0 @@ -#pragma once - -#include <forstio/core/common.h> -#include <forstio/core/error.h> - -#include <chrono> -#include <functional> -#include <limits> -#include <list> -#include <queue> -#include <type_traits> - -namespace saw { -class conveyor_storage; -class conveyor_node { -public: - conveyor_node(); - virtual ~conveyor_node() = default; - - /** - * Internal method to retrieve results from children - */ - virtual void get_result(error_or_value &err_or_val) = 0; - - /** - * Swap out child with another one - */ - virtual error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee_) = 0; - - /** - * Retrieve the next storage node - */ - virtual conveyor_storage *next_storage() = 0; - - /** - * Notify that a new parent was attached - * Only relevant for the feeding nodes - */ - virtual void notify_parent_attached(conveyor_node &){}; -}; - -class conveyor_node_with_child_mixin final { -public: - own<conveyor_node> child = nullptr; - - conveyor_node_with_child_mixin(own<conveyor_node> &&child_, - conveyor_node &owner_); - ~conveyor_node_with_child_mixin() = default; - - /** - * Swap out children and return the child ptr, since the caller is the child - * itself. Stack needs to be cleared before the child is destroyed, so the - * swapped out node is returned as well. - */ - error_or<own<conveyor_node>> swap_child(own<conveyor_node> &&swapee); -}; - -class conveyor_node_with_parent_mixin final { -public: - conveyor_node *parent = nullptr; - - error_or<own<conveyor_node>> - swap_child_of_parent(own<conveyor_node> &&swapee) { - SAW_ASSERT(parent) { - return make_error<err::invalid_state>( - "Can't swap child, because parent doesn't exist"); - } - - return parent->swap_child(std::move(swapee)); - } - void change_parent(conveyor_node *p) { parent = p; } -}; - -class event_loop; -class wait_scope; -/* - * Event class similar to capn'proto. - * https://github.com/capnproto/capnproto - */ -class event { -private: - event_loop &loop_; - event **prev_ = nullptr; - event *next_ = nullptr; - - friend class event_loop; - -public: - event(); - event(event_loop &loop); - virtual ~event(); - - virtual void fire() = 0; - - void arm_next(); - void arm_later(); - void arm_last(); - void disarm(); - - bool is_armed() const; -}; - -class conveyor_storage { -protected: - conveyor_storage *parent_ = nullptr; - -public: - conveyor_storage(); - virtual ~conveyor_storage(); - - virtual size_t space() const = 0; - virtual size_t queued() const = 0; - virtual void child_has_fired() = 0; - virtual void parent_has_fired() = 0; - - virtual void set_parent(conveyor_storage *parent) = 0; - conveyor_storage *get_parent() const; -}; - -class conveyor_event_storage : public conveyor_storage, public event { -public: - conveyor_event_storage(); - virtual ~conveyor_event_storage() = default; - - void set_parent(conveyor_storage *parent) override; -}; - -class conveyor_base { -protected: - own<conveyor_node> node_; - -public: - conveyor_base(own<conveyor_node> &&node_p); - virtual ~conveyor_base() = default; - - conveyor_base(conveyor_base &&) = default; - conveyor_base &operator=(conveyor_base &&) = default; - - void get(error_or_value &err_or_val); -}; - -template <typename T> class conveyor; - -template <typename T> conveyor<T> chained_conveyor_type(T *); - -// template <typename T> Conveyor<T> chainedConveyorType(Conveyor<T> *); - -template <typename T> T remove_error_or_type(T *); - -template <typename T> T remove_error_or_type(error_or<T> *); - -template <typename T> -using remove_error_or = decltype(remove_error_or_type((T *)nullptr)); - -template <typename T> -using chained_conveyors = decltype(chained_conveyor_type((T *)nullptr)); - -template <typename Func, typename T> -using conveyor_result = - chained_conveyors<remove_error_or<return_type<Func, T>>>; - -struct propagate_error { -public: - error operator()(const error &err) const; - error operator()(error &&err); -}; - -class conveyor_sink { -private: - own<conveyor_node> node_; - -public: - conveyor_sink(); - conveyor_sink(own<conveyor_node> &&node); - - conveyor_sink(conveyor_sink &&) = default; - conveyor_sink &operator=(conveyor_sink &&) = default; -}; - -template <typename T> class merge_conveyor_node_data; - -template <typename T> class merge_conveyor { -private: - lent<merge_conveyor_node_data<T>> data_; - -public: - merge_conveyor() = default; - merge_conveyor(lent<merge_conveyor_node_data<T>> d); - ~merge_conveyor(); - - void attach(conveyor<T> conv); -}; - -/** - * Main interface for async operations. - */ -template <typename T> class conveyor final : public conveyor_base { -public: - /** - * Construct an immediately fulfilled node - */ - conveyor(fix_void<T> value); - - /** - * Construct an immediately failed node - */ - conveyor(error &&err); - - /** - * Construct a conveyor with a child node - */ - conveyor(own<conveyor_node> node_p); - - conveyor(conveyor<T> &&) = default; - conveyor<T> &operator=(conveyor<T> &&) = default; - - /** - * This method converts values or errors from children - */ - template <typename Func, typename ErrorFunc = propagate_error> - [[nodiscard]] conveyor_result<Func, T> - then(Func &&func, ErrorFunc &&error_func = propagate_error()); - - /** - * This method adds a buffer node in the conveyor chains which acts as a - * scheduler interrupt point and collects elements up to the supplied limit. - */ - [[nodiscard]] conveyor<T> - buffer(size_t limit = std::numeric_limits<size_t>::max()); - - /** - * This method just takes ownership of any supplied types, - * which are destroyed when the chain gets destroyed. - * Useful for resource lifetime control. - */ - template <typename... Args> - [[nodiscard]] conveyor<T> attach(Args &&...args); - - /** @todo implement - * This method limits the total amount of passed elements - * Be careful where you place this node into the chain. - * If you meant to fork it and destroy paths you shouldn't place - * an interrupt point between the fork and this limiter - */ - [[nodiscard]] conveyor<T> limit(size_t val = 1); - - /** - * - */ - [[nodiscard]] std::pair<conveyor<T>, merge_conveyor<T>> merge(); - - /** - * Moves the conveyor chain into a thread local storage point which drops - * every element. Use sink() if you want to control the lifetime of a - * conveyor chain - */ - template <typename ErrorFunc = propagate_error> - void detach(ErrorFunc &&err_func = propagate_error()); - /** - * Creates a local sink which drops elements, but lifetime control remains - * in your hand. - */ - template <typename ErrorFunc = propagate_error> - [[nodiscard]] conveyor_sink - sink(ErrorFunc &&error_func = propagate_error()); - - /** - * If no sink() or detach() is used you have to take elements out of the - * chain yourself. - */ - error_or<fix_void<T>> take(); - - /** @todo implement - * Specifically pump elements through this chain with the provided - * wait_scope - */ - void poll(wait_scope &wait_scope); - - // helper - static conveyor<T> to_conveyor(own<conveyor_node> node); - - // helper - static own<conveyor_node> from_conveyor(conveyor<T> conveyor); -}; - -template <typename Func> conveyor_result<Func, void> exec_later(Func &&func); - -/* - * Join Conveyors into a single one - */ -template <typename... Args> -conveyor<std::tuple<Args...>> -join_conveyors(std::tuple<conveyor<Args>...> &conveyors); - -template <typename T> class conveyor_feeder { -public: - virtual ~conveyor_feeder() = default; - - virtual void feed(T &&data) = 0; - virtual void fail(error &&error) = 0; - - virtual size_t space() const = 0; - virtual size_t queued() const = 0; - - virtual error swap(conveyor<T> &&conveyor) noexcept = 0; -}; - -template <> class conveyor_feeder<void> { -public: - virtual ~conveyor_feeder() = default; - - virtual void feed(void_t &&value = void_t{}) = 0; - virtual void fail(error &&error) = 0; - - virtual size_t space() const = 0; - virtual size_t queued() const = 0; - - virtual error swap(conveyor<void_t> &&conveyor) noexcept = 0; -}; - -template <typename T> struct conveyor_and_feeder { - own<conveyor_feeder<T>> feeder; - class conveyor<T> conveyor; -}; - -template <typename T> conveyor_and_feeder<T> new_conveyor_and_feeder(); - -template <typename T> conveyor_and_feeder<T> one_time_conveyor_and_feeder(); - -enum class Signal : uint8_t { Terminate, User1 }; - -/** - * Class which acts as a correspondent between the running framework and outside - * events which may be signals from the operating system or just other threads. - * Default EventPorts are supplied by setupAsyncIo() in io.h - */ -class event_port { -public: - virtual ~event_port() = default; - - virtual conveyor<void> on_signal(Signal signal) = 0; - - virtual void poll() = 0; - virtual void wait() = 0; - virtual void wait(const std::chrono::steady_clock::duration &) = 0; - virtual void wait(const std::chrono::steady_clock::time_point &) = 0; - - virtual void wake() = 0; -}; - -class sink_conveyor_node; - -class conveyor_sink_set final : public event { -private: - /* - class Helper final : public Event { - private: - void destroySinkConveyorNode(ConveyorNode& sink); - void fail(Error&& error); - - std::vector<Own<ConveyorNode>> sink_nodes; - std::queue<ConveyorNode*> delete_nodes; - std::function<void(Error&& error)> error_handler; - - public: - ConveyorSinks() = default; - ConveyorSinks(EventLoop& event_loop); - - void add(Conveyor<void> node); - - void fire() override {} - }; - - gin::Own<Helper> helper; - */ - friend class sink_conveyor_node; - - void destroy_sink_conveyor_node(conveyor_node &sink_node); - void fail(error &&err); - - std::list<own<conveyor_node>> sink_nodes_; - - std::queue<conveyor_node *> delete_nodes_; - - std::function<void(error &&)> error_handler_; - -public: - // ConveyorSinks(); - // ConveyorSinks(EventLoop& event_loop); - conveyor_sink_set() = default; - conveyor_sink_set(event_loop &event_loop); - - void add(conveyor<void> &&node); - - void fire() override; -}; - -/* - * EventLoop class similar to capn'proto. - * https://github.com/capnproto/capnproto - */ -class event_loop { -private: - friend class event; - event *head_ = nullptr; - event **tail_ = &head_; - event **next_insert_point_ = &head_; - event **later_insert_point_ = &head_; - - bool is_runnable_ = false; - - own<event_port> event_port_ = nullptr; - - own<conveyor_sink_set> daemon_sink_ = nullptr; - - // functions - void set_runnable(bool runnable); - - friend class wait_scope; - void enter_scope(); - void leave_scope(); - - bool turn_loop(); - bool turn(); - -public: - event_loop(); - event_loop(own<event_port> &&port); - ~event_loop(); - - event_loop(event_loop &&) = default; - event_loop &operator=(event_loop &&) = default; - - bool wait(); - bool wait(const std::chrono::steady_clock::duration &); - bool wait(const std::chrono::steady_clock::time_point &); - bool poll(); - - event_port *get_event_port(); - - conveyor_sink_set &daemon(); -}; - -/* - * WaitScope class similar to capn'proto. - * https://github.com/capnproto/capnproto - */ -class wait_scope { -private: - event_loop &loop_; - -public: - wait_scope(event_loop &loop); - ~wait_scope(); - - void wait(); - void wait(const std::chrono::steady_clock::duration &); - void wait(const std::chrono::steady_clock::time_point &); - void poll(); -}; - -template <typename Func> conveyor_result<Func, void> yield_next(Func &&func); - -template <typename Func> conveyor_result<Func, void> yield_later(Func &&func); - -template <typename Func> conveyor_result<Func, void> yield_last(Func &&func); -} // namespace saw - -// Secret stuff -// Aka private semi hidden classes -namespace saw { - -template <typename Out, typename In> struct fix_void_caller { - template <typename Func> static Out apply(Func &func, In &&in) { - return func(std::move(in)); - } -}; - -template <typename Out> struct fix_void_caller<Out, void_t> { - template <typename Func> static Out apply(Func &func, void_t &&in) { - (void)in; - return func(); - } -}; - -template <typename In> struct fix_void_caller<void_t, In> { - template <typename Func> static void_t apply(Func &func, In &&in) { - func(std::move(in)); - return void_t{}; - } -}; - -template <> struct fix_void_caller<void_t, void_t> { - template <typename Func> static void_t apply(Func &func, void_t &&in) { - (void)in; - func(); - return void_t{}; - } -}; - -template <typename T> class adapt_conveyor_node; - -template <typename T> -class adapt_conveyor_feeder final : public conveyor_feeder<unfix_void<T>> { -private: - adapt_conveyor_node<T> *feedee_ = nullptr; - -public: - ~adapt_conveyor_feeder(); - - void set_feedee(adapt_conveyor_node<T> *feedee); - - void feed(T &&value) override; - void fail(error &&error) override; - - size_t space() const override; - size_t queued() const override; - - error swap(conveyor<T> &&conv) noexcept override; -}; - -template <typename T> -class adapt_conveyor_node final : public conveyor_node, - public conveyor_event_storage { -private: - adapt_conveyor_feeder<T> *feeder_ = nullptr; - - std::queue<error_or<unfix_void<T>>> storage_; - - conveyor_node_with_parent_mixin parent_node_; - -public: - adapt_conveyor_node(); - ~adapt_conveyor_node(); - - void set_feeder(adapt_conveyor_feeder<T> *feeder); - - void feed(T &&value); - void fail(error &&error); - - // ConveyorNode - void get_result(error_or_value &err_or_val) override; - - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee) noexcept override; - - conveyor_storage *next_storage() noexcept override; - void notify_parent_attached(conveyor_node &) noexcept override; - - // ConveyorStorage - size_t space() const override; - size_t queued() const override; - - void child_has_fired() override; - void parent_has_fired() override; - - // Event - void fire() override; -}; - -template <typename T> class one_time_conveyor_node; - -template <typename T> -class one_time_conveyor_feeder final : public conveyor_feeder<unfix_void<T>> { -private: - one_time_conveyor_node<T> *feedee_ = nullptr; - -public: - ~one_time_conveyor_feeder(); - - void set_feedee(one_time_conveyor_node<T> *feedee); - - void feed(T &&value) override; - void fail(error &&error) override; - - size_t space() const override; - size_t queued() const override; -}; - -template <typename T> -class one_time_conveyor_node final : public conveyor_node, - public conveyor_storage, - public event { -private: - one_time_conveyor_feeder<T> *feeder_ = nullptr; - - bool passed_ = false; - maybe<error_or<T>> storage_ = std::nullopt; - -public: - ~one_time_conveyor_node(); - - void set_feeder(one_time_conveyor_feeder<T> *feeder); - - void feed(T &&value); - void fail(error &&error); - - // ConveyorNode - void get_result(error_or_value &err_or_val) override; - - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee) override; - - // ConveyorStorage - size_t space() const override; - size_t queued() const override; - - void child_has_fired() override {} - void parent_has_fired() override; - - // Event - void fire() override; -}; - -/** - * This class buffers and saves incoming elements and acts as an interrupt node - * for processing calls - */ -class queue_buffer_conveyor_node_base : public conveyor_node, - public conveyor_event_storage { -protected: - conveyor_node_with_child_mixin child_mixin_; - -public: - queue_buffer_conveyor_node_base(own<conveyor_node> child_) - : conveyor_event_storage{}, child_mixin_{std::move(child_), *this} {} - virtual ~queue_buffer_conveyor_node_base() = default; - - /** - * Use mixin - */ - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee_) noexcept override; - - conveyor_storage *next_storage() noexcept override { - return static_cast<conveyor_storage *>(this); - } -}; - -template <typename T> -class queue_buffer_conveyor_node final - : public queue_buffer_conveyor_node_base { -private: - std::queue<error_or<T>> storage_; - size_t max_store_; - -public: - queue_buffer_conveyor_node(own<conveyor_node> dep, size_t max_size) - : queue_buffer_conveyor_node_base{std::move(dep)}, max_store_{ - max_size} {} - // Event - void fire() override; - // ConveyorNode - void get_result(error_or_value &eov) noexcept override; - - // ConveyorStorage - size_t space() const override; - size_t queued() const override; - - void child_has_fired() override; - void parent_has_fired() override; -}; - -class attach_conveyor_node_base : public conveyor_node { -protected: - conveyor_node_with_child_mixin child_mixin_; - -public: - attach_conveyor_node_base(own<conveyor_node> &&child_) - : child_mixin_{std::move(child_), *this} {} - - virtual ~attach_conveyor_node_base() = default; - - void get_result(error_or_value &err_or_val) noexcept override; - - /** - * Use mixin - */ - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee_) noexcept override; - - conveyor_storage *next_storage() noexcept override; -}; - -template <typename... Args> -class attach_conveyor_node final : public attach_conveyor_node_base { -public: - attach_conveyor_node(own<conveyor_node> &&dep, Args &&...args) - : attach_conveyor_node_base(std::move(dep)), attached_data_{ - std::move(args...)} {} - -private: - std::tuple<Args...> attached_data_; -}; - -class convert_conveyor_node_base : public conveyor_node { -public: - convert_conveyor_node_base(own<conveyor_node> &&dep); - virtual ~convert_conveyor_node_base() = default; - - void get_result(error_or_value &err_or_val) override; - - virtual void get_impl(error_or_value &err_or_val) = 0; - - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee) noexcept override; - - conveyor_storage *next_storage() noexcept override; - -protected: - conveyor_node_with_child_mixin child_mixin_; -}; - -template <typename T, typename DepT, typename Func, typename ErrorFunc> -class convert_conveyor_node final : public convert_conveyor_node_base { -private: - Func func_; - ErrorFunc error_func_; - - static_assert(std::is_same<DepT, remove_error_or<DepT>>::value, - "Should never be of type ErrorOr"); - -public: - convert_conveyor_node(own<conveyor_node> &&dep, Func &&func, - ErrorFunc &&error_func) - : convert_conveyor_node_base(std::move(dep)), func_{std::move(func)}, - error_func_{std::move(error_func)} {} - - void get_impl(error_or_value &err_or_val) noexcept override { - error_or<unfix_void<DepT>> dep_eov; - error_or<unfix_void<remove_error_or<T>>> &eov = - err_or_val.as<unfix_void<remove_error_or<T>>>(); - if (child_mixin_.child) { - child_mixin_.child->get_result(dep_eov); - if (dep_eov.is_value()) { - try { - - eov = fix_void_caller<T, DepT>::apply( - func_, std::move(dep_eov.get_value())); - } catch (const std::bad_alloc &) { - eov = make_error<err::out_of_memory>("Out of memory"); - } catch (const std::exception &) { - eov = make_error<err::invalid_state>( - "Exception in chain occured. Return ErrorOr<T> if you " - "want to handle errors which are recoverable"); - } - } else if (dep_eov.is_error()) { - eov = error_func_(std::move(dep_eov.get_error())); - } else { - eov = make_error<err::invalid_state>("No value set in dependency"); - } - } else { - eov = make_error<err::invalid_state>("Conveyor doesn't have child"); - } - } -}; - -class sink_conveyor_node final : public conveyor_node, - public conveyor_event_storage { -private: - conveyor_node_with_child_mixin child_mixin_; - conveyor_sink_set *conveyor_sink_; - -public: - sink_conveyor_node(own<conveyor_node> node, conveyor_sink_set &conv_sink) - : conveyor_event_storage{}, child_mixin_{std::move(node), *this}, - conveyor_sink_{&conv_sink} {} - - sink_conveyor_node(own<conveyor_node> node) - : conveyor_event_storage{}, child_mixin_{std::move(node), *this}, - conveyor_sink_{nullptr} {} - - // Event only queued if a critical error occured - void fire() override { - // Queued for destruction of children, because this acts as a sink and - // no other event should be here - child_mixin_.child = nullptr; - - if (conveyor_sink_) { - conveyor_sink_->destroy_sink_conveyor_node(*this); - conveyor_sink_ = nullptr; - } - } - - // ConveyorStorage - size_t space() const override { return 1; } - size_t queued() const override { return 0; } - - // ConveyorNode - void get_result(error_or_value &err_or_val) noexcept override { - err_or_val.as<void_t>() = - make_error<err::invalid_state>("In a sink node no result can be returned"); - } - - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee) noexcept override { - return child_mixin_.swap_child(std::move(swapee)); - } - - // ConveyorStorage - void child_has_fired() override { - if (child_mixin_.child) { - error_or<void> dep_eov; - child_mixin_.child->get_result(dep_eov); - if (dep_eov.is_error()) { - if (dep_eov.get_error().is_critical()) { - if (!is_armed()) { - arm_last(); - } - } - if (conveyor_sink_) { - conveyor_sink_->fail(std::move(dep_eov.get_error())); - } - } - } - } - - /* - * No parent needs to be fired since we always have space - */ - void parent_has_fired() override {} - - conveyor_storage *next_storage() override { - // Should never happen though - assert(false); - return nullptr; - // return static_cast<ConveyorStorage*>(this); - } -}; - -class immediate_conveyor_node_base : public conveyor_node, - public conveyor_event_storage { -private: -public: - immediate_conveyor_node_base(); - - virtual ~immediate_conveyor_node_base() = default; - - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee) noexcept override { - (void)swapee; - return make_error<err::not_supported>("Node doesn't support swapping"); - } - - conveyor_storage *next_storage() noexcept override { - return static_cast<conveyor_storage *>(this); - } -}; - -template <typename T> -class immediate_conveyor_node final : public immediate_conveyor_node_base { -private: - error_or<fix_void<T>> value_; - uint8_t retrieved_; - -public: - immediate_conveyor_node(fix_void<T> &&val); - immediate_conveyor_node(error &&error); - - // ConveyorStorage - size_t space() const override; - size_t queued() const override; - - void child_has_fired() override; - void parent_has_fired() override; - - // ConveyorNode - void get_result(error_or_value &err_or_val) noexcept override { - if (retrieved_ > 0) { - err_or_val.as<fix_void<T>>() = - make_error<err::buffer_exhausted>("Already taken value"); - } else { - err_or_val.as<fix_void<T>>() = std::move(value_); - } - if (queued() > 0) { - ++retrieved_; - } - } - - // Event - void fire() override; -}; - -/* - * Collects every incoming value and throws it in one lane - */ -class merge_conveyor_node_base : public conveyor_node, - public conveyor_event_storage { -public: - merge_conveyor_node_base(); - - virtual ~merge_conveyor_node_base() = default; - - conveyor_storage *next_storage() noexcept override { - return static_cast<conveyor_storage *>(this); - } -}; - -template <typename T> -class merge_conveyor_node : public merge_conveyor_node_base { -private: - class appendage final : public conveyor_node, public conveyor_storage { - public: - own<conveyor_node> child; - merge_conveyor_node *merger; - - maybe<error_or<fix_void<T>>> error_or_value_; - - public: - appendage(own<conveyor_node> n, merge_conveyor_node &m) - : conveyor_storage{}, child{std::move(n)}, merger{&m}, - error_or_value_{std::nullopt} {} - - bool child_storage_has_element_queued() const { - if (!child) { - return false; - } - conveyor_storage *storage = child->next_storage(); - if (storage) { - return storage->queued() > 0; - } - return false; - } - - void get_appendage_result(error_or_value &eov); - - /** - * ConveyorNode - */ - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&swapee_) override; - - conveyor_storage *next_storage() noexcept override { - return static_cast<conveyor_storage *>(this); - } - - void get_result(error_or_value &err_or_val) override; - - /** - * ConveyorStorage - */ - size_t space() const override; - - size_t queued() const override; - - void child_has_fired() override; - - void parent_has_fired() override; - - void set_parent(conveyor_storage *par) override; - }; - - friend class merge_conveyor_node_data<T>; - friend class appendage; - - our<merge_conveyor_node_data<T>> data_; - size_t next_appendage_ = 0; - -public: - merge_conveyor_node(our<merge_conveyor_node_data<T>> data); - ~merge_conveyor_node(); - // ConveyorNode - error_or<own<conveyor_node>> - swap_child(own<conveyor_node> &&c) noexcept override; - - // Event - void get_result(error_or_value &err_or_val) noexcept override; - - void fire() override; - - // ConveyorStorage - size_t space() const override; - size_t queued() const override; - void child_has_fired() override; - void parent_has_fired() override; -}; - -template <typename T> class merge_conveyor_node_data { -public: - std::vector<own<typename merge_conveyor_node<T>::appendage>> appendages; - - merge_conveyor_node<T> *merger = nullptr; - -public: - void attach(conveyor<T> conv); - - void governing_node_destroyed(); -}; - -/* -class JoinConveyorNodeBase : public ConveyorNode, public ConveyorEventStorage { -private: - -public: -}; - -template <typename... Args> -class JoinConveyorNode final : public JoinConveyorNodeBase { -private: - template<typename T> - class Appendage : public ConveyorEventStorage { - private: - Maybe<T> data = std::nullopt; - - public: - size_t space() const override; - size_t queued() const override; - - void fire() override; - void get_result(ErrorOrValue& eov) override; - }; - - std::tuple<Appendage<Args>...> appendages; - -public: -}; - -*/ - -} // namespace saw - -#include "async.tmpl.h" diff --git a/c++/async/async.tmpl.h b/c++/async/async.tmpl.h deleted file mode 100644 index 9569f60..0000000 --- a/c++/async/async.tmpl.h +++ /dev/null @@ -1,767 +0,0 @@ -#pragma once - -#include <forstio/core/common.h> -#include <forstio/core/error.h> - -#include <cassert> -// Template inlining - -namespace saw { - -template <typename Func> conveyor_result<Func, void> execLater(Func &&func) { - conveyor<void> conveyor{fix_void<void>{}}; - return conveyor.then(std::move(func)); -} - -template <typename T> -conveyor<T>::conveyor(fix_void<T> value) : conveyor_base(nullptr) { - // Is there any way to do this? - // @todo new conveyor_base constructor for Immediate values - - own<immediate_conveyor_node<fix_void<T>>> immediate = - heap<immediate_conveyor_node<fix_void<T>>>(std::move(value)); - - if (!immediate) { - return; - } - - node_ = std::move(immediate); -} - -template <typename T> -conveyor<T>::conveyor(error &&err) : conveyor_base(nullptr) { - own<immediate_conveyor_node<fix_void<T>>> immediate = - heap<immediate_conveyor_node<fix_void<T>>>(std::move(err)); - - if (!immediate) { - return; - } - - node_ = std::move(immediate); -} - -template <typename T> -conveyor<T>::conveyor(own<conveyor_node> node_p) - : conveyor_base{std::move(node_p)} {} - -template <typename T> -template <typename Func, typename ErrorFunc> -conveyor_result<Func, T> conveyor<T>::then(Func &&func, - ErrorFunc &&error_func) { - own<conveyor_node> conversion_node = - heap<convert_conveyor_node<fix_void<return_type<Func, T>>, fix_void<T>, - Func, ErrorFunc>>( - std::move(node_), std::move(func), std::move(error_func)); - - return conveyor<remove_error_or<return_type<Func, T>>>::to_conveyor( - std::move(conversion_node)); -} - -template <typename T> conveyor<T> conveyor<T>::buffer(size_t size) { - SAW_ASSERT(node_) { return conveyor<T>{own<conveyor_node>{nullptr}}; } - conveyor_storage *storage = node_->next_storage(); - SAW_ASSERT(storage) { return conveyor<T>{own<conveyor_node>{nullptr}}; } - - own<queue_buffer_conveyor_node<fix_void<T>>> storage_node = - heap<queue_buffer_conveyor_node<fix_void<T>>>(std::move(node_), size); - - conveyor_storage *storage_ptr = - static_cast<conveyor_storage *>(storage_node.get()); - - storage->set_parent(storage_ptr); - return conveyor<T>{std::move(storage_node)}; -} - -template <typename T> -template <typename... Args> -conveyor<T> conveyor<T>::attach(Args &&...args) { - own<attach_conveyor_node<Args...>> attach_node = - heap<attach_conveyor_node<Args...>>(std::move(node_), - std::move(args...)); - return conveyor<T>{std::move(attach_node)}; -} - -template <typename T> -std::pair<conveyor<T>, merge_conveyor<T>> conveyor<T>::merge() { - our<merge_conveyor_node_data<T>> data = - share<merge_conveyor_node_data<T>>(); - - own<merge_conveyor_node<T>> merge_node = heap<merge_conveyor_node<T>>(data); - - SAW_ASSERT(node_) { - return std::make_pair(conveyor<T>{own<conveyor_node>{nullptr}}, - merge_conveyor<T>{}); - } - conveyor_storage *storage = node_->next_storage(); - SAW_ASSERT(storage) { - return std::make_pair(conveyor<T>{own<conveyor_node>{nullptr}}, - merge_conveyor<T>{}); - } - - data->attach(conveyor<T>::to_conveyor(std::move(node_))); - - merge_conveyor<T> node_ref{data}; - - return std::make_pair(conveyor<T>{std::move(merge_node)}, - std::move(node_ref)); -} - -template <> -template <typename ErrorFunc> -conveyor_sink conveyor<void>::sink(ErrorFunc &&error_func) { - conveyor_storage *storage = node_->next_storage(); - SAW_ASSERT(storage) { return conveyor_sink{}; } - - own<sink_conveyor_node> sink_node = - heap<sink_conveyor_node>(std::move(node_)); - conveyor_storage *storage_ptr = - static_cast<conveyor_storage *>(sink_node.get()); - - storage->set_parent(storage_ptr); - - return conveyor_sink{std::move(sink_node)}; -} - -void detach_conveyor(conveyor<void> &&conveyor); - -template <typename T> -template <typename ErrorFunc> -void conveyor<T>::detach(ErrorFunc &&func) { - detach_conveyor(std::move(then([](T &&) {}, std::move(func)))); -} - -template <> -template <typename ErrorFunc> -void conveyor<void>::detach(ErrorFunc &&func) { - detach_conveyor(std::move(then([]() {}, std::move(func)))); -} - -template <typename T> -conveyor<T> conveyor<T>::to_conveyor(own<conveyor_node> node) { - return conveyor<T>{std::move(node)}; -} - -template <typename T> -own<conveyor_node> conveyor<T>::from_conveyor(conveyor<T> conveyor) { - return std::move(conveyor.node_); -} - -template <typename T> error_or<fix_void<T>> conveyor<T>::take() { - SAW_ASSERT(node_) { - return error_or<fix_void<T>>{ - make_error<err::invalid_state>("conveyor in invalid state")}; - } - conveyor_storage *storage = node_->next_storage(); - if (storage) { - if (storage->queued() > 0) { - error_or<fix_void<T>> result; - node_->get_result(result); - return result; - } else { - return error_or<fix_void<T>>{ - make_error<err::buffer_exhausted>("conveyor buffer has no elements")}; - } - } else { - return error_or<fix_void<T>>{ - make_error<err::invalid_state>("conveyor node has no child storage")}; - } -} - -template <typename T> conveyor_and_feeder<T> new_conveyor_and_feeder() { - own<adapt_conveyor_feeder<fix_void<T>>> feeder = - heap<adapt_conveyor_feeder<fix_void<T>>>(); - own<adapt_conveyor_node<fix_void<T>>> node = - heap<adapt_conveyor_node<fix_void<T>>>(); - - feeder->set_feedee(node.get()); - node->set_feeder(feeder.get()); - - return conveyor_and_feeder<T>{std::move(feeder), - conveyor<T>::to_conveyor(std::move(node))}; -} - -// QueueBuffer -template <typename T> void queue_buffer_conveyor_node<T>::fire() { - if (child_mixin_.child) { - if (!storage_.empty()) { - if (storage_.front().is_error()) { - if (storage_.front().get_error().is_critical()) { - child_mixin_.child = nullptr; - } - } - } - } - - bool has_space_before_fire = space() > 0; - - if (parent_) { - parent_->child_has_fired(); - if (!storage_.empty() && parent_->space() > 0) { - arm_later(); - } - } - - if (!child_mixin_.child) { - while (!storage_.empty()) { - storage_.pop(); - } - return; - } - - conveyor_storage *ch_storage = child_mixin_.child->next_storage(); - if (ch_storage && !has_space_before_fire) { - ch_storage->parent_has_fired(); - } -} - -template <typename T> -void queue_buffer_conveyor_node<T>::get_result(error_or_value &eov) noexcept { - error_or<T> &err_or_val = eov.as<T>(); - err_or_val = std::move(storage_.front()); - storage_.pop(); -} - -template <typename T> size_t queue_buffer_conveyor_node<T>::space() const { - return max_store_ - storage_.size(); -} - -template <typename T> size_t queue_buffer_conveyor_node<T>::queued() const { - return storage_.size(); -} - -template <typename T> void queue_buffer_conveyor_node<T>::child_has_fired() { - if (child_mixin_.child && storage_.size() < max_store_) { - error_or<T> eov; - child_mixin_.child->get_result(eov); - - if (eov.is_error()) { - if (eov.get_error().is_critical()) { - } - } - - storage_.push(std::move(eov)); - if (!is_armed()) { - arm_later(); - } - } -} - -template <typename T> void queue_buffer_conveyor_node<T>::parent_has_fired() { - SAW_ASSERT(parent_) { return; } - - if (parent_->space() == 0) { - return; - } - - if (queued() > 0) { - arm_later(); - } -} - -template <typename T> -immediate_conveyor_node<T>::immediate_conveyor_node(fix_void<T> &&val) - : value_{std::move(val)}, retrieved_{0} {} - -template <typename T> -immediate_conveyor_node<T>::immediate_conveyor_node(error &&error) - : value_{std::move(error)}, retrieved_{0} {} - -template <typename T> size_t immediate_conveyor_node<T>::space() const { - return 0; -} - -template <typename T> size_t immediate_conveyor_node<T>::queued() const { - return retrieved_ > 1 ? 0 : 1; -} - -template <typename T> void immediate_conveyor_node<T>::child_has_fired() { - // Impossible case - assert(false); -} - -template <typename T> void immediate_conveyor_node<T>::parent_has_fired() { - SAW_ASSERT(parent_) { return; } - assert(parent_->space() > 0); - - if (queued() > 0) { - arm_next(); - } -} - -template <typename T> void immediate_conveyor_node<T>::fire() { - - if (parent_) { - parent_->child_has_fired(); - if (queued() > 0 && parent_->space() > 0) { - arm_last(); - } - } -} - -template <typename T> -merge_conveyor<T>::merge_conveyor(lent<merge_conveyor_node_data<T>> d) - : data_{std::move(d)} {} - -template <typename T> merge_conveyor<T>::~merge_conveyor() {} - -template <typename T> void merge_conveyor<T>::attach(conveyor<T> conveyor) { - auto sp = data_.lock(); - SAW_ASSERT(sp) { return; } - - sp->attach(std::move(conveyor)); -} - -template <typename T> -merge_conveyor_node<T>::merge_conveyor_node(our<merge_conveyor_node_data<T>> d) - : data_{d} { - SAW_ASSERT(data_) { return; } - - data_->merger = this; -} - -template <typename T> merge_conveyor_node<T>::~merge_conveyor_node() {} - -template <typename T> -error_or<own<conveyor_node>> -merge_conveyor_node<T>::swap_child(own<conveyor_node> &&swapee_) noexcept { - (void)swapee_; - return make_error<err::invalid_state>( - "merge_conveyor_node<T>::appendage should block calls to this class"); -} - -template <typename T> -void merge_conveyor_node<T>::get_result(error_or_value &eov) noexcept { - error_or<fix_void<T>> &err_or_val = eov.as<fix_void<T>>(); - - SAW_ASSERT(data_) { return; } - - /// @todo search appendages for result - - auto &appendages = data_->appendages; - next_appendage_ = std::min(appendages.size(), next_appendage_); - - for (size_t i = next_appendage_; i < appendages.size(); ++i) { - if (appendages[i]->queued() > 0) { - err_or_val = std::move(appendages[i]->error_or_value_.value()); - appendages[i]->error_or_value_ = std::nullopt; - next_appendage_ = i + 1; - return; - } - } - for (size_t i = 0; i < next_appendage_; ++i) { - if (appendages[i]->queued() > 0) { - err_or_val = std::move(appendages[i]->error_or_value_.value()); - appendages[i]->error_or_value_ = std::nullopt; - next_appendage_ = i + 1; - return; - } - } - - err_or_val = make_error<err::invalid_state>("No value in Merge appendages"); -} - -template <typename T> void merge_conveyor_node<T>::fire() { - SAW_ASSERT(queued() > 0) { return; } - - if (parent_) { - parent_->child_has_fired(); - - if (queued() > 0 && parent_->space() > 0) { - arm_later(); - } - } -} - -template <typename T> size_t merge_conveyor_node<T>::space() const { return 0; } - -template <typename T> size_t merge_conveyor_node<T>::queued() const { - SAW_ASSERT(data_) { return 0; } - - size_t queue_count = 0; - - for (auto &iter : data_->appendages) { - queue_count += iter->queued(); - } - - return queue_count; -} - -template <typename T> void merge_conveyor_node<T>::child_has_fired() { - /// This can never happen - assert(false); -} - -template <typename T> void merge_conveyor_node<T>::parent_has_fired() { - SAW_ASSERT(parent_) { return; } - if (queued() > 0) { - if (parent_->space() > 0) { - arm_later(); - } - } -} - -/** - * merge_conveyor_node<T>::Apendage - */ - -template <typename T> -error_or<own<conveyor_node>> -merge_conveyor_node<T>::appendage::swap_child(own<conveyor_node> &&swapee_) { - own<conveyor_node> old_child = std::move(child); - - child = std::move(swapee_); - - // This case should never happen - SAW_ASSERT(old_child) { return make_error<err::invalid_state>("No child exists"); } - - return old_child; -} - -template <typename T> -void merge_conveyor_node<T>::appendage::get_result(error_or_value &eov) { - error_or<fix_void<T>> &err_or_val = eov.as<fix_void<T>>(); - - SAW_ASSERT(queued() > 0) { - err_or_val = - make_error<err::invalid_state>("No element queued in Merge appendage Node"); - return; - } - - err_or_val = std::move(error_or_value_.value()); - error_or_value_ = std::nullopt; -} - -template <typename T> size_t merge_conveyor_node<T>::appendage::space() const { - SAW_ASSERT(merger) { return 0; } - - if (error_or_value_.has_value()) { - return 0; - } - - return 1; -} - -template <typename T> size_t merge_conveyor_node<T>::appendage::queued() const { - SAW_ASSERT(merger) { return 0; } - - if (error_or_value_.has_value()) { - return 1; - } - - return 0; -} - -/// @todo delete this function. Replaced by the regular get_result -template <typename T> -void merge_conveyor_node<T>::appendage::get_appendage_result( - error_or_value &eov) { - error_or<fix_void<T>> &err_or_val = eov.as<fix_void<T>>(); - - SAW_ASSERT(queued() > 0) { - err_or_val = - make_error<err::invalid_state>("No element queued in Merge appendage Node"); - return; - } - - err_or_val = std::move(error_or_value_.value()); - error_or_value_ = std::nullopt; -} - -template <typename T> -void merge_conveyor_node<T>::appendage::child_has_fired() { - SAW_ASSERT(!error_or_value_.has_value()) { return; } - error_or<fix_void<T>> eov; - child->get_result(eov); - - error_or_value_ = std::move(eov); - - if (!merger->is_armed()) { - merger->arm_later(); - } -} - -template <typename T> -void merge_conveyor_node<T>::appendage::parent_has_fired() { - conveyor_storage *child_storage = child->next_storage(); - if (child_storage) { - child_storage->parent_has_fired(); - } -} - -template <typename T> -void merge_conveyor_node<T>::appendage::set_parent(conveyor_storage *par) { - SAW_ASSERT(merger) { return; } - - SAW_ASSERT(child) { return; } - - parent_ = par; -} - -template <typename T> -void merge_conveyor_node_data<T>::attach(conveyor<T> conv) { - auto nas = conveyor<T>::from_conveyor(std::move(conv)); - SAW_ASSERT(nas) { return; } - conveyor_storage *storage = nas->next_storage(); - SAW_ASSERT(storage) { return; } - - auto merge_node_appendage = - heap<typename merge_conveyor_node<T>::appendage>(std::move(nas), - *merger); - auto merge_node_appendage_ptr = merge_node_appendage.get(); - - storage->set_parent(merge_node_appendage.get()); - - SAW_ASSERT(merger) { return; } - - conveyor_storage *mrg_storage = merger->next_storage(); - SAW_ASSERT(mrg_storage) { return; } - - merge_node_appendage->set_parent(mrg_storage); - - appendages.push_back(std::move(merge_node_appendage)); - - /// @todo return this. necessary? maybe for the weird linking setup - /// maybe not - // return merge_node_appendage_ptr; -} - -template <typename T> -void merge_conveyor_node_data<T>::governing_node_destroyed() { - appendages.clear(); - merger = nullptr; -} - -template <typename T> adapt_conveyor_feeder<T>::~adapt_conveyor_feeder() { - if (feedee_) { - feedee_->set_feeder(nullptr); - feedee_ = nullptr; - } -} - -template <typename T> -void adapt_conveyor_feeder<T>::set_feedee(adapt_conveyor_node<T> *feedee_p) { - feedee_ = feedee_p; -} - -template <typename T> void adapt_conveyor_feeder<T>::feed(T &&value) { - if (feedee_) { - feedee_->feed(std::move(value)); - } -} - -template <typename T> void adapt_conveyor_feeder<T>::fail(error &&error) { - if (feedee_) { - feedee_->fail(std::move(error)); - } -} - -template <typename T> size_t adapt_conveyor_feeder<T>::queued() const { - if (feedee_) { - return feedee_->queued(); - } - return 0; -} - -template <typename T> size_t adapt_conveyor_feeder<T>::space() const { - if (feedee_) { - return feedee_->space(); - } - return 0; -} - -template <typename T> -error adapt_conveyor_feeder<T>::swap(conveyor<T> &&conv) noexcept { - SAW_ASSERT(feedee_) { return make_error<err::invalid_state>("No feedee connected"); } - - auto node = conveyor<T>::from_conveyor(std::move(conv)); - - feedee_->swap_child(std::move(node)); - - return no_error(); -} - -template <typename T> -adapt_conveyor_node<T>::adapt_conveyor_node() : conveyor_event_storage{} {} - -template <typename T> adapt_conveyor_node<T>::~adapt_conveyor_node() { - if (feeder_) { - feeder_->set_feedee(nullptr); - feeder_ = nullptr; - } -} - -template <typename T> -error_or<own<conveyor_node>> -adapt_conveyor_node<T>::swap_child(own<conveyor_node> &&swapee) noexcept { - // This should return the owning pointer of this instance - auto myself_err = parent_node_.swap_child_of_parent(std::move(swapee)); - - if (myself_err.is_error()) { - return myself_err; - } - - auto &myself = myself_err.get_value(); - - assert(myself.get() == this); - - return myself_err; -} - -template <typename T> -conveyor_storage *adapt_conveyor_node<T>::next_storage() noexcept { - return static_cast<conveyor_storage *>(this); -} - -template <typename T> -void adapt_conveyor_node<T>::notify_parent_attached( - conveyor_node &par) noexcept { - parent_node_.change_parent(&par); -} - -template <typename T> -void adapt_conveyor_node<T>::set_feeder(adapt_conveyor_feeder<T> *feeder_p) { - feeder_ = feeder_p; -} - -template <typename T> void adapt_conveyor_node<T>::feed(T &&value) { - storage_.push(std::move(value)); - arm_next(); -} - -template <typename T> void adapt_conveyor_node<T>::fail(error &&error) { - storage_.push(std::move(error)); - arm_next(); -} - -template <typename T> size_t adapt_conveyor_node<T>::queued() const { - return storage_.size(); -} - -template <typename T> size_t adapt_conveyor_node<T>::space() const { - return std::numeric_limits<size_t>::max() - storage_.size(); -} - -template <typename T> -void adapt_conveyor_node<T>::get_result(error_or_value &err_or_val) { - if (!storage_.empty()) { - err_or_val.as<T>() = std::move(storage_.front()); - storage_.pop(); - } else { - err_or_val.as<T>() = make_error<err::invalid_state>( - "Signal for retrieval of storage sent even though no " - "data is present"); - } -} - -template <typename T> void adapt_conveyor_node<T>::child_has_fired() { - // Adapt node has no children - assert(false); -} - -template <typename T> void adapt_conveyor_node<T>::parent_has_fired() { - SAW_ASSERT(parent_) { return; } - - if (parent_->space() == 0) { - return; - } -} - -template <typename T> void adapt_conveyor_node<T>::fire() { - if (parent_) { - parent_->child_has_fired(); - - if (storage_.size() > 0) { - arm_later(); - } - } -} - -template <typename T> one_time_conveyor_feeder<T>::~one_time_conveyor_feeder() { - if (feedee_) { - feedee_->set_feeder(nullptr); - feedee_ = nullptr; - } -} - -template <typename T> -void one_time_conveyor_feeder<T>::set_feedee( - one_time_conveyor_node<T> *feedee_p) { - feedee_ = feedee_p; -} - -template <typename T> void one_time_conveyor_feeder<T>::feed(T &&value) { - if (feedee_) { - feedee_->feed(std::move(value)); - } -} - -template <typename T> void one_time_conveyor_feeder<T>::fail(error &&error) { - if (feedee_) { - feedee_->fail(std::move(error)); - } -} - -template <typename T> size_t one_time_conveyor_feeder<T>::queued() const { - if (feedee_) { - return feedee_->queued(); - } - return 0; -} - -template <typename T> size_t one_time_conveyor_feeder<T>::space() const { - if (feedee_) { - return feedee_->space(); - } - return 0; -} - -template <typename T> one_time_conveyor_node<T>::~one_time_conveyor_node() { - if (feeder_) { - feeder_->set_feedee(nullptr); - feeder_ = nullptr; - } -} - -template <typename T> -void one_time_conveyor_node<T>::set_feeder( - one_time_conveyor_feeder<T> *feeder_p) { - feeder_ = feeder_p; -} - -template <typename T> void one_time_conveyor_node<T>::feed(T &&value) { - storage_ = std::move(value); - arm_next(); -} - -template <typename T> void one_time_conveyor_node<T>::fail(error &&error) { - storage_ = std::move(error); - arm_next(); -} - -template <typename T> size_t one_time_conveyor_node<T>::queued() const { - return storage_.has_value() ? 1 : 0; -} - -template <typename T> size_t one_time_conveyor_node<T>::space() const { - return passed_ ? 0 : 1; -} - -template <typename T> -void one_time_conveyor_node<T>::get_result(error_or_value &err_or_val) { - if (storage_.has_value()) { - err_or_val.as<T>() = std::move(storage_.value()); - storage_ = std::nullopt; - } else { - err_or_val.as<T>() = make_error<err::invalid_state>( - "Signal for retrieval of storage sent even though no " - "data is present"); - } -} - -template <typename T> void one_time_conveyor_node<T>::fire() { - if (parent_) { - parent_->child_has_fired(); - } -} - -} // namespace saw diff --git a/c++/codec-json/.nix/derivation.nix b/c++/codec-json/.nix/derivation.nix deleted file mode 100644 index 3738e43..0000000 --- a/c++/codec-json/.nix/derivation.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-codec-json"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/codec-json/SConscript b/c++/codec-json/SConscript deleted file mode 100644 index 772ac0b..0000000 --- a/c++/codec-json/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -codec_json_env = env.Clone(); - -codec_json_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -codec_json_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += codec_json_env.sources; -env.headers += codec_json_env.headers; - -## Shared lib -objects_shared = [] -codec_json_env.add_source_files(objects_shared, codec_json_env.sources, shared=True); -codec_json_env.library_shared = codec_json_env.SharedLibrary('#build/forstio-codec-json', [objects_shared]); - -## Static lib -objects_static = [] -codec_json_env.add_source_files(objects_static, codec_json_env.sources, shared=False); -codec_json_env.library_static = codec_json_env.StaticLibrary('#build/forstio-codec-json', [objects_static]); - -# Set Alias -env.Alias('library_codec_json', [codec_json_env.library_shared, codec_json_env.library_static]); - -env.targets += ['library_codec_json']; - -# Install -env.Install('$prefix/lib/', [codec_json_env.library_shared, codec_json_env.library_static]); -env.Install('$prefix/include/forstio/codec/json/', [codec_json_env.headers]); diff --git a/c++/codec-json/SConstruct b/c++/codec-json/SConstruct deleted file mode 100644 index edd5f57..0000000 --- a/c++/codec-json/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-codec']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/codec-json/json.h b/c++/codec-json/json.h deleted file mode 100644 index 56cadc0..0000000 --- a/c++/codec-json/json.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include <forstio/core/buffer.h> -#include <forstio/core/common.h> -#include <forstio/codec/data.h> - -#include <algorithm> - -namespace saw { -namespace encode { -struct Json {}; -} - -template<typename Schema> -class data<Schema, encode::Json> { -private: - ring_buffer buffer_; -public: - data():buffer_{}{} - - data(std::size_t ring_size_):buffer_{ring_size_}{} - - data(ring_buffer buff_): - buffer_{std::move(buff_)} - {} - - data(const std::string_view& view__): - buffer_{view__.size()} - { - auto ptr = reinterpret_cast<const uint8_t*>(view__.data()); - if(!ptr){ - return; - } - buffer_.push(*ptr, view__.size()); - } - - buffer& get_buffer(){ - return buffer_; - } - - const buffer& get_buffer() const { - return buffer_; - } - - error push(uint8_t val){ - return buffer_.push(val); - } - - std::size_t get_size() const { - return buffer_.read_composite_length(); - } - - uint8_t& at(std::size_t i){ - return buffer_.read(i); - } - - const uint8_t& at(std::size_t i) const { - return buffer_.read(i); - } -}; -} - -#include "json.tmpl.h" - -namespace saw { - -/** - * Codec class for json - */ -template<typename Schema> -class codec<Schema, encode::Json> { -public: - struct config { - size_t depth = 16; - size_t length = 1024; - }; -private: - config cfg_; -public: - /** - * Default constructor - */ - codec(){} - - /** - * Constructor - */ - codec(config cfg__):cfg_{std::move(cfg__)}{} - - SAW_FORBID_COPY(codec); - SAW_DEFAULT_MOVE(codec); - - template <typename FromEncoding> - error_or<void> encode(const data<Schema, FromEncoding>& from_encode, data<Schema, encode::Json>& to_encode){ - // To Be encoded - buffer_view buff_v{to_encode.get_buffer()}; - auto eov = impl::json_encode<Schema, Schema, FromEncoding>::encode(from_encode, buff_v); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - to_encode.get_buffer().write_advance(buff_v.write_offset()); - - return void_t{}; - } - - template <typename ToEncoding> - error_or<void> decode(data<Schema, encode::Json>& from_decode, data<Schema, ToEncoding>& to_decode){ - buffer_view buff_v{from_decode.get_buffer()}; - - auto eov = impl::json_decode<Schema, Schema, ToEncoding>::decode(buff_v, to_decode); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - from_decode.get_buffer().read_advance(buff_v.read_offset()); - - return void_t {}; - } -}; -} - diff --git a/c++/codec-json/json.tmpl.h b/c++/codec-json/json.tmpl.h deleted file mode 100644 index 4b3a1a2..0000000 --- a/c++/codec-json/json.tmpl.h +++ /dev/null @@ -1,734 +0,0 @@ -#pragma once - -#include <charconv> -#include <sstream> - -#include <iostream> - -namespace saw { -namespace impl { -template<typename Schema, typename RootSchema, typename FromEncode> -class json_encode { - static_assert(always_false<Schema, RootSchema, FromEncode>, "This schema type is not being handled by the json encoding."); -}; - -template<typename T, size_t N, typename RootSchema, typename FromEncode> -struct json_encode<schema::Primitive<T,N>, RootSchema, FromEncode> { - static error_or<void> encode(const data<schema::Primitive<T,N>, FromEncode>& from, buffer& to) { - auto val = from.get(); - std::array<uint8_t, 256> data; - auto tc_result = std::to_chars(reinterpret_cast<char*>(data.data()), reinterpret_cast<char*>(data.data())+data.size(), val); - - if(tc_result.ec != std::errc{}){ - return make_error<err::critical>(); - } - - size_t bytes_written = 0; - for(char* ptr = reinterpret_cast<char*>(data.data()); ptr != tc_result.ptr; ++ptr){ - ++bytes_written; - } - - auto& buff = to; - error err = buff.write_require_length(bytes_written); - if(!err.template is_type<err::no_error>()){ - return std::move(err); - } - - for(char* ptr = reinterpret_cast<char*>(data.data()); ptr != tc_result.ptr; ++ptr){ - uint8_t* un_ptr = reinterpret_cast<uint8_t*>(ptr); - buff.push(un_ptr[0]); - } - - return void_t{}; - } -}; - -template<typename RootSchema, typename FromEncode> -struct json_encode<schema::String, RootSchema, FromEncode> { - static error_or<void> encode(const data<schema::String, FromEncode>& from, buffer& to) { - { - auto err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - for(std::size_t i = 0; i < from.size(); ++i){ - auto err = to.push(from.get_at(i)); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - { - auto err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename... T, typename RootSchema, typename FromEncode> -struct json_encode<schema::Tuple<T...>, RootSchema, FromEncode> { - template<size_t i> - static error_or<void> encode_element(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to){ - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<i>(), to); - - if(eov.is_error()){ - return eov; - } - - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = to.push(','); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('['); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push(']'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename T, size_t D, typename RootSchema, typename FromEncode> -struct json_encode<schema::Array<T,D>, RootSchema, FromEncode> { - template<size_t Level> - static error_or<void> encode_level(const data<schema::Array<T,D>, FromEncode>& from, buffer& to, std::array<std::size_t, D>& index){ - if constexpr (Level == D){ - auto eov = json_encode<T, RootSchema, FromEncode>::encode(from.at(index), to); - if(eov.is_error()){ - return eov; - } - } else { - { - auto err = to.push('['); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - for(std::size_t i = 0; i < from.get_dim_size(Level); ++i){ - if( i > 0 ){ - auto err = to.push(','); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - { - index[Level] = i; - auto eov = encode_level<Level+1>(from, to, index); - if(eov.is_error()){ - return eov; - } - } - } - { - auto err = to.push(']'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Array<T,D>, FromEncode>& from, buffer& to) { - std::array<std::size_t, D> index; - return encode_level<0>(from, to, index); - } -}; - -template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode> -struct json_encode<schema::Struct<schema::Member<T,Key>...>, RootSchema, FromEncode> { - - template<size_t i> - static error_or<void> encode_element(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){ - // Encode the name - { - std::string_view view = parameter_key_pack_type<i, Key...>::literal.view(); - error err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size()); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - // Add the separator - { - auto eov_ele = to.push(':'); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - - // Encode the value - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to); - - // Go to the next element - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = to.push(','); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - - return void_t{}; - } - static error_or<void> encode(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('{'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push('}'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode> -struct json_encode<schema::Union<schema::Member<T,Key>...>, RootSchema, FromEncode> { - - template<size_t i> - static error_or<void> encode_element(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){ - if(from.template holds_alternative<typename parameter_key_pack_type<i, Key...>::literal>()){ - // Encode the name - { - std::string_view view = parameter_key_pack_type<i, Key...>::literal.view(); - error err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size()); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - // Add the separator - { - auto eov_ele = to.push(':'); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - - // Encode the value - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to); - } - // Go to the next element - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - - return void_t{}; - } - static error_or<void> encode(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('{'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push('}'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -struct json_helper { - static bool is_whitespace(int8_t ch) { - return ch == '\t' || ch == ' ' || ch == '\r' || ch == '\n'; - } - - static void skip_whitespace(buffer_view& buff) { - while(buff.read_composite_length() > 0 && json_helper::is_whitespace(buff.read())) { - buff.read_advance(1); - } - } -}; - -template<typename Schema, typename RootSchema, typename ToDecode> -struct json_decode; - -template<typename T, size_t N, typename RootSchema, typename ToDecode> -struct json_decode<schema::Primitive<T,N>, RootSchema, ToDecode> { - static error_or<void> decode(buffer_view& buff, data<schema::Primitive<T,N>, ToDecode>& to) { - assert( - ( buff.read() >= '0' && buff.read() <= '9') - || ( buff.read() == '+' || buff.read() == '-') - ); - - std::size_t offset = 0; - - if (buff.read() == '-'){ - ++offset; - } else if (buff.read() == '+'){ - return make_error<err::not_supported>(); - } - if (offset >= buff.read_composite_length()) { - return make_error<err::buffer_exhausted>(); - } - if (buff.read(offset) >= '1' && buff.read(offset) <= '9') { - ++offset; - - if(offset >= buff.read_composite_length()) { - return make_error<err::buffer_exhausted>(); - } - - while(1){ - if (buff.read(offset) >= '0' && buff.read(offset) <= '9') { - ++offset; - - if(offset >= buff.read_composite_length()) { - break; - } - continue; - } - break; - } - } else if (buff.read(offset) == '0' ) { - ++offset; - } else { - return make_error<err::buffer_exhausted>(); - } - - { - std::string_view num_view{reinterpret_cast<char*>(&buff.read()), offset}; - typename native_data_type<schema::Primitive<T,N>>::type result; - auto fc_result = std::from_chars(num_view.data(), num_view.data() + num_view.size(), result); - if(fc_result.ec != std::errc{}){ - return make_error<err::invalid_state>(); - } - - to.set(result); - } - buff.read_advance(offset); - - return void_t{}; - } -}; - -template<typename RootSchema, typename ToDecode> -struct json_decode<schema::String, RootSchema, ToDecode> { - static error_or<void> decode(buffer_view& buff, data<schema::String, ToDecode>& to){ - assert(buff.read() == '"'); - buff.read_advance(1); - - std::stringstream iss; - bool string_done = false; - while(!string_done){ - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - switch(buff.read()){ - case '\\':{ - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - switch(buff.read()){ - case '\\': - case '/': - case '"': - iss<< buff.read(); - break; - case 'b': - iss<<'\b'; - break; - case 'f': - iss<<'\f'; - break; - case 'n': - iss<<'\n'; - break; - case 'r': - iss<<'\r'; - break; - case 't': - iss<<'\t'; - break; - case 'u': { - buff.read_advance(1); - if(buff.read_composite_length() < 4){ - return make_error<err::buffer_exhausted>(); - } - iss<<'?'; - iss<<'?'; - iss<<'?'; - iss<<'?'; - - buff.read_advance(3); - } break; - } - } break; - case '"': - string_done = true; - break; - default:{ - // Avoids Control sequences - if(buff.read() >= ' ' && buff.read() <= '~'){ - iss<<buff.read(); - } - // Avoid Unicode - else if (buff.read() < 0) { - do { - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } while( buff.read() < 0 ); - iss<<'?'; - } - break; - } - } - buff.read_advance(1); - } - - std::string raw = iss.str(); - to.set(std::move(raw)); - - return void_t{}; - } -}; - -template<typename... T, string_literal... Lits, typename RootSchema, typename ToDecode> -struct json_decode<schema::Struct<schema::Member<T,Lits>...>, RootSchema, ToDecode> { - template<std::size_t i> - static error_or<void> decode_field_search(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields, const data<schema::String,ToDecode>& search_name){ - if constexpr ( i < sizeof...(T)){ - using Type = typename parameter_pack_type<i, T...>::type; - constexpr static string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - if(search_name == Literal.view()){ - if(fields[i]){ - return make_error<err::invalid_state>(); - } - fields[i] = true; - auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<Literal>()); - if(eov.is_error()){ - return eov; - } - }else { - decode_field_search<i+1>(buff, to, fields, search_name); - } - }else { - return make_error<err::invalid_state>(); - } - return void_t{}; - } - - static error_or<void> decode_fields(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields){ - for(;;){ - data<schema::String, ToDecode> name; - auto eov = json_decode<schema::String, RootSchema, ToDecode>::decode(buff, name); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - if(buff.read() != ':'){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - { - auto eov = decode_field_search<0>(buff, to, fields, name); - if(eov.is_error()){ - return eov; - } - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - if(buff.read() == ','){ - buff.read_advance(1); - }else if(buff.read() == '}'){ - // If not all fields are set, the dataset is incomplete - for(auto& iter : fields){ - if(!iter){ - return make_error<err::invalid_state>(); - } - } - buff.read_advance(1); - return void_t{}; - }else{ - return make_error<err::invalid_state>(); - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to){ - std::array<bool, sizeof...(T)> found_fields; - std::fill(found_fields.begin(), found_fields.end(), false); - - assert(buff.read() == '{'); - buff.read_advance(1); - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - // Check if there are no elements present in the JSON Struct - if(buff.read() == '}'){ - if(sizeof...(T) > 0){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - return void_t{}; - } - - auto eov = decode_fields(buff, to, found_fields); - if(eov.is_error()){ - return eov; - } - - return void_t{}; - } -}; - -template<typename... T, typename RootSchema, typename ToDecode> -struct json_decode<schema::Tuple<T...>, RootSchema, ToDecode> { - template<std::size_t i> - static error_or<void> decode_element(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){ - if constexpr (i < sizeof...(T)){ - if constexpr ( i > 0 ){ - if(buff.read() != ','){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } - using Type = typename parameter_pack_type<i, T...>::type; - - auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<i>()); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - eov = decode_element<i+1>(buff, to); - if(eov.is_error()){ - return eov; - } - }else{ - if(buff.read() != ']'){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){ - assert(buff.read() == '['); - buff.read_advance(1); - - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - auto eov = decode_element<0>(buff, to); - if(eov.is_error()){ - return eov; - } - - return void_t{}; - } -}; - -// The whole std::vector approach is hacky af. ToDo change it maybe? -template<typename T, size_t D, typename RootSchema, typename ToDecode> -struct json_decode<schema::Array<T,D>, RootSchema, ToDecode> { - template<size_t Level> - static error_or<void> decode_flat_level(buffer_view& buff, std::vector<data<T, encode::Native>>& to, std::array<std::size_t, D>& index, std::array<std::size_t, D>& dims, bool log_dim){ - if constexpr (Level == D) { - json_helper::skip_whitespace(buff); - try { - to.push_back({}); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - auto eov = json_decode<T, RootSchema, ToDecode>::decode(buff, to.back()); - if(eov.is_error()){ - return eov; - } - } else { - assert(buff.read() == '['); - buff.read_advance(1); - - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - - index[Level] = 0; - for(;;){ - // We should have an element right now - auto eov = decode_flat_level<Level+1>(buff,to,index,dims, index[Level] == 0 && log_dim); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - - ++index[Level]; - if(buff.read() == ','){ - buff.read_advance(1); - } else if(buff.read() == ']'){ - buff.read_advance(1); - break; - } else { - return make_error<err::invalid_state>(); - } - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - } - if(log_dim){ - dims[Level] = index[Level]; - }else if (dims[Level] != index[Level]){ - return make_error<err::invalid_state>(); - } - } - return void_t{}; - } - - template<std::size_t Level> - static error_or<void> decode_unflat_level(std::vector<data<T,encode::Native>>& flat, data<schema::Array<T,D>, ToDecode>& to, std::array<std::size_t, D>& index, std::size_t& flat_index) { - if constexpr ( Level == D ){ - auto& flat_data = flat.at(flat_index); - to.at(index) = std::move(flat_data); - ++flat_index; - }else { - const std::size_t dim_size = to.get_dim_size(Level); - for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ - - auto eov = decode_unflat_level<Level+1>(flat, to, index, flat_index); - if(eov.is_error()){ - return eov; - } - } - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Array<T,D>, ToDecode>& to){ - std::array<std::size_t, D> index; - std::array<std::size_t, D> dims; - std::fill(dims.begin(), dims.end(), 0); - std::vector<data<T,encode::Native>> flat_array; - auto eov = decode_flat_level<0>(buff, flat_array, index, dims, true); - if(eov.is_error()){ - return eov; - } - - to = {dims}; - std::size_t flat_index = 0; - - return decode_unflat_level<0>(flat_array, to, index, flat_index); - } -}; -} -} diff --git a/c++/codec-minecraft/.nix/derivation.nix b/c++/codec-minecraft/.nix/derivation.nix deleted file mode 100644 index 7704d13..0000000 --- a/c++/codec-minecraft/.nix/derivation.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ lib -, stdenvNoCC -, scons -, clang -, clang-tools -, version -, forstio -}: - -let - -in stdenvNoCC.mkDerivation { - pname = "forstio-codec-minecraft"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/codec-minecraft/SConscript b/c++/codec-minecraft/SConscript deleted file mode 100644 index 4d1deab..0000000 --- a/c++/codec-minecraft/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -codec_minecraft_env = env.Clone(); - -codec_minecraft_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -codec_minecraft_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += codec_minecraft_env.sources; -env.headers += codec_minecraft_env.headers; - -## Shared lib -objects_shared = [] -codec_minecraft_env.add_source_files(objects_shared, codec_minecraft_env.sources, shared=True); -codec_minecraft_env.library_shared = codec_minecraft_env.SharedLibrary('#build/forstio-codec-minecraft', [objects_shared]); - -## Static lib -objects_static = [] -codec_minecraft_env.add_source_files(objects_static, codec_minecraft_env.sources, shared=False); -codec_minecraft_env.library_static = codec_minecraft_env.StaticLibrary('#build/forstio-codec-minecraft', [objects_static]); - -# Set Alias -env.Alias('library_codec_minecraft', [codec_minecraft_env.library_shared, codec_minecraft_env.library_static]); - -env.targets += ['library_codec_minecraft']; - -# Install -env.Install('$prefix/lib/', [codec_minecraft_env.library_shared, codec_minecraft_env.library_static]); -env.Install('$prefix/include/forstio/codec/minecraft/', [codec_minecraft_env.headers]); diff --git a/c++/codec-minecraft/SConstruct b/c++/codec-minecraft/SConstruct deleted file mode 100644 index edd5f57..0000000 --- a/c++/codec-minecraft/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-codec']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/codec-minecraft/minecraft.h b/c++/codec-minecraft/minecraft.h deleted file mode 100644 index 670b019..0000000 --- a/c++/codec-minecraft/minecraft.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include <forstio/core/error.h> -#include <forstio/codec/data.h> -#include <forstio/codec/stream_value.h> - -namespace saw { -namespace encode { -struct Minecraft {}; -struct VarIntTransport {}; -} - -template<typename T> -class data<T, encode::Minecraft> { -private: - ring_buffer buffer_; -public: - data() = default; - data(std::size_t size): - buffer_{size} - {} - - buffer& get_buffer(){ - return buffer_; - } -}; - -namespace mc { -namespace impl { -union minecraft_signed_four_conversion { - int32_t s; - uint32_t u; -}; - -union minecraft_signed_eight_conversion { - int64_t s; - uint64_t u; -}; - -template<typename Schema, typename FromEnc> -class minecraft_encode { - static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the Minecraft encoding."); -}; - -template<typename FromEnc> -class minecraft_encode<schema::VarInt, FromEnc>{ - static error_or<void> encode(const data<schema::VarInt, FromEnc>& from, buffer& to){ - uint8_t encode_index = 0; - minecraft_signed_four_conversion value; - value.s = from.get(); - - /** - * VarInt max length is 5 bytes - */ - std::array<uint8_t, 5> encode_data; - - do { - uint8_t step = static_cast<uint8_t>(value.u & 0x7F); - value.u = value.u >> 7; - if(value.u != 0){ - step |= 0x80; - } - encode_data[encode_index] = step; - ++encode_index; - }while(value.u != 0); - - auto err = buffer.push(encode_data[0], encode_index); - if (!err.template is_type<err::no_error>()) { - return err; - } - - return no_error(); - } -}; - -template<typename Schema, typename FromEnc> -class minecraft_decode { - static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the Minecraft encoding."); -}; - -template<typename FromEnc> -class minecraft_decode<schema::VarInt, FromEnc>{ - static error_or<void> decode(buffer& from, data<schema::VarInt, FromEnc>& to){ - uint8_t num_reads = 0; - - minecraft_signed_four_conversion value; - value.u = 0; - - uint8_t read{}; - do { - auto err = from.pop(read); - if( !err.template is_type<err::no_error>() ){ - return err; - } - value.u |= ((read & 0x7F) << (7*num_reads)); - ++num_reads; - if(num_reads > 5){ - return make_error<err::>(); - } - } while( (read & 0x80) != 0); - - to.set(value.s); - - return no_error(); - } -}; - -} -} - - - -namespace mc { - -} -} diff --git a/c++/codec-minecraft/var_int_data.cpp b/c++/codec-minecraft/var_int_data.cpp deleted file mode 100644 index 59e4317..0000000 --- a/c++/codec-minecraft/var_int_data.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "var_int_data.h" - -namespace saw { -data<schema::VarInt,encode::Native>::data(): - data_{} -{} - -data<schema::VarInt,encode::Native>::data(int32_t data): - data_{data} -{} - -int32_t data<schema::VarInt, encode::Native>::get() const { - return data_; -} - -void data<schema::VarInt, encode::Native>::set(int32_t data) { - data_ = data; -} - -data<schema::VarLong,encode::Native>::data(): - data_{} -{} - -data<schema::VarLong,encode::Native>::data(int64_t data): - data_{data} -{} - -int64_t data<schema::VarLong, encode::Native>::get() const { - return data_; -} - -void data<schema::VarLong, encode::Native>::set(int64_t data) { - data_ = data; -} - -} diff --git a/c++/codec-minecraft/var_int_data.h b/c++/codec-minecraft/var_int_data.h deleted file mode 100644 index 807c930..0000000 --- a/c++/codec-minecraft/var_int_data.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include <forstio/core/data.h> - -namespace saw { -template<> -class data<schema::VarInt, encode::Native> { -private: - int32_t data_; -public: - data(); - data(int32_t data); - - int32_t get() const; - void set(int32_t); -}; - -template<> -class data<schema::VarLong, encode::Native> { -private: - int64_t data_; -public: - data(); - data(int64_t data); - - int64_t get() const; - void set(int64_t); -}; - - -} diff --git a/c++/codec-netcdf/.nix/derivation.nix b/c++/codec-netcdf/.nix/derivation.nix deleted file mode 100644 index 770942e..0000000 --- a/c++/codec-netcdf/.nix/derivation.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ lib -, stdenv -, scons -, clang -, clang-tools -, version -, forstio -, netcdf -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-codec-netcdf"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - netcdf - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/codec-netcdf/SConscript b/c++/codec-netcdf/SConscript deleted file mode 100644 index a469f77..0000000 --- a/c++/codec-netcdf/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -codec_netcdf_env = env.Clone(); - -codec_netcdf_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -codec_netcdf_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += codec_netcdf_env.sources; -env.headers += codec_netcdf_env.headers; - -## Shared lib -objects_shared = [] -codec_netcdf_env.add_source_files(objects_shared, codec_netcdf_env.sources, shared=True); -codec_netcdf_env.library_shared = codec_netcdf_env.SharedLibrary('#build/forstio-codec-netcdf', [objects_shared]); - -## Static lib -objects_static = [] -codec_netcdf_env.add_source_files(objects_static, codec_netcdf_env.sources, shared=False); -codec_netcdf_env.library_static = codec_netcdf_env.StaticLibrary('#build/forstio-codec-netcdf', [objects_static]); - -# Set Alias -env.Alias('library_codec_netcdf', [codec_netcdf_env.library_shared, codec_netcdf_env.library_static]); - -env.targets += ['library_codec_netcdf']; - -# Install -env.Install('$prefix/lib/', [codec_netcdf_env.library_shared, codec_netcdf_env.library_static]); -env.Install('$prefix/include/forstio/codec/netcdf/', [codec_netcdf_env.headers]); diff --git a/c++/codec-netcdf/SConstruct b/c++/codec-netcdf/SConstruct deleted file mode 100644 index edd5f57..0000000 --- a/c++/codec-netcdf/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-codec']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/codec-netcdf/netcdf.h b/c++/codec-netcdf/netcdf.h deleted file mode 100644 index cc9aedb..0000000 --- a/c++/codec-netcdf/netcdf.h +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include <forstio/core/string_literal.h> -#include <forstio/core/error.h> -#include <forstio/codec/data.h> - -#include <netcdf.h> -#include <netcdf_mem.h> - -namespace saw { -namespace encode { -/** - * Template type hint - */ -struct Netcdf {}; -} - -/** - * Class representing the files system netcdf file - */ -template<typename Schema> -class data<Schema, encode::Netcdf> { -private: - std::vector<uint8_t> buff_; -public: - data() = default; - - data(std::vector<uint8_t> buff): - buff_{std::move(buff)} - {} - - template<size_t N> - data(const std::array<uint8_t, N>& arr): - buff_{arr.begin(), arr.end()} - {} - - std::vector<uint8_t>& get_data() { - return buff_; - } - - const std::vector<uint8_t>& get_data() const { - return buff_; - } -}; - -template<typename Schema> -class codec<Schema, encode::Netcdf>{ - static_assert(always_false<Schema,encode::Netcdf>, "NetCDF only supports Structs as a root object"); -}; - -} -#include "netcdf.tmpl.h" -namespace saw { - -template<typename... Vals, string_literal... Keys> -class codec<schema::Struct<schema::Member<Vals,Keys>...>, encode::Netcdf> { -private: - using Schema = schema::Struct<schema::Member<Vals,Keys>...>; -public: - SAW_FORBID_COPY(codec); - SAW_DEFAULT_MOVE(codec); - - /** - * Default constructor - */ - codec() = default; - - /** - * Encoder function - */ - template<typename FromEncoding> - error_or<void> encode(const data<Schema, FromEncoding>& from, data<Schema,encode::Netcdf>& to) { - int rc{}; - int ncid{}; - - rc = nc_create_mem("forstio_internal_write_memory", 0,/*NC_NETCDF4, */0, &ncid); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - - { - auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode_meta(from, ncid); - if(eov.is_error()){ - nc_close(ncid); - return eov; - } - } - - rc = nc_enddef(ncid); - if(rc != NC_NOERR){ - nc_close(ncid); - return make_error<err::critical>(); - } - - { - auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode(from, ncid); - if(eov.is_error()){ - nc_close(ncid); - return eov; - } - } - - NC_memio nc_memio; - rc = nc_close_memio(ncid, &nc_memio); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - - if(!nc_memio.memory || nc_memio.size == 0){ - return make_error<err::critical>(); - } - - try { - to.get_data().resize(nc_memio.size); - }catch(const std::exception& e){ - (void) e; - return make_error<err::out_of_memory>(); - } - - for(std::size_t i = 0; i < nc_memio.size; ++i){ - to.get_data().at(i) = static_cast<uint8_t*>(nc_memio.memory)[i]; - } - - free(nc_memio.memory); - nc_memio.memory = nullptr; - - return void_t{}; - } - - /** - * Decoder function - */ - template<typename ToEncoding> - error_or<void> decode(data<Schema, encode::Netcdf>& from_decode, data<Schema,ToEncoding>& to_decode) { - int ncid{}; - int rc{}; - - rc = nc_open_mem("forstio_internal_read_memory", NC_NOWRITE, from_decode.get_data().size(), &from_decode.get_data()[0], &ncid); - if(rc != NC_NOERR){ - // Don't know how to get the error, so fail critically. - return make_error<err::critical>(); - } - - auto eov = impl::netcdf_decode<Schema, ToEncoding>::decode(to_decode, ncid); - - nc_close(ncid); - - return eov; - } -}; -} diff --git a/c++/codec-netcdf/netcdf.tmpl.h b/c++/codec-netcdf/netcdf.tmpl.h deleted file mode 100644 index bf257e4..0000000 --- a/c++/codec-netcdf/netcdf.tmpl.h +++ /dev/null @@ -1,348 +0,0 @@ -#pragma once - -namespace saw { -namespace impl { -template<typename Schema> -struct netcdf_primitive_id { - static_assert(always_false<Schema>, "Not a primitive id"); -}; - -template<> -struct netcdf_primitive_id<schema::Int32> { - static constexpr nc_type value = NC_INT; -}; - -template<> -struct netcdf_primitive_id<schema::UInt32> { - static constexpr nc_type value = NC_UINT; -}; - -template<> -struct netcdf_primitive_id<schema::Int64> { - static constexpr nc_type value = NC_INT64; -}; - -template<> -struct netcdf_primitive_id<schema::UInt64> { - static constexpr nc_type value = NC_UINT64; -}; - -template<> -struct netcdf_primitive_id<schema::Float32> { - static constexpr nc_type value = NC_FLOAT; -}; - -template<> -struct netcdf_primitive_id<schema::Float64> { - static constexpr nc_type value = NC_DOUBLE; -}; - -template<typename Schema> -struct netcdf_is_group { - static constexpr bool value = false; -}; - -template<typename... T, string_literal... Lits> -struct netcdf_is_group<schema::Struct<schema::Member<T,Lits>...>> { - static constexpr bool value = true; -}; - -template<typename Schema, typename ToEncode> -struct netcdf_encode; - -template<typename T, size_t N, typename ToEncode> -struct netcdf_encode<schema::Primitive<T,N>, ToEncode> { - using Schema = schema::Primitive<T,N>; - - static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ - int rc{}; - - typename native_data_type<Schema>::type val = from.get(); - - rc = nc_put_var(ncid, ncvarid, &val); - if(rc != NC_NOERR) { - return make_error<err::critical>(); - } - - return void_t{}; - } - - static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ - (void) from; - (void) ncid; - (void) ncvarid; - return void_t{}; - } -}; - -template<typename T, size_t Dim, typename ToEncode> -struct netcdf_encode<schema::Array<T,Dim>, ToEncode> { - using Schema = schema::Array<T,Dim>; - - template<size_t Level> - static error_or<void> encode_level(data<Schema,ToEncode>& from, int ncid, int ncvarid){ - - return make_error<err::not_implemented>(); - } - - static error_or<void> encode(data<Schema, ToEncode>& from, int ncid, int ncvarid){ - - return make_error<err::not_implemented>(); - } - - static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ - - return make_error<err::not_implemented>(); - } -}; - -template<typename... T, string_literal... Lits, typename ToEncode> -struct netcdf_encode<schema::Struct<schema::Member<T,Lits>...>, ToEncode> { - using Schema = schema::Struct<schema::Member<T,Lits>...>; - - template<std::size_t i> - static error_or<void> encode_member(const data<Schema, ToEncode>& from, int ncid){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - { - /** - * We have to ask for the internal id of the netcdf structure - */ - if constexpr (netcdf_is_group<Type>::value){ - return make_error<err::not_implemented>(); - }else{ - int nc_varid{}; - int rc {}; - rc = nc_inq_varid(ncid, Literal.data.data(), &nc_varid); - if(rc != NC_NOERR) { - return make_error<err::critical>(); - } - auto eov = netcdf_encode<Type, ToEncode>::encode(from.template get<Literal>(), ncid, nc_varid); - if(eov.is_error()){ - return eov; - } - } - - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = encode_member<i+1>(from, ncid); - if(eov.is_error()){ - return eov; - } - } - - return void_t{}; - } - - static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid){ - if constexpr (sizeof...(T) > 0){ - auto eov = encode_member<0>(from, ncid); - return eov; - } - - return void_t{}; - } - - template<std::size_t i> - static error_or<void> encode_meta_member(const data<Schema, ToEncode>& from, int ncid){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - { - /** - * We have to ask for the internal id of the netcdf structure - */ - if constexpr (netcdf_is_group<Type>::value){ - return make_error<err::not_implemented>(); - }else{ - int nc_varid{}; - int rc {}; - rc = nc_def_var(ncid, Literal.data.data(), netcdf_primitive_id<Type>::value, 0, nullptr, &nc_varid); - if(rc != NC_NOERR) { - return make_error<err::critical>(); - } - auto eov = netcdf_encode<Type, ToEncode>::encode_meta(from.template get<Literal>(), ncid, nc_varid); - if(eov.is_error()){ - return eov; - } - } - - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = encode_meta_member<i+1>(from, ncid); - if(eov.is_error()){ - return eov; - } - } - - return void_t{}; - } - - static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid){ - if constexpr (sizeof...(T) > 0){ - auto eov = encode_meta_member<0>(from, ncid); - return eov; - } - - return void_t{}; - } -}; - -template<typename Schema, typename ToDecode> -struct netcdf_decode; - -template<typename T, size_t N, typename ToDecode> -struct netcdf_decode<schema::Primitive<T,N>, ToDecode> { - using Schema = schema::Primitive<T,N>; - - static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ - int rc{}; - - nc_type nc_vartype{}; - int nc_dimnum{}; - std::array<int,NC_MAX_VAR_DIMS> nc_dimids; - - rc = nc_inq_var(from, nc_varid, nullptr, &nc_vartype, &nc_dimnum, &nc_dimids[0], nullptr); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - if(nc_vartype != netcdf_primitive_id<schema::Primitive<T,N>>::value){ - return make_error<err::critical>(); - } - if(nc_dimnum != 0){ - return make_error<err::critical>(); - } - - typename native_data_type<schema::Primitive<T,N>>::type val{}; - rc = nc_get_var(from, nc_varid, &val); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - - to.set(val); - - return void_t {}; - } -}; - -template<typename T, size_t Dim, typename ToDecode> -struct netcdf_decode<schema::Array<T,Dim>, ToDecode> { - using Schema = schema::Array<T,Dim>; - - template<std::size_t Level> - static error_or<void> decode_level(data<Schema, ToDecode>& to, int from, int nc_varid, std::array<std::size_t, Dim>& index, const std::array<size_t,Dim>& count){ - if constexpr ( Level == Dim ){ - int rc{}; - typename native_data_type<T>::type val; - rc = nc_get_vara(from, nc_varid, index.data(), count.data(), &val); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - to.at(index).set(val); - }else{ - const std::size_t dim_size = to.get_dim_size(Level); - for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ - auto eov = decode_level<Level+1>(to, from, nc_varid, index, count); - if(eov.is_error()){ - return eov; - } - } - } - - return void_t{}; - } - - static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ - int rc{}; - - nc_type nc_vartype{}; - - int nc_dimnum{}; - std::array<int, NC_MAX_VAR_DIMS> nc_dimids; - - rc = nc_inq_var(from, nc_varid, nullptr, &nc_vartype, &nc_dimnum, &nc_dimids[0], nullptr); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - if(nc_vartype != netcdf_primitive_id<T>::value){ - return make_error<err::critical>(); - } - if(nc_dimnum != Dim){ - return make_error<err::critical>(); - } - - std::array<std::size_t, Dim> dims; - std::array<size_t, Dim> count; - for(std::size_t i = 0; i < Dim; ++i){ - rc = nc_inq_dim(from, nc_dimids[i], nullptr, &dims[i]); - if(rc != NC_NOERR){ - return make_error<err::critical>(); - } - count[i] = 1; - } - - to = {dims}; - std::array<std::size_t, Dim> index; - - return decode_level<0>(to, from, nc_varid, index, count); - } -}; - -template<typename... T, string_literal... Lits, typename ToDecode> -struct netcdf_decode<schema::Struct<schema::Member<T,Lits>...>, ToDecode> { - using Schema = schema::Struct<schema::Member<T,Lits>...>; - - template<std::size_t i> - static error_or<void> decode_member(data<Schema,ToDecode>& to, int from){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - { - /** - * We have to ask for the internal id of the netcdf structure - */ - if constexpr (netcdf_is_group<Type>::value){ - int nc_group_id{}; - int rc {}; - rc = nc_inq_ncid(from, Literal.data.data(), &nc_group_id); - if(rc != NC_NOERR) { - return make_error<err::critical>(); - } - auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), nc_group_id); - if(eov.is_error()){ - return eov; - } - }else{ - int nc_varid{}; - int rc {}; - rc = nc_inq_varid(from, Literal.data.data(), &nc_varid); - if(rc != NC_NOERR) { - return make_error<err::critical>(); - } - auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), from, nc_varid); - if(eov.is_error()){ - return eov; - } - } - - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = decode_member<i+1>(to, from); - if(eov.is_error()){ - return eov; - } - } - - return void_t{}; - } - - - static error_or<void> decode(data<Schema, ToDecode>& to, int from){ - if constexpr (sizeof...(T) > 0){ - auto eov = decode_member<0>(to, from); - return eov; - } - - return void_t{}; - } -}; -} -} diff --git a/c++/codec/.nix/derivation.nix b/c++/codec/.nix/derivation.nix deleted file mode 100644 index bcf2be7..0000000 --- a/c++/codec/.nix/derivation.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-codec"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - buildInputs = [ - forstio.core - ]; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/codec/SConscript b/c++/codec/SConscript deleted file mode 100644 index c038d42..0000000 --- a/c++/codec/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -codec_env = env.Clone(); - -codec_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -codec_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += codec_env.sources; -env.headers += codec_env.headers; - -## Shared lib -objects_shared = [] -codec_env.add_source_files(objects_shared, codec_env.sources, shared=True); -codec_env.library_shared = codec_env.SharedLibrary('#build/forstio-codec', [objects_shared]); - -## Static lib -objects_static = [] -codec_env.add_source_files(objects_static, codec_env.sources, shared=False); -codec_env.library_static = codec_env.StaticLibrary('#build/forstio-codec', [objects_static]); - -# Set Alias -env.Alias('library_codec', [codec_env.library_shared, codec_env.library_static]); - -env.targets += ['library_codec']; - -# Install -env.Install('$prefix/lib/', [codec_env.library_shared, codec_env.library_static]); -env.Install('$prefix/include/forstio/codec/', [codec_env.headers]); diff --git a/c++/codec/SConstruct b/c++/codec/SConstruct deleted file mode 100644 index 0d7b7c6..0000000 --- a/c++/codec/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-core']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/codec/args.h b/c++/codec/args.h deleted file mode 100644 index 6bb75a2..0000000 --- a/c++/codec/args.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "schema.h" - -namespace saw { -namespace encode { -struct Args {}; -} - -namespace schema { -template<typename InnerSchemaStruct, typename InnerSchemaTuple> -using Args = Struct< - Member<String, "program">, - Member<InnerSchemaStruct, "args">, - Member<InnerSchemaTuple, "positionals"> ->; -} - -template<typename T> -class data<T, encode::Args> { - static_assert(always_false<T>,"Not supported. Use the schema::Args alias or check how it's defined."); -}; - -template<typename... Str, string_literal... Lits, typename... Tup> -class data<schema::Args<schema::Struct<schema::Member<Str,Lits>...>, schema::Tuple<Tup...>>, encode::Args> { -private: - char** argv_; - int argc_; -public: - data(char** argv, int argc): - argv_{argv}, - argc_{argc} - {} - - size_t size() const { - if(argc_ < 0){ - return 0; - } - - static_assert(sizeof(int) <= sizeof(size_t), "size_t is smaller than int"); - - return static_cast<size_t>(argc_); - } - - std::string_view arg_view(size_t i){ - if(i < size()){ - return std::string_view{argv_[i]}; - } - return ""; - } -}; - -namespace impl { -template<typename T, typename ToDec> -struct args_decode { - static_assert(always_false<T,ToDec>, "Not supported"); -}; - -template<typename... Str, string_literal... Lits, typename... Tup, typename ToDec> -struct args_decode<schema::Args<schema::Struct<schema::Member<Str,Lits>...>,schema::Tuple<Tup...>>,ToDec> { - using Schema = schema::Args< - schema::Struct<schema::Member<Str,Lits>...>, - schema::Tuple<Tup...> - >; - - static error_or<void> decode(data<Schema, encode::Args>& from, data<Schema,ToDec>& to){ - if(from.size() == 0){ - return make_error<err::invalid_state>(); - } - - to.get<"program">().set(std::string{from.arg_view(0)}); - std::size_t tuple_pos = 0; - for(size_t i = 1; i < from.size(); ++i){ - auto view = from.arg_view(i); - if(view.starts_with("--")){ - view.remove_prefix(std::min(2u, view.size())); - ++i; - - if( i >= from.size() ){ - return make_error<err::invalid_state>(); - } - - auto value_view = from.arg_view(i); - - auto eov = decode_struct_member<0>(to.get<"args">(), view, value_view); - if(eov.is_error()){ - return eov; - } - } else { - auto eov = decode_tuple_member<0>(to.get<"positionals">(), view); - if(eov.is_error()){ - return eov; - } - ++tuple_pos; - } - } - - if(tuple_pos != sizeof...(Tup)){ - return make_error<err::invalid_state>(); - } - - return void_t{}; - } -}; -} - -template<typename Schema> -class codec<Schema, encode::Args> { -public: - template<typename ToDec> - error_or<void> decode(data<Schema, encode::Args>& from, data<Schema, ToDec>& to){ - struct name_and_value { - std::string name; - std::string value; - }; - std::string program; - std::vector<name_and_value> navs; - std::vector<std::string> positionals; - - return void_t{}; - } -}; -} diff --git a/c++/codec/csv.h b/c++/codec/csv.h deleted file mode 100644 index 67c2c1d..0000000 --- a/c++/codec/csv.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "data.h" - -namespace saw { -namespace encode { -struct Csv {}; -} - -template<typename Schema> -class codec<Schema, encode::Csv> { -public: - template<typename FromEncode> - static error_or<void> encode(const data<Schema, FromEncode>& from, data<Schema,encode::Csv>& to){ - - return make_error<err::not_implemented>(); - } - - template<typename ToDecode> - static error_or<void> decode(data<Schema,encode::Csv>& from, data<Schema, FromEncode>& to){ - - return make_error<err::not_implemented>(); - } -}; -} diff --git a/c++/codec/data.h b/c++/codec/data.h deleted file mode 100644 index 237ef5a..0000000 --- a/c++/codec/data.h +++ /dev/null @@ -1,370 +0,0 @@ -#pragma once - -#include <forstio/core/common.h> -#include <forstio/core/templates.h> - -#include <cassert> - -#include <array> -#include <concepts> -#include <variant> -#include <vector> - -#include "schema.h" - -namespace saw { -namespace encode { -struct Native {}; -} -template<typename Schema, typename Encode> -class codec; -/* - * Helper for the basic message container, so the class doesn't have to be - * specialized 10 times. - */ -template <class T> struct native_data_type; - -template <> -struct native_data_type<schema::Primitive<schema::SignedInteger, 1>> { - using type = int8_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::SignedInteger, 2>> { - using type = int16_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::SignedInteger, 4>> { - using type = int32_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::SignedInteger, 8>> { - using type = int64_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::UnsignedInteger, 1>> { - using type = uint8_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::UnsignedInteger, 2>> { - using type = uint16_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::UnsignedInteger, 4>> { - using type = uint32_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::UnsignedInteger, 8>> { - using type = uint64_t; -}; - -template <> -struct native_data_type<schema::Primitive<schema::FloatingPoint, 4>> { - using type = float; -}; - -template <> -struct native_data_type<schema::Primitive<schema::FloatingPoint, 8>> { - using type = double; -}; - -template<typename T, typename Encoding = encode::Native> -class data { -private: - static_assert(always_false<T>, "Type not supported"); -}; - -template<typename... T, string_literal... literals> -class data<schema::Union<schema::Member<T, literals>...>, encode::Native> { -private: - std::variant<data<T,encode::Native>...> value_; -public: - data() = default; - - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - template<string_literal lit> - void set(data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native> val){ - value_ = std::move(val); - } - - template<string_literal lit> - data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& init(){ - value_ = data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>{}; - return get<lit>(); - } - - template<string_literal lit> - bool holds_alternative() const { - return (parameter_key_pack_index<lit, literals...>::value == value_.index()); - } - - template<string_literal lit> - data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get(){ - return std::get<parameter_key_pack_index<lit, literals...>::value>(value_); - } - - template<string_literal lit> - const data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get() const{ - return std::get<parameter_key_pack_index<lit, literals...>::value>(value_); - } -}; - -template<typename... T, string_literal... literals> -class data<schema::Struct<schema::Member<T, literals>...>, encode::Native> { -private: - std::tuple<data<T,encode::Native>...> value_; -public: - data() = default; - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - template<string_literal literal> - data< - typename parameter_pack_type< - parameter_key_pack_index< - literal, literals... - >::value - , T...>::type - , encode::Native>& get(){ - return std::get<parameter_key_pack_index<literal, literals...>::value>(value_); - } - - template<string_literal literal> - const data< - typename parameter_pack_type< - parameter_key_pack_index< - literal, literals... - >::value - , T...>::type - , encode::Native>& get() const { - return std::get<parameter_key_pack_index<literal, literals...>::value>(value_); - } - - constexpr size_t size() const { - return sizeof...(T); - } -}; - -template<typename... T> -class data<schema::Tuple<T...>, encode::Native> { -private: - std::tuple<data<T,encode::Native>...> value_; -public: - data() = default; - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - template<size_t i> - data<typename parameter_pack_type<i,T...>::type, encode::Native>& get(){ - return std::get<i>(value_); - } - - template<size_t i> - const data<typename parameter_pack_type<i,T...>::type, encode::Native>& get() const{ - return std::get<i>(value_); - } - - constexpr size_t size() const { - return sizeof...(T); - } -}; - -template<typename T, size_t Dim> -class data<schema::Array<T,Dim>, encode::Native> { - private: - std::array<std::size_t, Dim> dims_; - std::vector<data<T, encode::Native>> value_; - - std::size_t get_full_size() const { - std::size_t s = 1; - - for(std::size_t iter = 0; iter < Dim; ++iter){ - assert(dims_.at(iter) > 0); - s *= dims_.at(iter); - } - - return s; - } - public: - data() = default; - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - data(const std::array<std::size_t, Dim>& i): - dims_{i}, - value_{} - { - value_.resize(get_full_size()); - } - - template<std::integral... Dims> - data(Dims... size_): - data{{size_...}} - { - static_assert(sizeof...(Dims)==Dim, "Argument size must be equal to the Dimension"); - } - - data<T, encode::Native>& at(const std::array<std::size_t, Dim>& ind){ - return value_.at(this->get_flat_index(ind)); - } - - const data<T, encode::Native>& at(const std::array<std::size_t, Dim>& ind) const { - return value_.at(this->get_flat_index(ind)); - } - - template<std::integral... Dims> - data<T, encode::Native>& at(Dims... i){ - return value_.at(this->get_flat_index({i...})); - } - - template<std::integral... Dims> - const data<T, encode::Native>& at(Dims... i) const { - return value_.at(this->get_flat_index({i...})); - } - - std::size_t get_dim_size(std::size_t i) const { - return dims_.at(i); - } - - size_t size() const { return value_.size();} - -private: - std::size_t get_flat_index(const std::array<std::size_t, Dim>& i) const { - std::size_t s = 0; - - std::size_t stride = 1; - - for(std::size_t iter = 0; iter < Dim; ++iter){ - assert(i.at(iter) < dims_.at(iter)); - s += i.at(iter) * stride; - stride *= dims_.at(iter); - } - - return s; - } -}; - -template<typename T, std::size_t... D> -class data<schema::FixedArray<T,D...>, encode::Native> { -private: - //using inner_type = std::array<data<T, encode::Native>, multiply_helper<Dims...>::value>; - //std::unique_ptr<inner_type> value_; - std::vector<data<T, encode::Native>> value_; - -public: - data(){ - value_.resize(ct_multiply<std::size_t, D...>::value); - } - - data<T, encode::Native>& at(const std::array<std::size_t, sizeof...(D)>& ind){ - return value_.at(this->get_flat_index(ind)); - } - - const data<T, encode::Native>& at(const std::array<std::size_t, sizeof...(D)>& ind) const { - return value_.at(this->get_flat_index(ind)); - } - - template<std::integral... Dims> - data<T, encode::Native>& at(Dims... i) { - return value_.at(this->get_flat_index({i...})); - } - - template<std::integral... Dims> - const data<T, encode::Native>& at(Dims... i) const { - return value_.at(this->get_flat_index({i...})); - } - - template<std::size_t i> - std::size_t get_dim_size() const { - return parameter_pack_value<i, std::size_t, D...>::value; - } -private: - std::size_t get_flat_index(const std::array<std::size_t, sizeof...(D)>& i) const { - std::size_t s = 0; - - std::size_t stride = 1; - - constexpr static std::array<std::size_t, sizeof...(D)> dims_{D...}; - - for(std::size_t iter = 0; iter < sizeof...(D); ++iter){ - assert(i.at(iter) < dims_.at(iter)); - s += i.at(iter) * stride; - stride *= dims_.at(iter); - } - - return s; - } -}; - -template<> -class data<schema::String, encode::Native> { -private: - std::string value_; -public: - data() = default; - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - data(std::string value__):value_{std::move(value__)}{} - data(std::size_t size_){ - value_.resize(size_); - } - - std::size_t size() const { - return value_.size(); - } - - void set(std::string str){ - value_ = std::move(str); - } - - char& at(size_t i) { - return value_.at(i); - } - - const char& at(size_t i) const { - return value_.at(i); - } - - char get_at(size_t i) const{ - return value_.at(i); - } - - void set_at(size_t i, char val){ - value_.at(i) = val; - } - - bool operator==(const std::string_view& val)const{ - return value_ == val; - } -}; - -template<typename T, size_t N> -class data<schema::Primitive<T,N>, encode::Native> { -private: - typename native_data_type<schema::Primitive<T,N>>::type value_; -public: - data():value_{{}}{}; - SAW_DEFAULT_COPY(data); - SAW_DEFAULT_MOVE(data); - - data(typename native_data_type<schema::Primitive<T,N>>::type value__): - value_{std::move(value__)}{} - - void set(typename native_data_type<schema::Primitive<T,N>>::type val){ - value_ = val; - } - - typename native_data_type<schema::Primitive<T,N>>::type get() const {return value_;} -}; - - -} diff --git a/c++/codec/forst.h b/c++/codec/forst.h deleted file mode 100644 index 7e8fbf0..0000000 --- a/c++/codec/forst.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "data.h" - -namespace saw { -namespace encode { -struct KelForst {}; -} -} - -#include "forst.tmpl.hpp" - -namespace saw { -class data<schema::String, encode::KelForst> { -private: - own<buffer> buff_; -public: - data(own<buffer> buff): - buff_{std::move(buff)} - {} -}; - -template<typename... T, string_literal... Keys> -class data<schema::Struct<schema::Member<T,Keys>...>, encode::KelForst> { -private: - own<buffer> buff_; -public: - data(own<buffer> buff): - buff_{std::move(buff)} - {} -}; -} diff --git a/c++/codec/forst.tmpl.h b/c++/codec/forst.tmpl.h deleted file mode 100644 index 30d18ef..0000000 --- a/c++/codec/forst.tmpl.h +++ /dev/null @@ -1,7 +0,0 @@ -namespace saw { -namespace impl { -struct forst_decode { - -}; -} -} diff --git a/c++/codec/interface.h b/c++/codec/interface.h deleted file mode 100644 index b1422a9..0000000 --- a/c++/codec/interface.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include <forstio/core/error.h> -#include "schema.h" -#include "data.h" - -namespace saw { -template<typename SchemaFunc, typename Encode, typename Func> -class function; - -template<typename Request, typename Response, typename Encode, typename Func> -class function<schema::Function<Request, Response>, Encode, Func> { -private: - Func func_; -public: - function(Func func): - func_{std::move(func)} - {} - - error_or<data<Response, Encode>> call(data<Request, Encode> req){ - return func_(std::move(req)); - } -}; - -template<typename T, typename Encode, typename... Funcs> -class interface; - -template<typename... Requests, typename... Responses, string_literal... Names, typename Encode, typename... Funcs> -class interface<schema::Interface<schema::Member<schema::Function<Requests, Responses>, Names>...>, Encode, Funcs...> { -private: - std::tuple<function<schema::Function<Requests, Responses>, Encode, Funcs>...> funcs_; -public: - interface(function<schema::Function<Requests, Responses>, Encode, Funcs>... funcs): - funcs_{std::move(funcs)...} - {} - - /** - * Get the function based on the string literal matching the position in the tuple - */ - template<string_literal Lit> - function< - schema::Function< - typename parameter_pack_type< - parameter_key_pack_index< - Lit, Names... - >::value - , Requests...>::type - , - typename parameter_pack_type< - parameter_key_pack_index< - Lit, Names... - >::value - , Responses...>::type - > - , - Encode - , - typename parameter_pack_type< - parameter_key_pack_index< - Lit, Names... - >::value - , Funcs...>::type - >& get(){ - return std::get<parameter_key_pack_index<Lit, Names...>::value>(funcs_); - } - - template<string_literal Lit> - error_or<data< - typename parameter_pack_type< - parameter_key_pack_index< - Lit, Names... - >::value - , Responses...>::type - , Encode>> call( - data< - typename parameter_pack_type< - parameter_key_pack_index< - Lit, Names... - >::value - , Requests...>::type - , Encode> req - ){ - return get<Lit>().call(std::move(req)); - } - -}; - -template<typename T, typename Encode> -struct function_factory { - template<typename Func> - static function<T,Encode, Func> create(Func func){ - return function<T,Encode,Func>{std::move(func)}; - } -}; - -template<typename T, typename Encode> -struct interface_factory { - template<typename... Func> - static interface<T,Encode, Func...> create(Func... func){ - return interface<T,Encode, Func...>{std::move(func)...}; - } -}; -} diff --git a/c++/codec/rpc.h b/c++/codec/rpc.h deleted file mode 100644 index b21ecf8..0000000 --- a/c++/codec/rpc.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -namespace saw { -template<typename T> -class remote { - static_assert(always_false<T>, "Type of remote not supported"); -}; - -template<typename T> -class rpc_client { - template<typename... T> - struct request { - private: - std::tuple<id<T>> ids_; - public: - error_or<data<T>> wait(); - }; - - template<typename... T> - request<T...> request_data(id<T>... data); -}; - -template<typename T> -class rpc_server { -}; -} diff --git a/c++/codec/schema.h b/c++/codec/schema.h deleted file mode 100644 index a8494fe..0000000 --- a/c++/codec/schema.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include <forstio/core/common.h> -#include <forstio/core/string_literal.h> - -namespace saw { -namespace schema { -// NOLINTBEGIN -template <typename T, string_literal Literal> struct Member {}; - -template <typename... T> struct Struct { - static_assert( - always_false<T...>, - "This schema template doesn't support this type of template argument"); -}; - -template <typename... V, string_literal... K> -struct Struct<Member<V, K>...> {}; - -template <typename... T> struct Union { - static_assert( - always_false<T...>, - "This schema template doesn't support this type of template argument"); -}; - -template <typename... V, string_literal... K> -struct Union<Member<V, K>...> {}; - -template <typename T, size_t Dim = 1> struct Array {}; - -template <class T> struct is_array { - constexpr static bool value = false; -}; - -template <class T, size_t Dim> struct is_array<schema::Array<T,Dim>> { - constexpr static bool value = true; -}; - -template<typename T, size_t... S> struct FixedArray {}; - -template <typename... T> struct Tuple {}; - -/** - * This acts as a separator of different encodings being mashed together - * For example we can transport any base64 encodings in JSON - * - * using WrappedExample = schema::Tuple< - * schema::Wrapper<schema::String, encode::Base64> - * >; - * - * data<WrappedExample, encode::Json> ex_data; - */ -template <typename T, typename Enc> -class Wrapper {}; - -struct String {}; - -struct SignedInteger {}; -struct UnsignedInteger {}; -struct FloatingPoint {}; - -template <class T, size_t N> struct Primitive { - static_assert(((std::is_same_v<T, SignedInteger> || - std::is_same_v<T, UnsignedInteger>)&&(N == 1 || N == 2 || - N == 4 || N == 8)) || - (std::is_same_v<T, FloatingPoint> && (N == 4 || N == 8)), - "Primitive Type is not supported"); -}; - -using Int8 = Primitive<SignedInteger, 1>; -using Int16 = Primitive<SignedInteger, 2>; -using Int32 = Primitive<SignedInteger, 4>; -using Int64 = Primitive<SignedInteger, 8>; - -using UInt8 = Primitive<UnsignedInteger, 1>; -using UInt16 = Primitive<UnsignedInteger, 2>; -using UInt32 = Primitive<UnsignedInteger, 4>; -using UInt64 = Primitive<UnsignedInteger, 8>; - -using Float32 = Primitive<FloatingPoint, 4>; -using Float64 = Primitive<FloatingPoint, 8>; - -/** - * Classes allowing to distinguish Ints from VarInts - */ -template<typename T, std::size_t MaxLen> -struct VariableLengthPrimitive {}; - -using VarInt = VariableLengthPrimitive<SignedInteger, 5>; -using VarLong = VariableLengthPrimitive<SignedInteger, 10>; - -/** - * Classes enabling Rpc calls - */ -template <class Request, class Response> -struct Function {}; - -template <class... T> struct Interface { - static_assert( - always_false<T...>, - "This schema template doesn't support this type of template argument"); -}; - -template <class... Requests, class... Responses, string_literal... Names> -struct Interface<Member<Function<Requests, Responses>,Names>...> {}; - -// NOLINTEND -} // namespace schema -} // namespace saw diff --git a/c++/codec/schema_hash.h b/c++/codec/schema_hash.h deleted file mode 100644 index 5690166..0000000 --- a/c++/codec/schema_hash.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include "schema.h" - -namespace saw { -struct schema_hash_combine { - static constexpr uint64_t apply(uint64_t seed, uint64_t v){ - return (seed ^ v) * 1099511628211u; - - - return seed ^( std::hash<uint64_t>{}(v) + 0x9e3779b9 + (seed<<6) + (seed >> 2)); - } -}; - -template<typename Schema> -struct schema_hash { - static_assert(always_false<Schema>, "Not schema_hashable"); -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,1>> { - static constexpr uint64_t base_value = 0u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,2>> { - static constexpr uint64_t base_value = 1u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,4>> { - static constexpr uint64_t base_value = 2u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,8>> { - static constexpr uint64_t base_value = 3u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,1>> { - static constexpr uint64_t base_value = 4u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,2>> { - static constexpr uint64_t base_value = 5u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,4>> { - static constexpr uint64_t base_value = 6u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,8>> { - static constexpr uint64_t base_value = 7u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::FloatingPoint,4>> { - static constexpr uint64_t base_value = 8u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::FloatingPoint,8>> { - static constexpr uint64_t base_value = 9u; -}; - -template<typename... T> -struct schema_hash<schema::Tuple<T...>> { - static constexpr uint64_t base_value = 10u; -}; - -template<typename... T, string_literal Literal> -struct schema_hash<schema::Struct<schema::Member<T,Literal>...>> { - static constexpr uint64_t base_value = 11u; -}; - -template<typename... T, string_literal Literal> -struct schema_hash<schema::Union<schema::Member<T,Literal>...>> { - static constexpr uint64_t base_value = 12u; -}; - -template<typename T, size_t Dim> -struct schema_hash<schema::Array<T,Dim>> { - static constexpr uint64_t base_value = 13u; -}; - -template<> -struct schema_hash<schema::String> { - static constexpr uint64_t base_value = 14u; -}; - -template<typename T, typename N> -struct schema_hash<schema::Wrapper<T,N>> { - static constexpr uint64_t base_value = 15u; -}; - -template<typename T, size_t... Dims> -struct schema_hash<schema::FixedArray<T,Dims...>> { - static constexpr uint64_t base_value = 16u; -}; - -} diff --git a/c++/codec/schema_stringify.h b/c++/codec/schema_stringify.h deleted file mode 100644 index a82081a..0000000 --- a/c++/codec/schema_stringify.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include "schema.h" - -#include <sstream> -#include <type_traits> - -namespace saw { -template<typename Schema> -struct schema_stringify { - static_assert(always_false<Schema>, "Not supported"); -}; - -template<typename T, size_t Dim> -struct schema_stringify<schema::Array<T,Dim>> { - static void apply(std::stringstream& iss) { - iss << "saw::schema::Array<"; - schema_stringify<T>::apply(iss); - iss << ","; - iss << ct_convert_to_digits<Dim, 10>::literal.view(); - iss << ">"; - } -}; - -template<typename T, size_t N> -struct schema_stringify<schema::Primitive<T,N>> { - static void apply(std::stringstream& iss) { - iss << "saw::schema::Primitive<"; - schema_stringify<T>::apply(iss); - iss << ","; - iss << ct_convert_to_digits<N,10>::literal.view(); - iss << ">"; - } -}; - -template<> -struct schema_stringify<schema::SignedInteger> { - static void apply(std::stringstream& iss) { - iss << "saw:schema::SignedInteger"; - } -}; - -template<> -struct schema_stringify<schema::UnsignedInteger> { - static void apply(std::stringstream& iss) { - iss << "saw:schema::UnsignedInteger"; - } -}; - -template<> -struct schema_stringify<schema::FloatingPoint> { - static void apply(std::stringstream& iss) { - iss << "saw:schema::FloatingPoint"; - } -}; - -template<typename... T> -struct schema_stringify_member { - static void apply(std::stringstream& iss) { - (void)iss; - } -}; - -template<typename T0, string_literal Name, typename... TL> -struct schema_stringify_member<schema::Member<T0,Name>, TL...> { - - static void apply(std::stringstream& iss) { - iss << "saw::schema::Member<"; - schema_stringify<T0>::apply(iss); - iss << ",\""; - iss << Name.view(); - iss << "\">"; - if constexpr ( sizeof...(TL) > 0){ - iss << ","; - schema_stringify_member<TL...>::apply(iss); - } - } -}; - -template<typename... T, string_literal... Lits> -struct schema_stringify<schema::Struct<schema::Member<T,Lits>...>> { - static void apply(std::stringstream& iss) { - iss << "saw::schema::Struct<"; - schema_stringify_member<schema::Member<T,Lits>...>::apply(iss); - iss << ">"; - } -}; - -template<typename... T, string_literal... Lits> -struct schema_stringify<schema::Union<schema::Member<T,Lits>...>> { - static void apply(std::stringstream& iss) { - iss << "saw::schema::Union<"; - schema_stringify_member<schema::Member<T,Lits>...>::apply(iss); - iss << ">"; - } -}; - -template<typename Req, typename Resp> -struct schema_stringify<schema::Function<Req, Resp>> { - static void apply(std::stringstream& iss){ - iss << "saw::schema::Function<"; - schema_stringify<Req>::apply(iss); - iss << ","; - schema_stringify<Resp>::apply(iss); - iss << ">"; - } -}; - -template<typename... T, string_literal... Lits> -struct schema_stringify<schema::Interface<schema::Member<T,Lits>...>>{ - static void apply(std::stringstream& iss){ - iss << "saw::schema::Interface<"; - schema_stringify_member<schema::Member<T,Lits>...>::apply(iss); - iss << ">"; - } -}; - -} diff --git a/c++/codec/simple.h b/c++/codec/simple.h deleted file mode 100644 index 8760754..0000000 --- a/c++/codec/simple.h +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include "data.h" -#include "stream_value.h" - -#include <forstio/core/buffer.h> -#include <forstio/core/error.h> - -namespace saw { -namespace encode { -struct KelSimple {}; -} - -template<typename T> -class data<T, encode::KelSimple> { -private: - ring_buffer buffer_; -public: - data() = default; - - buffer& get_buffer(){ - return buffer_; - } -}; - -namespace impl { -template<typename Schema, typename FromEnc> -class kelsimple_encode { - static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the kelsimple encoding."); -}; - -template<typename T, size_t N, typename FromEnc> -struct kelsimple_encode<schema::Primitive<T,N>, FromEnc> { - static error_or<void> encode(const data<schema::Primitive<T,N>, FromEnc>& from, buffer& to){ - auto eov = stream_value<schema::Primitive<T,N>>::encode(from.get(), to); - return eov; - } -}; - -template<typename T, size_t Dim, typename FromEnc> -struct kelsimple_encode<schema::Array<T,Dim>, FromEnc> { - template<std::size_t Level> - static error_or<void> encode_level(const data<schema::Array<T,Dim>, FromEnc>& from, buffer& to, std::array<std::size_t, Dim>& index){ - if constexpr (Dim == Level){ - return kelsimple_encode<T,FromEnc>::encode(from.at(index), to); - } else { - const std::size_t dim_size = from.get_dim_size(Level); - for(index[Level] = 0; (index.at(Level) < dim_size); ++index[Level]){ - auto eov = encode_level<Level+1>(from, to, index); - if(eov.is_error()){ - return eov; - } - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Array<T,Dim>, FromEnc>& from, buffer& to){ - { - for(uint64_t i = 0; i < Dim; ++i){ - auto eov = stream_value<schema::UInt64>::encode(from.get_dim_size(i), to); - if(eov.is_error()){ - return eov; - } - } - } - { - std::array<std::size_t, Dim> index; - std::fill(index.begin(), index.end(), 0); - - return encode_level<0>(from, to, index); - } - return void_t{}; - } -}; - -template<typename... T, string_literal... Lits, typename FromEnc> -struct kelsimple_encode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { - template<std::size_t i> - static error_or<void> encode_member(const data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - { - auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<Literal>(), to); - if(eov.is_error()){ - return eov; - } - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = encode_member<i+1>(from, to); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ - return encode_member<0>(from, to); - } -}; - -template<typename... T, string_literal... Lits, typename FromEnc> -struct kelsimple_encode<schema::Union<schema::Member<T,Lits>...>,FromEnc> { - template<std::size_t i> - static error_or<void> encode_member(const data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - if (from.template holds_alternative<Literal>()) { - { - auto eov = stream_value<schema::UInt64>::encode(static_cast<uint64_t>(i), to); - if(eov.is_error()){ - return eov; - } - } - { - auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<Literal>(), to); - if(eov.is_error()){ - return eov; - } - } - } - - if constexpr ( (i+1) < sizeof...(T) ){ - auto eov = encode_member<i+1>(from, to); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ - return encode_member<0>(from, to); - } -}; - -template<typename... T, typename FromEnc> -struct kelsimple_encode<schema::Tuple<T...>, FromEnc> { - template<std::size_t i> - static error_or<void> encode_member(const data<schema::Tuple<T...>, FromEnc>& from, buffer& to){ - using Type = typename parameter_pack_type<i,T...>::type; - { - auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<i>(), to); - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = encode_member<i+1>(from, to); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Tuple<T...>, FromEnc>& from, buffer& to){ - return encode_member<0>(from, to); - } -}; - -template<typename FromEnc> -struct kelsimple_encode<schema::String, FromEnc> { - static error_or<void> encode(const data<schema::String, FromEnc>& from, buffer& to){ - const auto str_size = from.size(); - typename native_data_type<schema::UInt64>::type str_len = static_cast<uint64_t>(str_size); - { - auto eov = stream_value<schema::UInt64>::encode(str_len, to); - if(eov.is_error()){ - return eov; - } - } - - for(std::size_t i = 0; i < str_size; ++i){ - auto eov = stream_value<schema::Int8>::encode(from.at(i), to); - if(eov.is_error()){ - return eov; - } - } - - return void_t{}; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -template<typename Schema, typename FromEnc> -class kelsimple_decode { - static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the kelsimple encoding."); -}; - -template<typename T, size_t N, typename FromEnc> -struct kelsimple_decode<schema::Primitive<T,N>, FromEnc> { - static error_or<void> decode(buffer& from, data<schema::Primitive<T,N>, FromEnc>& to){ - typename native_data_type<schema::Primitive<T,N>>::type val{}; - auto eov = stream_value<schema::Primitive<T,N>>::decode(val, from); - if (eov.is_value()) { - to.set(val); - } - return eov; - } - -}; - -template<typename T, size_t Dim, typename FromEnc> -struct kelsimple_decode<schema::Array<T,Dim>, FromEnc> { - template<std::size_t Level> - static error_or<void> decode_level(buffer& from, data<schema::Array<T,Dim>, FromEnc>& to, std::array<std::size_t, Dim>& index){ - if constexpr (Level == Dim){ - return kelsimple_decode<T, FromEnc>::decode(from, to.at(index)); - }else{ - const std::size_t dim_size = to.get_dim_size(Level); - for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ - auto eov = decode_level<Level+1>(from, to, index); - if(eov.is_error()){ - return eov; - } - } - } - return void_t{}; - } - - static error_or<void> decode(buffer& from, data<schema::Array<T,Dim>, FromEnc>& to){ - { - std::array<std::size_t, Dim> dims{}; - for(std::size_t i = 0; i < Dim; ++i){ - uint64_t val{}; - auto eov = stream_value<schema::UInt64>::decode(val, from); - if(eov.is_error()){ - return eov; - } - dims.at(i) = static_cast<std::size_t>(val); - } - to = data<schema::Array<T,Dim>,FromEnc>{dims}; - } - { - std::array<std::size_t, Dim> index{}; - return decode_level<0>(from, to, index); - } - return void_t{}; - } -}; -template<typename... T, string_literal... Lits, typename FromEnc> -struct kelsimple_decode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { - template<std::size_t i> - static error_or<void> decode_member(buffer& from, data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& to){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - { - auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<Literal>()); - if(eov.is_error()){ - return eov; - } - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = decode_member<i+1>(from, to); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - - } - static error_or<void> decode(buffer& from, data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& to){ - return decode_member<0>(from, to); - } - -}; - -template<typename... T, string_literal... Lits, typename FromEnc> -struct kelsimple_decode<schema::Union<schema::Member<T,Lits>...>,FromEnc> { - template<uint64_t i> - static error_or<void> decode_member(buffer& from, data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& to, uint64_t val){ - using Type = typename parameter_pack_type<i,T...>::type; - constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - - if( i == val ){ - to.template set<Literal>(data<Type, FromEnc>{}); - auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<Literal>()); - if(eov.is_error()){ - return eov; - } - return void_t{}; - } - - if constexpr ((i+1) < sizeof...(T)){ - auto eov = decode_member<i+1>(from, to, val); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - - } - static error_or<void> decode(buffer& from, data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& to){ - uint64_t val{}; - auto eov = stream_value<schema::UInt64>::decode(val, from); - if(eov.is_error()){ - return eov; - } - if ( val >= sizeof...(T) ){ - return make_error<err::invalid_state>(); - } - return decode_member<0>(from, to, val); - } - -}; - -template<typename... T, typename FromEnc> -struct kelsimple_decode<schema::Tuple<T...>,FromEnc> { - template<std::size_t i> - static error_or<void> decode_member(buffer& from, data<schema::Tuple<T...>, FromEnc>& to){ - using Type = typename parameter_pack_type<i,T...>::type; - { - auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<i>()); - } - if constexpr ((i+1) < sizeof...(T)){ - auto eov = decode_member<i+1>(from, to); - if(eov.is_error()){ - return eov; - } - } - return void_t{}; - - } - static error_or<void> decode(buffer& from, data<schema::Tuple<T...>, FromEnc>& to){ - return decode_member<0>(from, to); - } - -}; -template<typename FromEnc> -struct kelsimple_decode<schema::String, FromEnc> { - static error_or<void> decode(buffer& from, data<schema::String, FromEnc>& to){ - { - uint64_t val{}; - auto eov = stream_value<schema::UInt64>::decode(val, from); - if(eov.is_error()){ - return eov; - } - to = data<schema::String,FromEnc>{val}; - } - const std::size_t str_size = to.size(); - for(std::size_t i = 0; i < str_size; ++i){ - int8_t val{}; - auto eov = stream_value<schema::Int8>::decode(val, from); - if(eov.is_error()){ - return eov; - } - to.set_at(i, val); - } - return void_t{}; - } -}; - -} - -template<typename Schema> -class codec<Schema, encode::KelSimple> { -public: - struct config { - size_t depth = 16; - size_t length = 1024; - }; -private: - config cfg_; -public: - codec() = default; - - SAW_FORBID_COPY(codec); - SAW_DEFAULT_MOVE(codec); - - template<typename FromEnc> - error_or<void> encode(const data<Schema, FromEnc>& from_enc, data<Schema, encode::KelSimple>& to_enc){ - buffer_view buff_v{to_enc.get_buffer()}; - - auto eov = impl::kelsimple_encode<Schema, FromEnc>::encode(from_enc, buff_v); - - to_enc.get_buffer().write_advance(buff_v.write_offset()); - - return eov; - } - - template<typename ToDec> - error_or<void> decode(data<Schema, encode::KelSimple>& from_dec, data<Schema, ToDec>& to){ - buffer_view buff_v{from_dec.get_buffer()}; - - auto eov = impl::kelsimple_decode<Schema,ToDec>::decode(buff_v, to); - - return eov; - } -}; -} diff --git a/c++/codec/stream_value.h b/c++/codec/stream_value.h deleted file mode 100644 index 09203cb..0000000 --- a/c++/codec/stream_value.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include "schema.h" - -#include <forstio/core/buffer.h> -#include <forstio/core/error.h> - -#include <cstdint> -#include <cstring> - -namespace saw { -/** - * Helper class to encode/decode any primtive type into/from litte endian. - * The shift class does this by shifting bytes. This type of procedure is - * platform independent. So it does not matter if the memory layout is - * little endian or big endian - */ -template<typename T> class shift_stream_value { - static_assert(always_false<T>, "Shift Stream Value only supports Primitives"); -}; - -template <typename T, size_t N> class shift_stream_value<schema::Primitive<T,N>> { -public: - inline static error_or<void> decode(typename native_data_type<schema::Primitive<T,N>>::type &val, buffer &buff) { - if (buff.read_composite_length() < N) { - return make_error<err::buffer_exhausted>(); - } - - typename native_data_type<schema::Primitive<schema::UnsignedInteger,N>>::type raw = 0; - - for (size_t i = 0; i < N; ++i) { - raw |= (static_cast<typename native_data_type<schema::Primitive<T,N>>::type>(buff.read(i)) << (i * 8)); - } - - memcpy(&val, &raw, N); - buff.read_advance(N); - - return void_t{}; - } - - inline static error_or<void> encode(const typename native_data_type<schema::Primitive<T,N>>::type &val, buffer &buff) { - error err = buff.write_require_length(N); - if (err.failed()) { - return err; - } - - typename native_data_type<schema::Primitive<schema::UnsignedInteger,N>>::type raw{}; - memcpy(&raw, &val, N); - - for (size_t i = 0; i < N; ++i) { - buff.write(i) = raw >> (i * 8); - } - - buff.write_advance(N); - - return void_t{}; - } - - inline static size_t size() { return N; } -}; - -template <typename T> using stream_value = shift_stream_value<T>; - -} // namespace saw diff --git a/c++/core/.nix/derivation.nix b/c++/core/.nix/derivation.nix deleted file mode 100644 index 1618651..0000000 --- a/c++/core/.nix/derivation.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -}: - -stdenv.mkDerivation { - pname = "forstio-core"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/core/SConscript b/c++/core/SConscript deleted file mode 100644 index 04eb4c3..0000000 --- a/c++/core/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -core_env = env.Clone(); - -core_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -core_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += core_env.sources; -env.headers += core_env.headers; - -## Shared lib -objects_shared = [] -core_env.add_source_files(objects_shared, core_env.sources, shared=True); -core_env.library_shared = core_env.SharedLibrary('#build/forstio-core', [objects_shared]); - -## Static lib -objects_static = [] -core_env.add_source_files(objects_static, core_env.sources, shared=False); -core_env.library_static = core_env.StaticLibrary('#build/forstio-core', [objects_static]); - -# Set Alias -env.Alias('library_core', [core_env.library_shared, core_env.library_static]); - -env.targets += ['library_core']; - -# Install -env.Install('$prefix/lib/', [core_env.library_shared, core_env.library_static]); -env.Install('$prefix/include/forstio/core/', [core_env.headers]); diff --git a/c++/core/SConstruct b/c++/core/SConstruct deleted file mode 100644 index 865d131..0000000 --- a/c++/core/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=[]) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/core/array.h b/c++/core/array.h deleted file mode 100644 index f82b8d6..0000000 --- a/c++/core/array.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include <vector> - -namespace saw { -/** - * Array container avoiding exceptions - */ -template<typename T> -class array { -private: - std::vector<T> data_; -public: - array() = default; - - SAW_FORBID_COPY(array); - - T& at(size_t i) noexcept { - return data_.at(i); - } - - const T& at(size_t i) noexcept const { - return data_.at(i); - } - - size_t size() noexcept const { - return data_.size(); - } - - T& front() noexcept { - return data_.front(); - } - - const T& front() noexcept const { - return data_.front(); - } - - T& back() noexcept { - return data_.back(); - } - - const T& back() noexcept const { - return data_.back(); - } - - error_or<void> push(T val) noexcept { - try{ - data_.push_back(std::move(val)); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } - - error_or<void> pop() noexcept { - try{ - data_.pop_back(); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } - - error_or<void> resize(size_t i) noexcept { - try{ - data_.resize(i); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } - - error_or<void> reserve(size_t i) noexcept { - try{ - data_.reserve(i); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } - - error_or<void> shrink_to_fit() noexcept { - try{ - data_.shrink_to_fit(); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } -}; -} diff --git a/c++/core/buffer.cpp b/c++/core/buffer.cpp deleted file mode 100644 index 15f4cae..0000000 --- a/c++/core/buffer.cpp +++ /dev/null @@ -1,436 +0,0 @@ -#include "buffer.h" - -#include <algorithm> -#include <cassert> -#include <cstring> -#include <iomanip> -#include <sstream> - -namespace saw { -error buffer::push(const uint8_t &value) { - size_t write_remain = write_composite_length(); - if (write_remain > 0) { - write() = value; - write_advance(1); - } else { - return make_error<err::buffer_exhausted>(); - } - return no_error(); -} - -error buffer::push(const uint8_t &buffer, size_t size) { - error error = write_require_length(size); - if (error.failed()) { - return error; - } - const uint8_t *buffer_ptr = &buffer; - while (size > 0) { - size_t segment = std::min(write_segment_length(), size); - memcpy(&write(), buffer_ptr, segment); - write_advance(segment); - size -= segment; - buffer_ptr += segment; - } - return no_error(); -} - -error buffer::pop(uint8_t &value) { - if (read_composite_length() > 0) { - value = read(); - read_advance(1); - } else { - return make_error<err::buffer_exhausted>(); - } - return no_error(); -} - -error buffer::pop(uint8_t &buffer, size_t size) { - if (read_composite_length() >= size) { - uint8_t *buffer_ptr = &buffer; - while (size > 0) { - size_t segment = std::min(read_segment_length(), size); - memcpy(buffer_ptr, &read(), segment); - read_advance(segment); - size -= segment; - buffer_ptr += segment; - } - } else { - return make_error<err::buffer_exhausted>(); - } - return no_error(); -} - -/* -std::string buffer::to_hex() const { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - for (size_t i = 0; i < read_composite_length(); ++i) { - oss << std::setw(2) << (uint16_t)read(i); - if ((i + 1) < read_composite_length()) { - oss << ((i % 4 == 3) ? '\n' : ' '); - } - } - return oss.str(); -} -*/ - -std::string convert_to_string(const buffer& buff){ - std::ostringstream oss; - for (size_t i = 0; i < buff.read_composite_length(); ++i) { - oss << buff.read(i); - } - return oss.str(); -} - -buffer_view::buffer_view(buffer &buffer) - : buffer_{&buffer}, read_offset_{0}, write_offset_{0} {} - -size_t buffer_view::read_position() const { - return read_offset_ + buffer_->read_position(); -} - -size_t buffer_view::read_composite_length() const { - assert(read_offset_ <= buffer_->read_composite_length()); - if (read_offset_ > buffer_->read_composite_length()) { - return 0; - } - - return buffer_->read_composite_length() - read_offset_; -} - -size_t buffer_view::read_segment_length(size_t offset) const { - size_t off = offset + read_offset_; - assert(off <= buffer_->read_composite_length()); - if (off > buffer_->read_composite_length()) { - return 0; - } - - return buffer_->read_segment_length(off); -} - -void buffer_view::read_advance(size_t bytes) { - size_t offset = bytes + read_offset_; - assert(offset <= buffer_->read_composite_length()); - if (offset > buffer_->read_composite_length()) { - read_offset_ += buffer_->read_composite_length(); - return; - } - - read_offset_ += bytes; -} - -uint8_t &buffer_view::read(size_t i) { - size_t pos = i + read_offset_; - - assert(pos < buffer_->read_composite_length()); - - return buffer_->read(pos); -} - -const uint8_t &buffer_view::read(size_t i) const { - size_t pos = i + read_offset_; - - assert(pos < buffer_->read_composite_length()); - - return buffer_->read(pos); -} - -size_t buffer_view::write_position() const { - return write_offset_ + buffer_->write_position(); -} - -size_t buffer_view::write_composite_length() const { - assert(write_offset_ <= buffer_->write_composite_length()); - if (write_offset_ > buffer_->write_composite_length()) { - return 0; - } - - return buffer_->write_composite_length() - write_offset_; -} - -size_t buffer_view::write_segment_length(size_t offset) const { - size_t off = offset + write_offset_; - assert(off <= buffer_->write_composite_length()); - if (off > buffer_->write_composite_length()) { - return 0; - } - - return buffer_->write_segment_length(off); -} - -void buffer_view::write_advance(size_t bytes) { - size_t offset = bytes + write_offset_; - assert(offset <= buffer_->write_composite_length()); - if (offset > buffer_->write_composite_length()) { - write_offset_ += buffer_->write_composite_length(); - return; - } - - write_offset_ += bytes; -} - -uint8_t &buffer_view::write(size_t i) { - size_t pos = i + write_offset_; - - assert(pos < buffer_->write_composite_length()); - - return buffer_->write(pos); -} - -const uint8_t &buffer_view::write(size_t i) const { - size_t pos = i + write_offset_; - - assert(pos < buffer_->write_composite_length()); - - return buffer_->write(pos); -} - -error buffer_view::write_require_length(size_t bytes) { - return buffer_->write_require_length(bytes + write_offset_); -} - -size_t buffer_view::read_offset() const { return read_offset_; } - -size_t buffer_view::write_offset() const { return write_offset_; } - -ring_buffer::ring_buffer() : read_position_{0}, write_position_{0} { - buffer_.resize(RING_BUFFER_MAX_SIZE); -} - -ring_buffer::ring_buffer(size_t size) : read_position_{0}, write_position_{0} { - buffer_.resize(size); -} - -size_t ring_buffer::read_position() const { return read_position_; } - -/* - * If write is ahead of read it is a simple distance, but if read ist ahead of - * write then there are two segments - * - */ -size_t ring_buffer::read_composite_length() const { - return write_position() < read_position() - ? buffer_.size() - (read_position() - write_position()) - : (write_reached_read_ ? buffer_.size() - : write_position() - read_position()); -} - -/* - * If write is ahead then it's the simple distance again. If read is ahead it's - * until the end of the buffer/segment - */ -size_t ring_buffer::read_segment_length(size_t offset) const { - size_t read_composite = read_composite_length(); - assert(offset <= read_composite); - offset = std::min(offset, read_composite); - size_t remaining = read_composite - offset; - - size_t read_offset = read_position() + offset; - read_offset = read_offset >= buffer_.size() ? read_offset - buffer_.size() - : read_offset; - - // case 1 write is located before read and reached read - // then offset can be used normally - // case 2 write is located at read, but read reached write - // then it is set to zero by readCompositeLength() - // case 3 write is located after read - // since std::min you can use simple subtraction - if (write_position() < read_offset) { - return buffer_.size() - read_offset; - } - - if (write_position() == read_offset) { - if (remaining > 0) { - return buffer_.size() - read_offset; - } else { - return 0; - } - } - - return write_position() - read_offset; -} - -void ring_buffer::read_advance(size_t bytes) { - size_t read_composite = read_composite_length(); - - assert(bytes <= read_composite); - bytes = std::min(bytes, read_composite); - size_t advanced = read_position_ + bytes; - read_position_ = advanced >= buffer_.size() ? advanced - buffer_.size() - : advanced; - write_reached_read_ = bytes > 0 ? false : write_reached_read_; -} - -uint8_t &ring_buffer::read(size_t i) { - assert(i < read_composite_length()); - size_t pos = read_position_ + i; - pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; - return buffer_[pos]; -} - -const uint8_t &ring_buffer::read(size_t i) const { - assert(i < read_composite_length()); - size_t pos = read_position_ + i; - pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; - return buffer_[pos]; -} - -size_t ring_buffer::write_position() const { return write_position_; } - -size_t ring_buffer::write_composite_length() const { - return read_position() > write_position() - ? (read_position() - write_position()) - : (write_reached_read_ - ? 0 - : buffer_.size() - (write_position() - read_position())); -} - -size_t ring_buffer::write_segment_length(size_t offset) const { - size_t write_composite = write_composite_length(); - assert(offset <= write_composite); - offset = std::min(offset, write_composite); - - size_t write_offset = write_position() + offset; - write_offset = write_offset >= buffer_.size() - ? write_offset - buffer_.size() - : write_offset; - - if (read_position_ > write_offset) { - return read_position_ - write_offset; - } - - if (write_reached_read_) { - return 0; - } - - return buffer_.size() - write_offset; -} - -void ring_buffer::write_advance(size_t bytes) { - assert(bytes <= write_composite_length()); - size_t advanced = write_position_ + bytes; - write_position_ = advanced >= buffer_.size() ? advanced - buffer_.size() - : advanced; - - write_reached_read_ = - (write_position_ == read_position_ && bytes > 0 ? true : false); -} - -uint8_t &ring_buffer::write(size_t i) { - assert(i < write_composite_length()); - size_t pos = write_position_ + i; - pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; - return buffer_[pos]; -} - -const uint8_t &ring_buffer::write(size_t i) const { - assert(i < write_composite_length()); - size_t pos = write_position_ + i; - pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; - return buffer_[pos]; -} -/* - Error RingBuffer::increaseSize(size_t size){ - size_t old_size = buffer.size(); - size_t new_size = old_size + size; - buffer.resize(new_size); - if(readPosition() > writePosition() || (readPosition() == - writePosition() && write_reached_read)){ size_t remaining = old_size - - writePosition(); size_t real_remaining = 0; while(remaining > 0){ size_t - segment = std::min(remaining, size); memcpy(&buffer[new_size-segment], - &buffer[old_size-segment], segment); remaining -= segment; size -= segment; - old_size -= segment; - new_size -= segment; - } - } - - return noError(); - } -*/ -error ring_buffer::write_require_length(size_t bytes) { - size_t write_remain = write_composite_length(); - if (bytes > write_remain) { - return make_error<err::buffer_exhausted>(); - } - return no_error(); -} - -array_buffer::array_buffer(size_t size) - : read_position_{0}, write_position_{0} { - buffer_.resize(size); -} - -size_t array_buffer::read_position() const { return read_position_; } - -size_t array_buffer::read_composite_length() const { - return write_position_ - read_position_; -} - -size_t array_buffer::read_segment_length(size_t offset) const { - size_t read_composite = read_composite_length(); - assert(offset <= read_composite); - - offset = std::min(read_composite, offset); - size_t read_offset = read_position_ + offset; - - return write_position_ - read_offset; -} - -void array_buffer::read_advance(size_t bytes) { - assert(bytes <= read_composite_length()); - read_position_ += bytes; -} - -uint8_t &array_buffer::read(size_t i) { - assert(i < read_composite_length()); - - return buffer_[i + read_position_]; -} - -const uint8_t &array_buffer::read(size_t i) const { - assert(i + read_position_ < buffer_.size()); - - return buffer_[i + read_position_]; -} - -size_t array_buffer::write_position() const { return write_position_; } - -size_t array_buffer::write_composite_length() const { - assert(write_position_ <= buffer_.size()); - return buffer_.size() - write_position_; -} - -size_t array_buffer::write_segment_length(size_t offset) const { - assert(write_position_ <= buffer_.size()); - size_t write_composite = write_composite_length(); - - assert(offset <= write_composite); - offset = std::min(write_composite, offset); - size_t write_offset = write_position_ + offset; - - return buffer_.size() - write_offset; -} - -void array_buffer::write_advance(size_t bytes) { - assert(bytes <= write_composite_length()); - write_position_ += bytes; -} - -uint8_t &array_buffer::write(size_t i) { - assert(i < write_composite_length()); - return buffer_[i + write_position_]; -} - -const uint8_t &array_buffer::write(size_t i) const { - assert(i < write_composite_length()); - return buffer_[i + write_position_]; -} -error array_buffer::write_require_length(size_t bytes) { - size_t write_remain = write_composite_length(); - if (bytes > write_remain) { - return make_error<err::buffer_exhausted>(); - } - return no_error(); -} - -} // namespace saw diff --git a/c++/core/buffer.h b/c++/core/buffer.h deleted file mode 100644 index f0cf76e..0000000 --- a/c++/core/buffer.h +++ /dev/null @@ -1,199 +0,0 @@ -#pragma once - -#include "error.h" - -#include <array> -#include <cstdint> -#include <deque> -#include <list> -#include <string> -#include <vector> - -namespace saw { -/* - * Access class to reduce templated BufferSegments bloat - */ -class buffer { -protected: - ~buffer() = default; - -public: - virtual size_t read_position() const = 0; - virtual size_t read_composite_length() const = 0; - virtual size_t read_segment_length(size_t offset = 0) const = 0; - virtual void read_advance(size_t bytes) = 0; - - virtual uint8_t &read(size_t i = 0) = 0; - virtual const uint8_t &read(size_t i = 0) const = 0; - - virtual size_t write_position() const = 0; - virtual size_t write_composite_length() const = 0; - virtual size_t write_segment_length(size_t offset = 0) const = 0; - virtual void write_advance(size_t bytes) = 0; - - virtual uint8_t &write(size_t i = 0) = 0; - virtual const uint8_t &write(size_t i = 0) const = 0; - - /* - * Sometime buffers need to grow with a little more control - * than with push and pop for more efficient calls. - * There is nothing you can do if read hasn't been filled, but at - * least write can be increased if it is demanded. - */ - virtual error write_require_length(size_t bytes) = 0; - - error push(const uint8_t &value); - error push(const uint8_t &buffer, size_t size); - error pop(uint8_t &value); - error pop(uint8_t &buffer, size_t size); - -}; - -/** - * Converts a buffer to a string for convenience cases - */ -std::string convert_to_string(const buffer& buf); - -/** - * - */ - -/* - * A viewer class for buffers. - * Working on the reference buffer invalidates the buffer view - */ -class buffer_view : public buffer { -private: - buffer *buffer_; - size_t read_offset_; - size_t write_offset_; - -public: - buffer_view(buffer &); - - size_t read_position() const override; - size_t read_composite_length() const override; - size_t read_segment_length(size_t offset = 0) const override; - void read_advance(size_t bytes) override; - - uint8_t &read(size_t i = 0) override; - const uint8_t &read(size_t i = 0) const override; - - size_t write_position() const override; - size_t write_composite_length() const override; - size_t write_segment_length(size_t offset = 0) const override; - void write_advance(size_t bytes) override; - - uint8_t &write(size_t i = 0) override; - const uint8_t &write(size_t i = 0) const override; - - error write_require_length(size_t bytes) override; - - size_t read_offset() const; - size_t write_offset() const; -}; - -/* - * Buffer size meant for default allocation size of the ringbuffer since - * this class currently doesn't support proper resizing - */ -constexpr size_t RING_BUFFER_MAX_SIZE = 4096; -/* - * Buffer wrapping around if read caught up - */ -class ring_buffer final : public buffer { -private: - std::vector<uint8_t> buffer_; - size_t read_position_; - size_t write_position_; - bool write_reached_read_ = false; - -public: - ring_buffer(); - ring_buffer(size_t size); - - inline size_t size() const { return buffer_.size(); } - - inline uint8_t &operator[](size_t i) { return buffer_[i]; } - inline const uint8_t &operator[](size_t i) const { return buffer_[i]; } - - size_t read_position() const override; - size_t read_composite_length() const override; - size_t read_segment_length(size_t offset = 0) const override; - void read_advance(size_t bytes) override; - - uint8_t &read(size_t i = 0) override; - const uint8_t &read(size_t i = 0) const override; - - size_t write_position() const override; - size_t write_composite_length() const override; - size_t write_segment_length(size_t offset = 0) const override; - void write_advance(size_t bytes) override; - - uint8_t &write(size_t i = 0) override; - const uint8_t &write(size_t i = 0) const override; - - error write_require_length(size_t bytes) override; -}; - -/* - * One time buffer - */ -class array_buffer : public buffer { -private: - std::vector<uint8_t> buffer_; - - size_t read_position_; - size_t write_position_; - -public: - array_buffer(size_t size); - - size_t read_position() const override; - size_t read_composite_length() const override; - size_t read_segment_length(size_t offset = 0) const override; - void read_advance(size_t bytes) override; - - uint8_t &read(size_t i = 0) override; - const uint8_t &read(size_t i = 0) const override; - - size_t write_position() const override; - size_t write_composite_length() const override; - size_t write_segment_length(size_t offset = 0) const override; - void write_advance(size_t bytes) override; - - uint8_t &write(size_t i = 0) override; - const uint8_t &write(size_t i = 0) const override; - - error write_require_length(size_t bytes) override; -}; - -class chain_array_buffer : public buffer { -private: - std::deque<array_buffer> buffer_; - - size_t read_position_; - size_t write_position_; - -public: - chain_array_buffer(); - - size_t read_position() const override; - size_t read_composite_length() const override; - size_t read_segment_length(size_t offset = 0) const override; - void read_advance(size_t bytes) override; - - uint8_t &read(size_t i = 0) override; - const uint8_t &read(size_t i = 0) const override; - - size_t write_position() const override; - size_t write_composite_length() const override; - size_t write_segment_length(size_t offset = 0) const override; - void write_advance(size_t bytes) override; - - uint8_t &write(size_t i = 0) override; - const uint8_t &write(size_t i = 0) const override; - - error write_require_length(size_t bytes) override; -}; -} // namespace saw diff --git a/c++/core/common.h b/c++/core/common.h deleted file mode 100644 index a06c238..0000000 --- a/c++/core/common.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include <cstdint> -#include <memory> -#include <optional> -#include <utility> - -namespace saw { - -#define SAW_CONCAT_(x, y) x##y -#define SAW_CONCAT(x, y) SAW_CONCAT_(x, y) -#define SAW_UNIQUE_NAME(prefix) SAW_CONCAT(prefix, __LINE__) - -#define SAW_FORBID_COPY(classname) \ - classname(const classname &) = delete; \ - classname &operator=(const classname &) = delete - -#define SAW_FORBID_MOVE(classname) \ - classname(classname &&) = delete; \ - classname &operator=(classname &&) = delete - -#define SAW_DEFAULT_COPY(classname) \ - classname(const classname &) = default; \ - classname &operator=(const classname &) = default - -#define SAW_DEFAULT_MOVE(classname) \ - classname(classname &&) = default; \ - classname &operator=(classname &&) = default - -// In case of C++20 -#define SAW_ASSERT(expression) \ - assert(expression); \ - if (!(expression)) [[unlikely]] - -template <typename T> using maybe = std::optional<T>; - -template <typename T> using own = std::unique_ptr<T>; - -template <typename T> using our = std::shared_ptr<T>; - -template <typename T> using lent = std::weak_ptr<T>; - -template <typename T, class... Args> own<T> heap(Args &&...args) { - return own<T>(new T(std::forward<Args>(args)...)); -} - -template <typename T, class... Args> our<T> share(Args &&...args) { - return std::make_shared<T>(std::forward<Args>(args)...); -} - -template <typename T> T instance() noexcept; - -template <typename Func, typename T> struct return_type_helper { - typedef decltype(instance<Func>()(instance<T>())) Type; -}; -template <typename Func> struct return_type_helper<Func, void> { - typedef decltype(instance<Func>()()) Type; -}; - -template <typename Func, typename T> -using return_type = typename return_type_helper<Func, T>::Type; - -struct void_t {}; - -template <typename T> struct void_fix { typedef T Type; }; -template <> struct void_fix<void> { typedef void_t Type; }; -template <typename T> using fix_void = typename void_fix<T>::Type; - -template <typename T> struct void_unfix { typedef T Type; }; -template <> struct void_unfix<void_t> { typedef void Type; }; -template <typename T> using unfix_void = typename void_unfix<T>::Type; - -template <typename... T> constexpr bool always_false = false; - -} // namespace saw diff --git a/c++/core/error.cpp b/c++/core/error.cpp deleted file mode 100644 index 360e628..0000000 --- a/c++/core/error.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "error.h" - -namespace saw { -error::error(error::code code_, bool is_critical__) - : error_code_{static_cast<error::code>(code_)}, is_critical_{is_critical__} {} - -error::error(error::code code_, bool is_critical__, const std::string_view &msg) - : - error_code_{static_cast<error::code>(code_)} - , is_critical_{is_critical__}, error_message_{msg}{} - -error::error(error &&error) - : - error_code_{std::move(error.error_code_)} - , is_critical_{std::move(error.is_critical_)} - , error_message_{std::move(error.error_message_)}{} - -const std::string_view error::get_category() const { - auto& reg = impl::get_error_registry(); - - auto eov = reg.search_category(error_code_); - SAW_ASSERT(eov.is_value()){ - return "Error category not found. Report this error to the forstio maintainer"; - } - - return eov.get_value(); -} - -const std::string_view error::get_message() const { - return std::visit( - [this](auto &&arg) -> const std::string_view { - using T = std::decay_t<decltype(arg)>; - - if constexpr (std::is_same_v<T, std::string>) { - return std::string_view{arg}; - } else if constexpr (std::is_same_v<T, std::string_view>) { - return arg; - } else { - return "Error in class Error. Good luck :)"; - } - }, - error_message_); -} - -bool error::failed() const { - return !this->is_type<err::no_error>(); -} - -bool error::is_critical() const { - return is_critical_; -} - -bool error::is_recoverable() const { - return !is_critical_; -} - -error error::copy_error() const { - auto copy_error_code = error_code_; - error error{copy_error_code, is_critical_}; - - try { - error.error_message_ = error_message_; - } catch (const std::bad_alloc &) { - error.error_message_ = - std::string_view{"Error while copying Error string. Out of memory"}; - } - - return error; -} - -error::code error::get_id() const { return error_code_; } - -namespace impl { -error_registry& get_error_registry() { - static own<error_registry> reg = nullptr; - if(!reg){ - reg = heap<error_registry>(); - } - - assert(reg); - return *reg; -} -} - -error no_error(){ - return make_error<err::no_error>(); -} - -namespace impl { -error_registry::error_registry(): - infos_{ - { - err::no_error::description, - err::no_error::is_critical - }, - { - err::not_found::description, - err::not_found::is_critical - }, - { - err::out_of_memory::description, - err::out_of_memory::is_critical - } - } -{} - -error_or<const std::string_view> error_registry::search_category(const error::code& id) const { - if( id >= infos_.size()){ - return make_error<err::not_found>(); - } - - return infos_.at(id).description; -} - -error_or<error::code> error_registry::search_id(const std::string_view& desc)const{ - /** - * Search the index in the vector - */ - size_t i{}; - size_t info_max_size = std::min<std::size_t>(infos_.size(), std::numeric_limits<error::code>::max()); - for(i = 0; i < info_max_size; ++i){ - if(infos_.at(i).description == desc){ - break; - } - } - - if(i == info_max_size){ - return make_error<err::not_found>(); - } - - return static_cast<error::code>(i); -} - -error_or<error::code> error_registry::search_or_register_id(const std::string_view& desc, bool is_critical){ - auto err_or_id = search_id(desc); - - if(err_or_id.is_value()){ - return err_or_id.get_value(); - } - - auto& err = err_or_id.get_error(); - - if(err.is_type<err::not_found>()){ - size_t new_index = infos_.size(); - if(new_index == std::numeric_limits<error::code>::max()){ - return make_error<err::out_of_memory>("Error registry ids are exhausted"); - } - infos_.emplace_back(error_info{desc, is_critical}); - return static_cast<error::code>(new_index); - } - - return std::move(err); -} -} - -} // namespace saw diff --git a/c++/core/error.h b/c++/core/error.h deleted file mode 100644 index e816734..0000000 --- a/c++/core/error.h +++ /dev/null @@ -1,248 +0,0 @@ -#pragma once - -#include <algorithm> -#include <limits> -#include <string> -#include <string_view> -#include <variant> -#include <vector> - -#include <cassert> - -#include "common.h" - -namespace saw { -/** - * Utility class for generating errors. Has a base distinction between - * critical and recoverable errors. Additional code ids can be provided to the - * constructor if additional distinctions are necessary. - */ -class error { -public: - using code = uint32_t; -private: - code error_code_; - bool is_critical_; - std::variant<std::string_view, std::string> error_message_; - -public: - error(error::code id, bool is_critical); - error(error::code id, bool is_critical, const std::string_view &msg); - error(error &&error); - - SAW_FORBID_COPY(error); - - error &operator=(error &&) = default; - - const std::string_view get_message() const; - - const std::string_view get_category() const; - - bool failed() const; - - bool is_critical() const; - bool is_recoverable() const; - - /** - * Replaces the copy constructor. We need this since we want to explicitly copy and not implicitly - */ - error copy_error() const; - - code get_id() const; - - template<typename T> - bool is_type() const; -}; - -template<typename T> -class error_or; - -namespace impl { - -class error_registry { -private: - struct error_info { - error_info() = delete; - error_info(const std::string_view& d_, bool critical_):description{d_}, is_critical{critical_}{} - - std::string_view description; - bool is_critical; - }; - - std::vector<error_info> infos_; -public: - error_registry(); - - SAW_FORBID_COPY(error_registry); - SAW_FORBID_MOVE(error_registry); - - error_or<const std::string_view> search_category(const error::code& id) const; - - error_or<error::code> search_id(const std::string_view& desc) const; - - error_or<error::code> search_or_register_id(const std::string_view& desc, bool is_critical); -}; - -error_registry& get_error_registry(); - -template<typename T> -error::code get_template_id(){ - static error::code id = std::numeric_limits<error::code>::max(); - - if(id == std::numeric_limits<error::code>::max()){ - auto& reg = get_error_registry(); - - auto err_or_id = reg.search_or_register_id(T::description, T::is_critical); - if(err_or_id.is_error()){ - return std::numeric_limits<error::code>::max(); - } - - id = err_or_id.get_value(); - } - - return id; -} -} - -template<typename T> error make_error(const std::string_view& generic){ - error::code id = impl::get_template_id<T>(); - - return error{id, T::is_critical, generic}; -} - -template<typename T> error make_error(){ - error::code id = impl::get_template_id<T>(); - - return error{id, T::is_critical}; -} - -error make_error(error::code code, const std::string_view &generic); - - -namespace err { -struct no_error { - static constexpr std::string_view description = "No error has occured"; - static constexpr bool is_critical = false; -}; - -struct recoverable { - static constexpr std::string_view description = "Generic recoverable error"; - static constexpr bool is_critical = false; -}; - -struct critical { - static constexpr std::string_view description = "Generic critical error"; - static constexpr bool is_critical = true; -}; - -struct buffer_exhausted { - static constexpr std::string_view description = "Buffer Exhausted"; - static constexpr bool is_critical = false; -}; - -struct not_found { - static constexpr std::string_view description = "Not found"; - static constexpr bool is_critical = false; -}; - -struct out_of_memory { - static constexpr std::string_view description = "Out of memory"; - static constexpr bool is_critical = true; -}; - -struct invalid_state { - static constexpr std::string_view description = "Invalid state"; - static constexpr bool is_critical = true; -}; - -struct not_supported { - static constexpr std::string_view description = "Not supported"; - static constexpr bool is_critical = false; -}; - -struct not_implemented { - static constexpr std::string_view description = "Not implemented"; - static constexpr bool is_critical = true; -}; - -struct already_exists { - static constexpr std::string_view description = "Already exists"; - static constexpr bool is_critical = false; -}; -} - -/** - * Shorthand for no error happened - */ -error no_error(); - -/** - * Exception alternative. Since I code without exceptions this class is - * essentially a kind of exception replacement. - */ -template <typename T> class error_or; - -class error_or_value { -public: - virtual ~error_or_value() = default; - - template <typename T> error_or<unfix_void<T>> &as() { - return static_cast<error_or<unfix_void<T>> &>(*this); - } - - template <typename T> const error_or<unfix_void<T>> &as() const { - return static_cast<const error_or<unfix_void<T>> &>(*this); - } -}; - -template <typename T> class error_or final : public error_or_value { -private: - std::variant<error, fix_void<T>> value_or_error_; - - static_assert(!std::is_same_v<T, void_t>, - "Don't use internal private types"); - -public: - error_or():value_or_error_{fix_void<T>{}}{} - error_or(const fix_void<T> &value) : value_or_error_{value} {} - - error_or(fix_void<T> &&value) : value_or_error_{std::move(value)} {} - - error_or(const error &error) : value_or_error_{error} {} - error_or(error &&error) : value_or_error_{std::move(error)} {} - - bool is_value() const { - return std::holds_alternative<fix_void<T>>(value_or_error_); - } - - bool is_error() const { - return std::holds_alternative<class error>(value_or_error_); - } - - class error &get_error() { - return std::get<class error>(value_or_error_); - } - - const class error &get_error() const { - return std::get<class error>(value_or_error_); - } - - fix_void<T> &get_value() { return std::get<fix_void<T>>(value_or_error_); } - - const fix_void<T> &get_value() const { - return std::get<fix_void<T>>(value_or_error_); - } -}; - -template <typename T> class error_or<error_or<T>> { -private: - error_or() = delete; -}; - -template<typename T> -bool error::is_type() const { - - return error_code_ == impl::get_template_id<T>(); -} - -} // namespace saw diff --git a/c++/core/id.h b/c++/core/id.h deleted file mode 100644 index d836648..0000000 --- a/c++/core/id.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -namespace saw { -/** - * ID class which is tied to it's representing class - */ -template<typename T> -class id { -private: - /** - * Alias for the value type representing the ID - */ - using type = uint64_t; - - /** - * The low level value - */ - type value_; -public: - /** - * Basic constructor for the id class - */ - id(type val): - value_{val} - {} - - SAW_DEFAULT_COPY(id); - SAW_DEFAULT_MOVE(id); - - /** - * Equal operator for the id. - * Returns true if equal, false otherwise. - */ - bool operator==(const id<T>& rhs) const { - return value_ == rhs.value_; - } - - /** - * Unequal operator for the id. - * Returns false if equal, true otherwise. - */ - bool operator!=(const id<T>& rhs) const { - return !(*this == rhs); - } - - /** - * Returns a const ref of the underlying base type. - * Mostly used for internal purposes. - */ - const type& get_value() const { - return value_; - } -}; -} diff --git a/c++/core/id_map.h b/c++/core/id_map.h deleted file mode 100644 index d8329cf..0000000 --- a/c++/core/id_map.h +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once - -#include "id.h" -#include "error.h" - -#include <deque> - -namespace saw { -/** - * Fast random access id based container. - * - * Access - O(1) - * Insert - O(1) - * Erase - O(n) ? Dunno - */ -template<typename T> -class id_map final { -private: - /** - * Container which stores the primary data - */ - std::vector<T> data_; - /** - * Container which tracks free'd/fragmented elements within the - * main container - */ - std::deque<id<T>> free_ids_; - -private: - /** - * Tries to reduce top ids - */ - void reduce_free_ids() noexcept { - for(;;){ - if(free_ids_.empty()){ - break; - } - - if((free_ids_.front().get_value() + 1) < data_.size()){ - break; - } - - /** - * Can this throw? - */ - free_ids_.pop_front(); - } - } -public: - /** - * Default constructor - */ - id_map() = default; - - SAW_FORBID_COPY(id_map); - SAW_DEFAULT_MOVE(id_map); - - /** - * Inserts an element into the container and returns either an id on success - * or an error on failure. - */ - error_or<id<T>> insert(T val) noexcept { - /// @todo Fix size_t and id base type - if(free_ids_.empty()){ - try { - size_t i = data_.size(); - data_.emplace_back(std::move(val)); - return saw::id<T>{i}; - } catch(std::exception& e) { - return make_error<err::out_of_memory>(); - } - } else { - auto f_id = std::move(free_ids_.back()); - free_ids_.pop_back(); - data_.at(f_id.get_value()) = std::move(val); - return f_id; - } - - exit(-1); - // Dummy return since this is not reachable - return make_error<err::critical>(); - } - - /** - * Erase a value at this id. - */ - error_or<void> erase(const id<T>& val) noexcept { - /** - * If id is bigger than the available vector then return an error. - */ - if(val.get_value() >= data_.size()){ - return make_error<err::not_found>("ID is too large"); - } - - /** - * Check if it's the highest ID. Then we can just try to reduce the highest - * IDs. - */ - if((val.get_value() + 1) == data_.size()){ - data_.pop_back(); - this->reduce_free_ids(); - if(data_.size()*2 <= data_.capacity()){ - try { - data_.shrink_to_fit(); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - } - return void_t{}; - } - - /** - * Check if ID already exists with the free IDs. - * This would mean that a double free has occured. - */ - auto find_id = std::find(free_ids_.begin(), free_ids_.end(), val); - if(find_id != free_ids_.end()){ - return make_error<err::not_found>("ID value has already been freed"); - } - - /** - * Insert id into deque and sort it. - */ - try { - free_ids_.push_back(val); - } catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - std::stable_sort(free_ids_.begin(), free_ids_.end(), - [](const id<T>& left, const id<T>& right) -> bool { - return left.get_value() > right.get_value(); - } - ); - return void_t{}; - } -}; -} diff --git a/c++/core/mcts.h b/c++/core/mcts.h deleted file mode 100644 index 8a8f5ea..0000000 --- a/c++/core/mcts.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "tree.h" - -namespace saw { -template<typename T> -class mcts_tree { -private: - struct value { - uint64_t numerater; - uint64_t denominater; - T state; - - value() = default; - value(T st): - numerater{0}, - denominater{0}, - state{std::move(st)} - {} - }; - - tree_container<value, mcts_tree<T>> data_; -public: - mcts_tree() = default{ - data_.add(value{}); - } - - mcts_tree(T state){ - data_.add(value{std::move(state)}); - } - - size_t size() const { - return data_.size() - 1; - } - - T& get_state(){ - return data_.at(0).get_value().state; - } - - const T& get_state() const { - return data_.at(0).get_value().state; - } - - mcts_tree<T>& get_tree(size_t i){ - return data_.at(i+1).get_tree(); - } - - const mcts_tree<T>& get_tree(size_t i) const { - return data_.at(i+1).get_tree(); - } -}; -} diff --git a/c++/core/platonic.h b/c++/core/platonic.h deleted file mode 100644 index eefe99f..0000000 --- a/c++/core/platonic.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include "error.h" - -namespace saw { -namespace impl { -/** - * - */ -template<typename Prec, uint8_t N> -struct platonic_helper { - static_assert(always_false<Prec,N>, "Unsupported platonic body. Alternatively it's not a platonic body"); -}; - -template<typename Prec> -struct platonic_helper<Prec,4u> { - static constexpr surface_edges = 3u; -/* - static constexpr std::array<std::array<Prec,3u>, 4u> normals = { - {0.0, 0.0, -1.0}, // 1 - {}, // 2 - {}, // 3 - {} // 4 - }; -*/ -}; - -template<typename Prec> -struct platonic_helper<Prec,6u> { - static constexpr surface_edges = 4u; - - static constexpr std::array<std::array<Prec,3u>, 6u> normals = { - { 1.0, 0.0, 0.0}, // 1 - {-1.0, 0.0, 0.0}, // 2 - { 0.0, 1.0, 0.0}, // 3 - { 0.0,-1.0, 0.0}, // 4 - { 0.0, 0.0, 1.0}, // 5 - { 0.0, 0.0,-1.0} // 6 - }; -}; - -template<typename Prec> -struct platonic_helper<Prec,20u> { - static constexpr uint8_t surface_edges = 3u; -/* - static constexpr std::array<std::array<Prec,3u>, 20u> normals = { - {}, // 1 - {}, // 2 - {}, // 3 - {}, // 4 - {}, // 5 - {}, // 6 - {}, // 7 - {}, // 8 - {}, // 9 - {}, // 10 - {}, // 11 - {}, // 12 - {}, // 13 - {}, // 14 - {}, // 15 - {}, // 16 - {}, // 17 - {}, // 18 - {}, // 19 - {} // 20 - }; -*/ -}; -} -/** - * Container for describing each platonic body with - * helpers describing the orientation of each body. - */ -template<typename T, typename Prec, uint8_t N> -class platonic { -private: - /** - * Storage for the surfaces - */ - std::array<T,N> surfaces_; -public: - constexpr uint8_t get_surface_edge_size() constexpr { - return platonic_helper<T,N>::surface_edges; - } - - constexpr uint8_t get_surface_size() constexpr { - return N; - } - - T& at(uint8_t i){ - return surface_.at(i); - } - - const T& at(uint8_t i) const { - return surface_.at(i); - } - - constexpr std::array<Prec, 3>& get_surface_normal(size_t i) constexpr { - - } -}; -} diff --git a/c++/core/string_literal.h b/c++/core/string_literal.h deleted file mode 100644 index ccc8f49..0000000 --- a/c++/core/string_literal.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include <array> -#include <string_view> - -namespace saw { -/** - * Helper object which creates a templated string from the provided string - * literal. It guarantees compile time uniqueness and thus allows using strings - * in template parameters. - */ -template <class CharT, size_t N> class string_literal { -public: - static_assert(N > 0, "string_literal needs a null terminator"); - - constexpr string_literal(const CharT (&input)[N]) noexcept { - for (size_t i = 0; i < N; ++i) { - data[i] = input[i]; - } - } - - std::array<CharT, N> data{}; - - constexpr std::string_view view() const noexcept { - return std::string_view{data.data()}; - } - - constexpr bool - operator==(const string_literal<CharT, N> &) const noexcept = default; - - template <class CharTR, size_t NR> - constexpr bool - operator==(const string_literal<CharTR, NR> &) const noexcept { - return false; - } - - template<size_t NR> - constexpr string_literal<CharT, N+NR-1> operator+(const string_literal<CharT, NR>& rhs) const noexcept { - CharT sum[N+NR-1]; - - // The weird i+1 happens due to needing to skip the '\0' terminator - for(size_t i = 0; (i+1) < N; ++i){ - sum[i] = data[i]; - } - for(size_t i = 0; i < NR; ++i){ - sum[i+N-1] = rhs.data[i]; - } - - return string_literal<CharT, N+NR-1>{sum}; - } -}; - -template <typename T, T... Chars> -constexpr string_literal<T, sizeof...(Chars) + 1u> operator""_sl() { - return string_literal<T, sizeof...(Chars) + 1u>{{Chars..., '\0'}}; -} -} // namespace saw diff --git a/c++/core/templates.h b/c++/core/templates.h deleted file mode 100644 index 2eb0f7e..0000000 --- a/c++/core/templates.h +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once - -#include "string_literal.h" - -namespace saw { - -template <class T, class... TL> struct parameter_pack_index; - -template <class T, class... TL> struct parameter_pack_index<T, T, TL...> { - static constexpr size_t value = 0u; -}; - -template <class T, class TL0, class... TL> -struct parameter_pack_index<T, TL0, TL...> { - static constexpr size_t value = - 1u + parameter_pack_index<T, TL...>::value; -}; - -template <size_t N, class... T> struct parameter_pack_type { - static_assert(always_false<T...>, "Should've been caught by the specializations"); -}; - -template <class TN, class... T> struct parameter_pack_type<0, TN, T...> { - using type = TN; -}; - -template <size_t N, class TN, class... T> -struct parameter_pack_type<N, TN, T...> { - static_assert(sizeof...(T) > 0, "Exhausted parameters"); - static_assert(N > 0, "Invalid number. Should've been caught"); - using type = typename parameter_pack_type<N - 1, T...>::type; -}; -/* - * Nightmare inducing compiler problems found here. Somehow non-type - * string_literals cannot be resolved as non-type primitive template values can. - * This is the workaround - */ -template <string_literal V, string_literal Key0, string_literal... Keys> -struct parameter_key_pack_index_helper { - static constexpr size_t value = - (V == Key0) - ? (0u) - : (1u + parameter_key_pack_index_helper<V, Keys...>::value); -}; - -template <string_literal V, string_literal Key0> -struct parameter_key_pack_index_helper<V, Key0> { - static constexpr size_t value = (V == Key0) ? (0u) : (1u); -}; - -template <string_literal V, string_literal... Keys> -struct parameter_key_pack_index { - static constexpr size_t value = - parameter_key_pack_index_helper<V, Keys...>::value; - static_assert(value < sizeof...(Keys), - "Provided string_literal doesn't exist in searched list"); -}; - -template <size_t i, size_t s, string_literal Key0, string_literal... Keys> -struct parameter_key_pack_type_helper { - static constexpr string_literal literal = parameter_key_pack_type_helper<i, s+1, Keys...>::literal; -}; - -template <size_t i, string_literal Key0, string_literal... Keys> -struct parameter_key_pack_type_helper<i, i, Key0, Keys...> { - static constexpr string_literal literal = Key0; -}; - -template <size_t i, string_literal... Keys> -struct parameter_key_pack_type { - static constexpr string_literal literal = parameter_key_pack_type_helper<i, 0, Keys...>::literal; - - static_assert(i < sizeof...(Keys), "Provided index is too large for list"); -}; - -template<std::size_t i, std::size_t s, typename T, T V0, T... VN> -struct parameter_pack_value_helper { - static constexpr T value = parameter_pack_value_helper<i, s+1, T, VN...>::value; -}; - -template<std::size_t i, typename T, T V0, T... VN> -struct parameter_pack_value_helper<i, i, T, V0, VN...> { - static constexpr T value = V0; -}; - -template<std::size_t i, typename T, T... Values> -struct parameter_pack_value { - static constexpr T value = parameter_pack_value_helper<i, 0, T, Values...>::value; - static_assert(i < sizeof...(Values), "Provided index is too large for list"); -}; - -template<typename T, T... V> -struct ct_multiply; - -template<typename T> -struct ct_multiply<T> { - static constexpr T value = 1; -}; - -template<typename T, T V0, T... VN> -struct ct_multiply<T, V0, VN...> { - static constexpr T value = V0 * ct_multiply<T,VN...>::value; -}; - -namespace impl { -template<typename T, size_t i> -struct ct_convert_digits_table_helper { - static_assert(i <= 15, "Only conversion up to hex is supported"); - - static constexpr std::array<T, 16> table = { - '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F' - }; - - static constexpr T value = table[i]; -}; - -template<uint64_t Num, uint64_t Base, uint64_t... Digs> -struct ct_convert_digits_helper { - static constexpr size_t size = ct_convert_digits_helper<Num / Base, Base, Num % Base, Digs...>::size; - static constexpr std::array<uint64_t, size> value = ct_convert_digits_helper<Num / Base, Base, Num % Base, Digs...>::value; - static constexpr string_literal literal = ct_convert_digits_helper<Num / Base, Base, Num % Base, Digs...>::literal; -}; - -template<uint64_t Base, uint64_t... Digs> -struct ct_convert_digits_helper<0, Base, Digs...> { - static constexpr size_t size = sizeof...(Digs); - static constexpr std::array<uint64_t, size> value = {Digs...}; - static constexpr string_literal literal = {{ct_convert_digits_table_helper<char, Digs>::value..., '\0'}}; -}; - -template<uint64_t Base> -struct ct_convert_digits_helper<0, Base> { - static constexpr size_t size = 0; - static constexpr std::array<uint64_t, 1> value = {0}; - static constexpr string_literal literal = "0"_sl; -}; -} - -template<uint64_t Num, uint64_t Base> -struct ct_convert_to_digits { - static_assert(Base <= 16, "Only conversion up to hex is supported"); - - static constexpr size_t size = impl::ct_convert_digits_helper<Num, Base>::size; - static constexpr std::array<uint64_t, size> value = impl::ct_convert_digits_helper<Num, Base>::value; - static constexpr string_literal literal = impl::ct_convert_digits_helper<Num,Base>::literal; -}; -} diff --git a/c++/core/tree.h b/c++/core/tree.h deleted file mode 100644 index 68fa20a..0000000 --- a/c++/core/tree.h +++ /dev/null @@ -1,248 +0,0 @@ -#pragma once - -#include <variant> -#include <vector> - -#include "error.h" - -namespace saw { -/** - * Container with a simplistic approach to a branch - */ -template<typename T, typename Tree> -class branch; - -/** - * Tree object holding branches. - * - * The name comes from the fact a tree is acting as a node while the branch class is the - * edge to a leaf or other nodes. A tree holds the branches while the branch either has - * a leaf or another sub tree. - */ -template<typename T, typename Tree> -class tree_container final { -private: - /** - * Object holding the treeed branch instances - */ - std::vector<branch<T,Tree>> children_; -public: - /** - * Default constructor - */ - tree_container() = default; - - /** - * Destructor - */ - ~tree_container() = default; - - SAW_FORBID_COPY(tree_container); - SAW_DEFAULT_MOVE(tree_container); - - /** - * Reserve space for siz elements - */ - error_or<void> reserve(std::size_t siz){ - try{ - children_.reserve(siz); - }catch(const std::exception& e){ - (void) e; - - return make_error<err::out_of_memory>(); - } - - return void_t{}; - } - - /** - * Add a branch with a leaf attached to the tree - */ - error_or<std::size_t> add(T leaf) { - std::size_t index = size(); - try { - /** - * Technically we're adding a leaf on a branch - */ - children_.emplace_back(std::move(leaf)); - }catch(const std::exception& e){ - (void)e; - - return make_error<err::critical>(); - } - - return index; - } - - /** - * Add a branch to the tree with a tree attached - */ - error_or<std::size_t> add() { - std::size_t index = size(); - try { - - children_.emplace_back(Tree{}); - }catch(const std::exception& e){ - (void)e; - - return make_error<err::critical>(); - } - - return index; - } - - /** - * Returns the amount of branches contained within this tree level - */ - std::size_t size() const { - return children_.size(); - } - - /** - * Returns the branch at i - */ - branch<T,Tree>& at(std::size_t i){ - return children_.at(i); - } - - /** - * Returns the branch at i - */ - const branch<T,Tree>& at(std::size_t i) const { - return children_.at(i); - } -}; - -template<typename T, typename Tree> -class branch final { -private: - using type = std::variant<Tree,T>; - type tov_; - - /** - * We're friend classing the tree since it's way easier this way and the branch and tree - * class are intertwined heavily anyway. - */ -public: - /** - * - */ - branch():tov_{Tree{}}{} - - branch(Tree nd):tov_{std::move(nd)}{} - - branch(T val):tov_{std::move(val)}{} - - SAW_FORBID_COPY(branch); - SAW_DEFAULT_MOVE(branch); - - template<typename NT> - bool is() const { - return std::holds_alternative<NT>(tov_); - } - - bool is_tree() const { - return std::holds_alternative<Tree>(tov_); - } - - bool is_value() const { - return std::holds_alternative<T>(tov_); - } - - template<typename NT> - NT& get() { - return std::get<NT>(tov_); - } - - template<typename NT> - const NT& get() const { - return std::get<NT>(tov_); - } - - Tree& get_tree(){ - return std::get<Tree>(tov_); - } - - const Tree& get_tree() const { - return std::get<Tree>(tov_); - } - - T& get_value(){ - return std::get<T>(tov_); - } - - const T& get_value() const { - return std::get<T>(tov_); - } - - template<typename NT> - error_or<NT> extract(){ - if(!is<NT>()){ - return make_error<err::invalid_state>(); - } - - NT nd = std::move(std::get<NT>(tov_)); - tov_ = Tree{}; - - return nd; - } - - template<typename NT> - error_or<NT> replace(type nd){ - auto eon = extract<NT>(); - if(eon.is_error()){ - return eon; - } - - tov_ = std::move(nd); - - return eon; - } - - error_or<Tree> extract_tree() { - return extract<Tree>(); - } - - error_or<Tree> replace_tree(type nd){ - return replace<Tree>(std::move(nd)); - } - - error_or<T> extract_value() { - return extract<T>(); - } - - error_or<T> replace_value(type nd){ - return replace<T>(std::move(nd)); - } -}; - -template<typename T> -class tree { - private: - tree_container<T,tree<T>> data_; - public: - error_or<void> reserve(std::size_t size){ - return data_.reserve(size); - } - - size_t size() const { - return data_.size(); - } - - error_or<size_t> add() { - return data_.add(); - } - - error_or<size_t> add(T leaf){ - return data_.add(std::move(leaf)); - } - - branch<T, tree<T>>& at(size_t i){ - return data_.at(i); - } - - const branch<T, tree<T>>& at(size_t i) const { - return data_.at(i); - } -}; -} diff --git a/c++/device-hip/.nix/derivation.nix b/c++/device-hip/.nix/derivation.nix deleted file mode 100644 index 6849e6e..0000000 --- a/c++/device-hip/.nix/derivation.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-io_codec"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/device-hip/SConscript b/c++/device-hip/SConscript deleted file mode 100644 index 4ab02d6..0000000 --- a/c++/device-hip/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -dev_hip_env = env.Clone(); - -dev_hip_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -dev_hip_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += dev_hip_env.sources; -env.headers += dev_hip_env.headers; - -## Shared lib -objects_shared = [] -dev_hip_env.add_source_files(objects_shared, dev_hip_env.sources, shared=True); -dev_hip_env.library_shared = dev_hip_env.SharedLibrary('#build/forstio-device-hip', [objects_shared]); - -## Static lib -objects_static = [] -dev_hip_env.add_source_files(objects_static, dev_hip_env.sources, shared=False); -dev_hip_env.library_static = dev_hip_env.StaticLibrary('#build/forstio-device-hip', [objects_static]); - -# Set Alias -env.Alias('library_device-hip', [dev_hip_env.library_shared, dev_hip_env.library_static]); - -env.targets += ['library_device-hip']; - -# Install -env.Install('$prefix/lib/', [dev_hip_env.library_shared, dev_hip_env.library_static]); -env.Install('$prefix/include/forstio/device/hip/', [dev_hip_env.headers]); diff --git a/c++/device-hip/SConstruct b/c++/device-hip/SConstruct deleted file mode 100644 index 4e6e150..0000000 --- a/c++/device-hip/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-io']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/device-hip/rpc.h b/c++/device-hip/rpc.h deleted file mode 100644 index b6421ba..0000000 --- a/c++/device-hip/rpc.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace saw { -namespace rmt { -struct DeviceHip {}; -} -} diff --git a/c++/io-fs/.nix/derivation.nix b/c++/io-fs/.nix/derivation.nix deleted file mode 100644 index c8a4962..0000000 --- a/c++/io-fs/.nix/derivation.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ lib -, stdenvNoCC -, scons -, clang -, clang-tools -, version -, forstio -}: - -let - -in stdenvNoCC.mkDerivation { - pname = "forstio-io-fs"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - forstio.io - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/io-fs/SConscript b/c++/io-fs/SConscript deleted file mode 100644 index 0d85f62..0000000 --- a/c++/io-fs/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -io_env = env.Clone(); - -io_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -io_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += io_env.sources; -env.headers += io_env.headers; - -## Shared lib -objects_shared = [] -io_env.add_source_files(objects_shared, io_env.sources, shared=True); -io_env.library_shared = io_env.SharedLibrary('#build/forstio-io-fs', [objects_shared]); - -## Static lib -objects_static = [] -io_env.add_source_files(objects_static, io_env.sources, shared=False); -io_env.library_static = io_env.StaticLibrary('#build/forstio-io-fs', [objects_static]); - -# Set Alias -env.Alias('library_io', [io_env.library_shared, io_env.library_static]); - -env.targets += ['library_io']; - -# Install -env.Install('$prefix/lib/', [io_env.library_shared, io_env.library_static]); -env.Install('$prefix/include/forstio/io/fs/', [io_env.headers]); diff --git a/c++/io-fs/SConstruct b/c++/io-fs/SConstruct deleted file mode 100644 index 4cccf82..0000000 --- a/c++/io-fs/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-async']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/io-tls/.nix/derivation.nix b/c++/io-tls/.nix/derivation.nix deleted file mode 100644 index 23d8ba6..0000000 --- a/c++/io-tls/.nix/derivation.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -, gnutls -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-io-tls"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.io - gnutls - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/io-tls/SConscript b/c++/io-tls/SConscript deleted file mode 100644 index 4f88f37..0000000 --- a/c++/io-tls/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -io_tls_env = env.Clone(); - -io_tls_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -io_tls_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += io_tls_env.sources; -env.headers += io_tls_env.headers; - -## Shared lib -objects_shared = [] -io_tls_env.add_source_files(objects_shared, io_tls_env.sources, shared=True); -io_tls_env.library_shared = io_tls_env.SharedLibrary('#build/forstio-io-tls', [objects_shared]); - -## Static lib -objects_static = [] -io_tls_env.add_source_files(objects_static, io_tls_env.sources, shared=False); -io_tls_env.library_static = io_tls_env.StaticLibrary('#build/forstio-io-tls', [objects_static]); - -# Set Alias -env.Alias('library_io_tls', [io_tls_env.library_shared, io_tls_env.library_static]); - -env.targets += ['library_io_tls']; - -# Install -env.Install('$prefix/lib/', [io_tls_env.library_shared, io_tls_env.library_static]); -env.Install('$prefix/include/forstio/io/tls/', [io_tls_env.headers]); diff --git a/c++/io-tls/SConstruct b/c++/io-tls/SConstruct deleted file mode 100644 index fbd8657..0000000 --- a/c++/io-tls/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['gnutls','forstio-io']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/io-tls/tls.cpp b/c++/io-tls/tls.cpp deleted file mode 100644 index 9fa143c..0000000 --- a/c++/io-tls/tls.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "tls.h" - -#include <gnutls/gnutls.h> -#include <gnutls/x509.h> - -#include <forstio/io/io_helpers.h> - -#include <cassert> - -#include <iostream> - -namespace saw { - -class tls::impl { -public: - gnutls_certificate_credentials_t xcred; - -public: - impl() { - gnutls_global_init(); - gnutls_certificate_allocate_credentials(&xcred); - gnutls_certificate_set_x509_system_trust(xcred); - } - - ~impl() { - gnutls_certificate_free_credentials(xcred); - gnutls_global_deinit(); - } -}; - -static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, - size_t size); -static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size); - -tls::tls() : impl_{heap<tls::impl>()} {} - -tls::~tls() {} - -tls::impl &tls::get_impl() { return *impl_; } - -class tls_io_stream final : public io_stream { -private: - own<io_stream> internal; - gnutls_session_t session_handle; - -public: - tls_io_stream(own<io_stream> internal_) : internal{std::move(internal_)} {} - - ~tls_io_stream() { gnutls_bye(session_handle, GNUTLS_SHUT_RDWR); } - - error_or<size_t> read(void *buffer, size_t length) override { - ssize_t size = gnutls_record_recv(session_handle, buffer, length); - if (size < 0) { - if(gnutls_error_is_fatal(size) == 0){ - return make_error<err::recoverable>("Recoverable error on read in gnutls. TODO better error msg handling"); - // Leaving proper message handling done in previous error framework - //return recoverable_error([size](){return std::string{"Read recoverable Error "}+std::string{gnutls_strerror(size)};}, "Error read r"); - }else{ - return make_error<err::critical>("Fatal error on read in gnutls. TODO better error msg handling"); - } - }else if(size == 0){ - return make_error<err::disconnected>(); - } - - return static_cast<size_t>(length); - } - - conveyor<void> read_ready() override { return internal->read_ready(); } - - conveyor<void> on_read_disconnected() override { - return internal->on_read_disconnected(); - } - - error_or<size_t> write(const void *buffer, size_t length) override { - ssize_t size = gnutls_record_send(session_handle, buffer, length); - if(size < 0){ - if(gnutls_error_is_fatal(size) == 0){ - return make_error<err::recoverable>("Recoverable error on write in gnutls. TODO better error msg handling"); - }else{ - return make_error<err::critical>("Fatal error on write in gnutls. TODO better error msg handling"); - } - } - - return static_cast<size_t>(size); - } - - conveyor<void> write_ready() override { return internal->write_ready(); } - - gnutls_session_t &session() { return session_handle; } -}; - -tls_server::tls_server(own<server> srv) : internal{std::move(srv)} {} - -conveyor<own<io_stream>> tls_server::accept() { - SAW_ASSERT(internal) { return conveyor<own<io_stream>>{fix_void<own<io_stream>>{nullptr}}; } - return internal->accept().then([](own<io_stream> stream) -> own<io_stream> { - /// @todo handshake - - - return heap<tls_io_stream>(std::move(stream)); - }); -} - -namespace { -/* -* Small helper for setting up the nonblocking connection handshake -*/ -struct tls_client_stream_helper { -public: - own<conveyor_feeder<own<io_stream>>> feeder; - conveyor_sink connection_sink; - conveyor_sink stream_reader; - conveyor_sink stream_writer; - - own<tls_io_stream> stream = nullptr; -public: - tls_client_stream_helper(own<conveyor_feeder<own<io_stream>>> f): - feeder{std::move(f)} - {} - - void setupTurn(){ - SAW_ASSERT(stream){ - return; - } - - stream_reader = stream->read_ready().then([this](){ - turn(); - }).sink(); - - stream_writer = stream->write_ready().then([this](){ - turn(); - }).sink(); - } - - void turn(){ - if(stream){ - // Guarantee that the receiving end is already setup - SAW_ASSERT(feeder){ - return; - } - - auto &session = stream->session(); - - int ret; - do { - ret = gnutls_handshake(session); - } while ( (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) && gnutls_error_is_fatal(ret) == 0); - - if(gnutls_error_is_fatal(ret)){ - feeder->fail(make_error<err::critical>("Couldn't create Tls connection")); - stream = nullptr; - }else if(ret == GNUTLS_E_SUCCESS){ - feeder->feed(std::move(stream)); - } - } - } -}; -} - -own<server> tls_network::listen(network_address& address) { - return heap<tls_server>(internal.listen(address)); -} - -conveyor<own<io_stream>> tls_network::connect(network_address& address) { - // Helper setups - auto caf = new_conveyor_and_feeder<own<io_stream>>(); - own<tls_client_stream_helper> helper = heap<tls_client_stream_helper>(std::move(caf.feeder)); - tls_client_stream_helper* hlp_ptr = helper.get(); - - // Conveyor entangled structure - auto prim_conv = internal.connect(address).then([this, hlp_ptr, addr = address.address()]( - own<io_stream> stream) -> error_or<void> { - io_stream* inner_stream = stream.get(); - auto tls_stream = heap<tls_io_stream>(std::move(stream)); - - auto &session = tls_stream->session(); - - gnutls_init(&session, GNUTLS_CLIENT); - - gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(), - addr.size()); - - gnutls_set_default_priority(session); - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - tls_.get_impl().xcred); - gnutls_session_set_verify_cert(session, addr.c_str(), 0); - - gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(inner_stream)); - gnutls_transport_set_push_function(session, forst_tls_push_func); - gnutls_transport_set_pull_function(session, forst_tls_pull_func); - - // gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); - - hlp_ptr->stream = std::move(tls_stream); - hlp_ptr->setupTurn(); - hlp_ptr->turn(); - - return void_t{}; - }); - - helper->connection_sink = prim_conv.sink(); - - return caf.conveyor.attach(std::move(helper)); -} - -own<datagram> tls_network::datagram(network_address& address){ - ///@unimplemented - return nullptr; -} - -static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, - size_t size) { - io_stream *stream = reinterpret_cast<io_stream *>(p); - if (!stream) { - return -1; - } - - error_or<size_t> length = stream->write(data, size); - if (length.is_error() || !length.is_value()) { - return -1; - } - - return static_cast<ssize_t>(length.get_value()); -} - -static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size) { - io_stream *stream = reinterpret_cast<io_stream *>(p); - if (!stream) { - return -1; - } - - error_or<size_t> length = stream->read(data, size); - if (length.is_error() || !length.is_value()) { - return -1; - } - - return static_cast<ssize_t>(length.get_value()); -} - -tls_network::tls_network(tls& tls_, network &network) : tls_{tls_},internal{network} {} - -conveyor<own<network_address>> tls_network::resolve_address(const std::string &addr, - uint16_t port) { - /// @todo tls server name needed. Check validity. Won't matter later on, because gnutls should fail anyway. But - /// it's better to find the error source sooner rather than later - return internal.resolve_address(addr, port); -} - -std::optional<own<tls_network>> setup_tls_network(network &network) { - return std::nullopt; -} -} // namespace saw diff --git a/c++/io-tls/tls.h b/c++/io-tls/tls.h deleted file mode 100644 index 74b39ff..0000000 --- a/c++/io-tls/tls.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include <forstio/core/common.h> -#include <forstio/io/io.h> - -#include <optional> -#include <variant> - -namespace saw { -class tls; - -class tls_server final : public server { -private: - own<server> internal; - -public: - tls_server(own<server> srv); - - conveyor<own<io_stream>> accept() override; -}; - -class tls_network final : public network { -private: - tls& tls_; - network &internal; -public: - tls_network(tls& tls_, network &network_); - - conveyor<own<network_address>> resolve_address(const std::string &addr, uint16_t port = 0) override; - - own<server> listen(network_address& address) override; - - conveyor<own<io_stream>> connect(network_address& address) override; - - own<class datagram> datagram(network_address& address) override; -}; - -/** -* tls context class. -* Provides tls network class which ensures the usage of tls encrypted connections -*/ -class tls { -private: - class impl; - own<impl> impl_; -public: - tls(); - ~tls(); - - struct version { - struct tls_1_0{}; - struct tls_1_1{}; - struct tls_1_2{}; - }; - - struct options { - public: - version version; - }; - - impl &get_impl(); -private: - options options_; -}; - -std::optional<own<tls_network>> setup_tls_network(network &network); - -} // namespace saw diff --git a/c++/io/.nix/derivation.nix b/c++/io/.nix/derivation.nix deleted file mode 100644 index a14bd34..0000000 --- a/c++/io/.nix/derivation.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-io"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/io/SConscript b/c++/io/SConscript deleted file mode 100644 index 62ad58a..0000000 --- a/c++/io/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -io_env = env.Clone(); - -io_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -io_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += io_env.sources; -env.headers += io_env.headers; - -## Shared lib -objects_shared = [] -io_env.add_source_files(objects_shared, io_env.sources, shared=True); -io_env.library_shared = io_env.SharedLibrary('#build/forstio-io', [objects_shared]); - -## Static lib -objects_static = [] -io_env.add_source_files(objects_static, io_env.sources, shared=False); -io_env.library_static = io_env.StaticLibrary('#build/forstio-io', [objects_static]); - -# Set Alias -env.Alias('library_io', [io_env.library_shared, io_env.library_static]); - -env.targets += ['library_io']; - -# Install -env.Install('$prefix/lib/', [io_env.library_shared, io_env.library_static]); -env.Install('$prefix/include/forstio/io/', [io_env.headers]); diff --git a/c++/io/SConstruct b/c++/io/SConstruct deleted file mode 100644 index 4cccf82..0000000 --- a/c++/io/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-async']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/io/io.cpp b/c++/io/io.cpp deleted file mode 100644 index f0705d2..0000000 --- a/c++/io/io.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "io.h" - -#include <cassert> - -namespace saw { - -async_io_stream::async_io_stream(own<io_stream> str) - : stream_{std::move(str)}, - read_ready_{stream_->read_ready() - .then([this]() { read_stepper_.read_step(*stream_); }) - .sink()}, - write_ready_{stream_->write_ready() - .then([this]() { write_stepper_.write_step(*stream_); }) - .sink()}, - read_disconnected_{stream_->on_read_disconnected() - .then([this]() { - if (read_stepper_.on_read_disconnect) { - read_stepper_.on_read_disconnect->feed(); - } - }) - .sink()} {} - -void async_io_stream::read(void *buffer, size_t min_length, size_t max_length) { - SAW_ASSERT(buffer && max_length >= min_length && min_length > 0) { return; } - - SAW_ASSERT(!read_stepper_.read_task.has_value()) { return; } - - read_stepper_.read_task = read_task_and_step_helper::read_io_task{ - buffer, min_length, max_length, 0}; - read_stepper_.read_step(*stream_); -} - -conveyor<size_t> async_io_stream::read_done() { - auto caf = new_conveyor_and_feeder<size_t>(); - read_stepper_.read_done = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -conveyor<void> async_io_stream::on_read_disconnected() { - auto caf = new_conveyor_and_feeder<void>(); - read_stepper_.on_read_disconnect = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void async_io_stream::write(const void *buffer, size_t length) { - SAW_ASSERT(buffer && length > 0) { return; } - - SAW_ASSERT(!write_stepper_.write_task.has_value()) { return; } - - write_stepper_.write_task = - write_task_and_step_helper::write_io_task{buffer, length, 0}; - write_stepper_.write_step(*stream_); -} - -conveyor<size_t> async_io_stream::write_done() { - auto caf = new_conveyor_and_feeder<size_t>(); - write_stepper_.write_done = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -string_network_address::string_network_address(const std::string &address, - uint16_t port) - : address_value_{address}, port_value_{port} {} - -const std::string &string_network_address::address() const { - return address_value_; -} - -uint16_t string_network_address::port() const { return port_value_; } -} // namespace saw diff --git a/c++/io/io.h b/c++/io/io.h deleted file mode 100644 index 7653ace..0000000 --- a/c++/io/io.h +++ /dev/null @@ -1,219 +0,0 @@ -#pragma once - -#include <forstio/async/async.h> -#include <forstio/core/common.h> -#include "io_helpers.h" - -#include <string> -#include <variant> - -namespace saw { -/** - * Set of error common in io - */ -namespace err { -struct disconnected { - static constexpr std::string_view description = "Disconnected"; - static constexpr bool is_critical = true; -}; - -struct resource_busy { - static constexpr std::string_view description = "Resource busy"; - static constexpr bool is_critical = false; -}; -} -/* - * Input stream - */ -class input_stream { -public: - virtual ~input_stream() = default; - - virtual error_or<size_t> read(void *buffer, size_t length) = 0; - - virtual conveyor<void> read_ready() = 0; - - virtual conveyor<void> on_read_disconnected() = 0; -}; - -/* - * Output stream - */ -class output_stream { -public: - virtual ~output_stream() = default; - - virtual error_or<size_t> write(const void *buffer, size_t length) = 0; - - virtual conveyor<void> write_ready() = 0; -}; - -/* - * Io stream - */ -class io_stream : public input_stream, public output_stream { -public: - virtual ~io_stream() = default; -}; - -class async_input_stream { -public: - virtual ~async_input_stream() = default; - - virtual void read(void *buffer, size_t min_length, size_t max_length) = 0; - - virtual conveyor<size_t> read_done() = 0; - virtual conveyor<void> on_read_disconnected() = 0; -}; - -class async_output_stream { -public: - virtual ~async_output_stream() = default; - - virtual void write(const void *buffer, size_t length) = 0; - - virtual conveyor<size_t> write_done() = 0; -}; - -class async_io_stream final : public async_input_stream, - public async_output_stream { -private: - own<io_stream> stream_; - - conveyor_sink read_ready_; - conveyor_sink write_ready_; - conveyor_sink read_disconnected_; - - read_task_and_step_helper read_stepper_; - write_task_and_step_helper write_stepper_; - -public: - async_io_stream(own<io_stream> str); - - SAW_FORBID_COPY(async_io_stream); - SAW_FORBID_MOVE(async_io_stream); - - void read(void *buffer, size_t length, size_t max_length) override; - - conveyor<size_t> read_done() override; - - conveyor<void> on_read_disconnected() override; - - void write(const void *buffer, size_t length) override; - - conveyor<size_t> write_done() override; -}; - -class server { -public: - virtual ~server() = default; - - virtual conveyor<own<io_stream>> accept() = 0; -}; - -class network_address; -/** - * Datagram class. Bound to a local address it is able to receive inbound - * datagram messages and send them as well as long as an address is provided as - * well - */ -class datagram { -public: - virtual ~datagram() = default; - - virtual error_or<size_t> read(void *buffer, size_t length) = 0; - virtual conveyor<void> read_ready() = 0; - - virtual error_or<size_t> write(const void *buffer, size_t length, - network_address &dest) = 0; - virtual conveyor<void> write_ready() = 0; -}; - -class os_network_address; -class string_network_address; - -class network_address { -public: - using child_variant = - std::variant<os_network_address *, string_network_address *>; - - virtual ~network_address() = default; - - virtual network_address::child_variant representation() = 0; - - virtual const std::string &address() const = 0; - virtual uint16_t port() const = 0; -}; - -class os_network_address : public network_address { -public: - virtual ~os_network_address() = default; - - network_address::child_variant representation() override { return this; } -}; - -class string_network_address final : public network_address { -private: - std::string address_value_; - uint16_t port_value_; - -public: - string_network_address(const std::string &address, uint16_t port); - - const std::string &address() const override; - uint16_t port() const override; - - network_address::child_variant representation() override { return this; } -}; - -class network { -public: - virtual ~network() = default; - - /** - * Resolve the provided string and uint16 to the preferred storage method - */ - virtual conveyor<own<network_address>> - resolve_address(const std::string &addr, uint16_t port_hint = 0) = 0; - - /** - * Parse the provided string and uint16 to the preferred storage method - * Since no dns request is made here, no async conveyors have to be used. - */ - /// @todo implement - // virtual Own<NetworkAddress> parseAddress(const std::string& addr, - // uint16_t port_hint = 0) = 0; - - /** - * Set up a listener on this address - */ - virtual own<server> listen(network_address &bind_addr) = 0; - - /** - * Connect to a remote address - */ - virtual conveyor<own<io_stream>> connect(network_address &address) = 0; - - /** - * Bind a datagram socket at this address. - */ - virtual own<datagram> datagram(network_address &address) = 0; -}; - -class io_provider { -public: - virtual ~io_provider() = default; - - virtual own<input_stream> wrap_input_fd(int fd) = 0; - - virtual network &get_network() = 0; -}; - -struct async_io_context { - own<io_provider> io; - event_loop &event_loop; - event_port &event_port; -}; - -error_or<async_io_context> setup_async_io(); -} // namespace saw diff --git a/c++/io/io_helpers.cpp b/c++/io/io_helpers.cpp deleted file mode 100644 index c2cf2be..0000000 --- a/c++/io/io_helpers.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "io_helpers.h" - -#include "io.h" - -#include <cassert> - -namespace saw { -void read_task_and_step_helper::read_step(input_stream &reader) { - while (read_task.has_value()) { - read_io_task &task = *read_task; - - error_or<size_t> n_err = reader.read(task.buffer, task.max_length); - if (n_err.is_error()) { - const error &error = n_err.get_error(); - if (error.is_critical()) { - if (read_done) { - read_done->fail(error.copy_error()); - } - read_task = std::nullopt; - } - - break; - } else if (n_err.is_value()) { - size_t n = n_err.get_value(); - if (static_cast<size_t>(n) >= task.min_length && - static_cast<size_t>(n) <= task.max_length) { - if (read_done) { - read_done->feed(n + task.already_read); - } - read_task = std::nullopt; - } else { - task.buffer = static_cast<uint8_t *>(task.buffer) + n; - task.min_length -= static_cast<size_t>(n); - task.max_length -= static_cast<size_t>(n); - task.already_read += n; - } - - } else { - if (read_done) { - read_done->fail(make_error<err::invalid_state>("Read failed")); - } - read_task = std::nullopt; - } - } -} - -void write_task_and_step_helper::write_step(output_stream &writer) { - while (write_task.has_value()) { - write_io_task &task = *write_task; - - error_or<size_t> n_err = writer.write(task.buffer, task.length); - - if (n_err.is_value()) { - - size_t n = n_err.get_value(); - assert(n <= task.length); - if (n == task.length) { - if (write_done) { - write_done->feed(n + task.already_written); - } - write_task = std::nullopt; - } else { - task.buffer = static_cast<const uint8_t *>(task.buffer) + n; - task.length -= n; - task.already_written += n; - } - } else if (n_err.is_error()) { - const error &error = n_err.get_error(); - if (error.is_critical()) { - if (write_done) { - write_done->fail(error.copy_error()); - } - write_task = std::nullopt; - } - break; - } else { - if (write_done) { - write_done->fail(make_error<err::invalid_state>("Write failed")); - } - write_task = std::nullopt; - } - } -} - -} // namespace saw diff --git a/c++/io/io_helpers.h b/c++/io/io_helpers.h deleted file mode 100644 index 94e37f4..0000000 --- a/c++/io/io_helpers.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include <forstio/async/async.h> -#include <forstio/core/common.h> - -#include <cstdint> -#include <optional> - -namespace saw { -/* - * Helper classes for the specific driver implementations - */ - -/* - * Since I don't want to repeat these implementations for tls on unix systems - * and gnutls doesn't let me write or read into buffers I have to have this kind - * of strange abstraction. This may also be reusable for windows/macOS though. - */ -class input_stream; - -class read_task_and_step_helper { -public: - struct read_io_task { - void *buffer; - size_t min_length; - size_t max_length; - size_t already_read = 0; - }; - std::optional<read_io_task> read_task; - own<conveyor_feeder<size_t>> read_done = nullptr; - - own<conveyor_feeder<void>> on_read_disconnect = nullptr; - -public: - void read_step(input_stream &reader); -}; - -class output_stream; - -class write_task_and_step_helper { -public: - struct write_io_task { - const void *buffer; - size_t length; - size_t already_written = 0; - }; - std::optional<write_io_task> write_task; - own<conveyor_feeder<size_t>> write_done = nullptr; - -public: - void write_step(output_stream &writer); -}; -} // namespace saw diff --git a/c++/io/io_unix.cpp b/c++/io/io_unix.cpp deleted file mode 100644 index c3b4f17..0000000 --- a/c++/io/io_unix.cpp +++ /dev/null @@ -1,894 +0,0 @@ -#ifdef SAW_UNIX - -#include <csignal> -#include <sys/signalfd.h> - -#include <fcntl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <sys/epoll.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <cassert> -#include <cstring> - -#include <errno.h> -#include <unistd.h> - -#include <queue> -#include <sstream> -#include <unordered_map> -#include <vector> - -#include "io.h" - -namespace saw { -namespace unix { -constexpr int MAX_EPOLL_EVENTS = 256; - -class unix_event_port; -class i_fd_owner { -protected: - unix_event_port &event_port_; - -private: - int file_descriptor_; - int fd_flags_; - uint32_t event_mask_; - -public: - i_fd_owner(unix_event_port &event_port, int file_descriptor, int fd_flags, - uint32_t event_mask); - - virtual ~i_fd_owner(); - - virtual void notify(uint32_t mask) = 0; - - int fd() const { return file_descriptor_; } -}; - -class unix_event_port final : public event_port { -private: - int epoll_fd_; - int signal_fd_; - - sigset_t signal_fd_set_; - - std::unordered_multimap<Signal, own<conveyor_feeder<void>>> - signal_conveyors_; - - int pipefds_[2]; - - std::vector<int> to_unix_signal(Signal signal) const { - switch (signal) { - case Signal::User1: - return {SIGUSR1}; - case Signal::Terminate: - default: - return {SIGTERM, SIGQUIT, SIGINT}; - } - } - - Signal from_unix_signal(int signal) const { - switch (signal) { - case SIGUSR1: - return Signal::User1; - case SIGTERM: - case SIGINT: - case SIGQUIT: - default: - return Signal::Terminate; - } - } - - void notify_signal_listener(int sig) { - Signal signal = from_unix_signal(sig); - - auto equal_range = signal_conveyors_.equal_range(signal); - for (auto iter = equal_range.first; iter != equal_range.second; - ++iter) { - - if (iter->second) { - if (iter->second->space() > 0) { - iter->second->feed(); - } - } - } - } - - bool poll_impl(int time) { - epoll_event events[MAX_EPOLL_EVENTS]; - int nfds = 0; - do { - nfds = epoll_wait(epoll_fd_, events, MAX_EPOLL_EVENTS, time); - - if (nfds < 0) { - /// @todo error_handling - return false; - } - - for (int i = 0; i < nfds; ++i) { - if (events[i].data.u64 == 0) { - while (1) { - struct ::signalfd_siginfo siginfo; - ssize_t n = - ::read(signal_fd_, &siginfo, sizeof(siginfo)); - if (n < 0) { - break; - } - assert(n == sizeof(siginfo)); - - notify_signal_listener(siginfo.ssi_signo); - } - } else if (events[i].data.u64 == 1) { - uint8_t i; - if (pipefds_[0] < 0) { - continue; - } - while (1) { - ssize_t n = ::recv(pipefds_[0], &i, sizeof(i), 0); - if (n < 0) { - break; - } - } - } else { - i_fd_owner *owner = - reinterpret_cast<i_fd_owner *>(events[i].data.ptr); - if (owner) { - owner->notify(events[i].events); - } - } - } - } while (nfds == MAX_EPOLL_EVENTS); - - return true; - } - -public: - unix_event_port() : epoll_fd_{-1}, signal_fd_{-1} { - ::signal(SIGPIPE, SIG_IGN); - - epoll_fd_ = ::epoll_create1(EPOLL_CLOEXEC); - if (epoll_fd_ < 0) { - return; - } - - ::sigemptyset(&signal_fd_set_); - signal_fd_ = - ::signalfd(-1, &signal_fd_set_, SFD_NONBLOCK | SFD_CLOEXEC); - if (signal_fd_ < 0) { - return; - } - - struct epoll_event event; - memset(&event, 0, sizeof(event)); - event.events = EPOLLIN; - event.data.u64 = 0; - ::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, signal_fd_, &event); - - int rc = ::pipe2(pipefds_, O_NONBLOCK | O_CLOEXEC); - if (rc < 0) { - return; - } - memset(&event, 0, sizeof(event)); - event.events = EPOLLIN; - event.data.u64 = 1; - ::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, pipefds_[0], &event); - } - - ~unix_event_port() { - ::close(epoll_fd_); - ::close(signal_fd_); - ::close(pipefds_[0]); - ::close(pipefds_[1]); - } - - conveyor<void> on_signal(Signal signal) override { - auto caf = new_conveyor_and_feeder<void>(); - - signal_conveyors_.insert(std::make_pair(signal, std::move(caf.feeder))); - - std::vector<int> sig = to_unix_signal(signal); - - for (auto iter = sig.begin(); iter != sig.end(); ++iter) { - ::sigaddset(&signal_fd_set_, *iter); - } - ::sigprocmask(SIG_BLOCK, &signal_fd_set_, nullptr); - ::signalfd(signal_fd_, &signal_fd_set_, SFD_NONBLOCK | SFD_CLOEXEC); - - auto node = conveyor<void>::from_conveyor(std::move(caf.conveyor)); - return conveyor<void>::to_conveyor(std::move(node)); - } - - void poll() override { poll_impl(0); } - - void wait() override { poll_impl(-1); } - - void wait(const std::chrono::steady_clock::duration &duration) override { - poll_impl( - std::chrono::duration_cast<std::chrono::milliseconds>(duration) - .count()); - } - void - wait(const std::chrono::steady_clock::time_point &time_point) override { - auto now = std::chrono::steady_clock::now(); - if (time_point <= now) { - poll(); - } else { - poll_impl(std::chrono::duration_cast<std::chrono::milliseconds>( - time_point - now) - .count()); - } - } - - void wake() override { - /// @todo pipe() in the beginning and write something minor into it like - /// uint8_t or sth the value itself doesn't matter - if (pipefds_[1] < 0) { - return; - } - uint8_t i = 0; - ::send(pipefds_[1], &i, sizeof(i), MSG_DONTWAIT); - } - - void subscribe(i_fd_owner &owner, int fd, uint32_t event_mask) { - if (epoll_fd_ < 0 || fd < 0) { - return; - } - ::epoll_event event; - memset(&event, 0, sizeof(event)); - event.events = event_mask | EPOLLET; - event.data.ptr = &owner; - - if (::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event) < 0) { - /// @todo error_handling - return; - } - } - - void unsubscribe(int fd) { - if (epoll_fd_ < 0 || fd < 0) { - return; - } - if (::epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) < 0) { - /// @todo error_handling - return; - } - } -}; - -ssize_t unix_read(int fd, void *buffer, size_t length); -ssize_t unix_write(int fd, const void *buffer, size_t length); - -class unix_io_stream final : public io_stream, public i_fd_owner { -private: - own<conveyor_feeder<void>> read_ready_ = nullptr; - own<conveyor_feeder<void>> on_read_disconnect_ = nullptr; - own<conveyor_feeder<void>> write_ready_ = nullptr; - -public: - unix_io_stream(unix_event_port &event_port, int file_descriptor, - int fd_flags, uint32_t event_mask); - - error_or<size_t> read(void *buffer, size_t length) override; - - conveyor<void> read_ready() override; - - conveyor<void> on_read_disconnected() override; - - error_or<size_t> write(const void *buffer, size_t length) override; - - conveyor<void> write_ready() override; - - /* - void read(void *buffer, size_t min_length, size_t max_length) override; - Conveyor<size_t> readDone() override; - Conveyor<void> readReady() override; - - Conveyor<void> onReadDisconnected() override; - - void write(const void *buffer, size_t length) override; - Conveyor<size_t> writeDone() override; - Conveyor<void> writeReady() override; - */ - - void notify(uint32_t mask) override; -}; - -class unix_server final : public server, public i_fd_owner { -private: - own<conveyor_feeder<own<io_stream>>> accept_feeder_ = nullptr; - -public: - unix_server(unix_event_port &event_port, int file_descriptor, int fd_flags); - - conveyor<own<io_stream>> accept() override; - - void notify(uint32_t mask) override; -}; - -class unix_datagram final : public datagram, public i_fd_owner { -private: - own<conveyor_feeder<void>> read_ready_ = nullptr; - own<conveyor_feeder<void>> write_ready_ = nullptr; - -public: - unix_datagram(unix_event_port &event_port, int file_descriptor, - int fd_flags); - - error_or<size_t> read(void *buffer, size_t length) override; - conveyor<void> read_ready() override; - - error_or<size_t> write(const void *buffer, size_t length, - network_address &dest) override; - conveyor<void> write_ready() override; - - void notify(uint32_t mask) override; -}; - -/** - * Helper class which provides potential addresses to NetworkAddress - */ -class socket_address { -private: - union { - struct sockaddr generic; - struct sockaddr_un unix; - struct sockaddr_in inet; - struct sockaddr_in6 inet6; - struct sockaddr_storage storage; - } address_; - - socklen_t address_length_; - bool wildcard_; - - socket_address() : wildcard_{false} {} - -public: - socket_address(const void *sockaddr, socklen_t len, bool wildcard) - : address_length_{len}, wildcard_{wildcard} { - assert(len <= sizeof(address_)); - memcpy(&address_.generic, sockaddr, len); - } - - int socket(int type) const { - type |= SOCK_NONBLOCK | SOCK_CLOEXEC; - - int result = ::socket(address_.generic.sa_family, type, 0); - return result; - } - - bool bind(int fd) const { - if (wildcard_) { - int value = 0; - ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)); - } - int error = ::bind(fd, &address_.generic, address_length_); - return error < 0; - } - - struct ::sockaddr *get_raw() { - return &address_.generic; - } - - const struct ::sockaddr *get_raw() const { return &address_.generic; } - - socklen_t get_raw_length() const { return address_length_; } - - static std::vector<socket_address> resolve(std::string_view str, - uint16_t port_hint) { - std::vector<socket_address> results; - - struct ::addrinfo *head; - struct ::addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - - std::string port_string = std::to_string(port_hint); - bool wildcard = str == "*" || str == "::"; - std::string address_string{str}; - - int error = ::getaddrinfo(address_string.c_str(), port_string.c_str(), - &hints, &head); - - if (error) { - return {}; - } - - for (struct ::addrinfo *it = head; it != nullptr; it = it->ai_next) { - if (it->ai_addrlen > sizeof(socket_address::address_)) { - continue; - } - results.push_back({it->ai_addr, it->ai_addrlen, wildcard}); - } - ::freeaddrinfo(head); - return results; - } -}; - -class unix_network_address final : public os_network_address { -private: - const std::string path_; - uint16_t port_hint_; - std::vector<socket_address> addresses_; - -public: - unix_network_address(const std::string &path, uint16_t port_hint, - std::vector<socket_address> &&addr) - : path_{path}, port_hint_{port_hint}, addresses_{std::move(addr)} {} - - const std::string &address() const override; - - uint16_t port() const override; - - // Custom address info - socket_address &unix_address(size_t i = 0); - size_t unix_address_size() const; -}; - -class unix_network final : public network { -private: - unix_event_port &event_port_; - -public: - unix_network(unix_event_port &event_port); - - conveyor<own<network_address>> - resolve_address(const std::string &address, - uint16_t port_hint = 0) override; - - own<server> listen(network_address &addr) override; - - conveyor<own<io_stream>> connect(network_address &addr) override; - - own<class datagram> datagram(network_address &addr) override; -}; - -class unix_io_provider final : public io_provider { -private: - unix_event_port &event_port_; - class event_loop event_loop_; - - unix_network unix_network_; - -public: - unix_io_provider(unix_event_port &port_ref, own<event_port> port); - - class network &get_network() override; - - own<input_stream> wrap_input_fd(int fd) override; - - class event_loop &event_loop(); -}; - -i_fd_owner::i_fd_owner(unix_event_port &event_port, int file_descriptor, - int fd_flags, uint32_t event_mask) - : event_port_{event_port}, file_descriptor_{file_descriptor}, - fd_flags_{fd_flags}, event_mask_{event_mask} { - event_port_.subscribe(*this, file_descriptor, event_mask); -} - -i_fd_owner::~i_fd_owner() { - if (file_descriptor_ >= 0) { - event_port_.unsubscribe(file_descriptor_); - ::close(file_descriptor_); - } -} - -ssize_t unix_read(int fd, void *buffer, size_t length) { - return ::recv(fd, buffer, length, 0); -} - -ssize_t unix_write(int fd, const void *buffer, size_t length) { - return ::send(fd, buffer, length, 0); -} - -unix_io_stream::unix_io_stream(unix_event_port &event_port, int file_descriptor, - int fd_flags, uint32_t event_mask) - : i_fd_owner{event_port, file_descriptor, fd_flags, - event_mask | EPOLLRDHUP} {} - -error_or<size_t> unix_io_stream::read(void *buffer, size_t length) { - ssize_t read_bytes = unix_read(fd(), buffer, length); - if (read_bytes > 0) { - return static_cast<size_t>(read_bytes); - } else if (read_bytes == 0) { - return make_error<err::disconnected>(); - } - - return make_error<err::resource_busy>(); -} - -conveyor<void> unix_io_stream::read_ready() { - auto caf = new_conveyor_and_feeder<void>(); - read_ready_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -conveyor<void> unix_io_stream::on_read_disconnected() { - auto caf = new_conveyor_and_feeder<void>(); - on_read_disconnect_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -error_or<size_t> unix_io_stream::write(const void *buffer, size_t length) { - ssize_t write_bytes = unix_write(fd(), buffer, length); - if (write_bytes > 0) { - return static_cast<size_t>(write_bytes); - } - - int error = errno; - - if (error == EAGAIN || error == EWOULDBLOCK) { - return make_error<err::resource_busy>(); - } - - return make_error<err::disconnected>(); -} - -conveyor<void> unix_io_stream::write_ready() { - auto caf = new_conveyor_and_feeder<void>(); - write_ready_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void unix_io_stream::notify(uint32_t mask) { - if (mask & EPOLLOUT) { - if (write_ready_) { - write_ready_->feed(); - } - } - - if (mask & EPOLLIN) { - if (read_ready_) { - read_ready_->feed(); - } - } - - if (mask & EPOLLRDHUP) { - if (on_read_disconnect_) { - on_read_disconnect_->feed(); - } - } -} - -unix_server::unix_server(unix_event_port &event_port, int file_descriptor, - int fd_flags) - : i_fd_owner{event_port, file_descriptor, fd_flags, EPOLLIN} {} - -conveyor<own<io_stream>> unix_server::accept() { - auto caf = new_conveyor_and_feeder<own<io_stream>>(); - accept_feeder_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void unix_server::notify(uint32_t mask) { - if (mask & EPOLLIN) { - if (accept_feeder_) { - struct ::sockaddr_storage address; - socklen_t address_length = sizeof(address); - - int accept_fd = - ::accept4(fd(), reinterpret_cast<struct ::sockaddr *>(&address), - &address_length, SOCK_NONBLOCK | SOCK_CLOEXEC); - if (accept_fd < 0) { - return; - } - auto fd_stream = heap<unix_io_stream>(event_port_, accept_fd, 0, - EPOLLIN | EPOLLOUT); - accept_feeder_->feed(std::move(fd_stream)); - } - } -} - -unix_datagram::unix_datagram(unix_event_port &event_port, int file_descriptor, - int fd_flags) - : i_fd_owner{event_port, file_descriptor, fd_flags, EPOLLIN | EPOLLOUT} {} - -namespace { -ssize_t unix_read_msg(int fd, void *buffer, size_t length) { - struct ::sockaddr_storage their_addr; - socklen_t addr_len = sizeof(sockaddr_storage); - return ::recvfrom(fd, buffer, length, 0, - reinterpret_cast<struct ::sockaddr *>(&their_addr), - &addr_len); -} - -ssize_t unix_write_msg(int fd, const void *buffer, size_t length, - ::sockaddr *dest_addr, socklen_t dest_addr_len) { - - return ::sendto(fd, buffer, length, 0, dest_addr, dest_addr_len); -} -} // namespace - -error_or<size_t> unix_datagram::read(void *buffer, size_t length) { - ssize_t read_bytes = unix_read_msg(fd(), buffer, length); - if (read_bytes > 0) { - return static_cast<size_t>(read_bytes); - } - return make_error<err::resource_busy>(); -} - -conveyor<void> unix_datagram::read_ready() { - auto caf = new_conveyor_and_feeder<void>(); - read_ready_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -error_or<size_t> unix_datagram::write(const void *buffer, size_t length, - network_address &dest) { - unix_network_address &unix_dest = static_cast<unix_network_address &>(dest); - socket_address &sock_addr = unix_dest.unix_address(); - socklen_t sock_addr_length = sock_addr.get_raw_length(); - ssize_t write_bytes = unix_write_msg(fd(), buffer, length, - sock_addr.get_raw(), sock_addr_length); - if (write_bytes > 0) { - return static_cast<size_t>(write_bytes); - } - return make_error<err::resource_busy>(); -} - -conveyor<void> unix_datagram::write_ready() { - auto caf = new_conveyor_and_feeder<void>(); - write_ready_ = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void unix_datagram::notify(uint32_t mask) { - if (mask & EPOLLOUT) { - if (write_ready_) { - write_ready_->feed(); - } - } - - if (mask & EPOLLIN) { - if (read_ready_) { - read_ready_->feed(); - } - } -} - -namespace { -bool begins_with(const std::string_view &viewed, - const std::string_view &begins) { - return viewed.size() >= begins.size() && - viewed.compare(0, begins.size(), begins) == 0; -} - -std::variant<unix_network_address, unix_network_address *> -translate_network_address_to_unix_network_address(network_address &addr) { - auto addr_variant = addr.representation(); - std::variant<unix_network_address, unix_network_address *> os_addr = - std::visit( - [](auto &arg) - -> std::variant<unix_network_address, unix_network_address *> { - using T = std::decay_t<decltype(arg)>; - - if constexpr (std::is_same_v<T, os_network_address *>) { - return static_cast<unix_network_address *>(arg); - } - - auto sock_addrs = socket_address::resolve( - std::string_view{arg->address()}, arg->port()); - - return unix_network_address{arg->address(), arg->port(), - std::move(sock_addrs)}; - }, - addr_variant); - return os_addr; -} - -unix_network_address &translate_to_unix_address_ref( - std::variant<unix_network_address, unix_network_address *> &addr_variant) { - return std::visit( - [](auto &arg) -> unix_network_address & { - using T = std::decay_t<decltype(arg)>; - - if constexpr (std::is_same_v<T, unix_network_address>) { - return arg; - } else if constexpr (std::is_same_v<T, unix_network_address *>) { - return *arg; - } else { - static_assert(true, "Cases exhausted"); - } - }, - addr_variant); -} - -} // namespace - -own<server> unix_network::listen(network_address &addr) { - auto unix_addr_storage = - translate_network_address_to_unix_network_address(addr); - unix_network_address &address = - translate_to_unix_address_ref(unix_addr_storage); - - assert(address.unix_address_size() > 0); - if (address.unix_address_size() == 0) { - return nullptr; - } - - int fd = address.unix_address(0).socket(SOCK_STREAM); - if (fd < 0) { - return nullptr; - } - - int val = 1; - int rc = ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - if (rc < 0) { - ::close(fd); - return nullptr; - } - - bool failed = address.unix_address(0).bind(fd); - if (failed) { - ::close(fd); - return nullptr; - } - - ::listen(fd, SOMAXCONN); - - return heap<unix_server>(event_port_, fd, 0); -} - -conveyor<own<io_stream>> unix_network::connect(network_address &addr) { - auto unix_addr_storage = - translate_network_address_to_unix_network_address(addr); - unix_network_address &address = - translate_to_unix_address_ref(unix_addr_storage); - - assert(address.unix_address_size() > 0); - if (address.unix_address_size() == 0) { - return conveyor<own<io_stream>>{make_error<err::critical>()}; - } - - int fd = address.unix_address(0).socket(SOCK_STREAM); - if (fd < 0) { - return conveyor<own<io_stream>>{make_error<err::disconnected>()}; - } - - own<unix_io_stream> io_str = - heap<unix_io_stream>(event_port_, fd, 0, EPOLLIN | EPOLLOUT); - - bool success = false; - for (size_t i = 0; i < address.unix_address_size(); ++i) { - socket_address &addr_iter = address.unix_address(i); - int status = - ::connect(fd, addr_iter.get_raw(), addr_iter.get_raw_length()); - if (status < 0) { - int error = errno; - /* - * It's not connected yet... - * But edge triggered epolling means that it'll - * be ready when the signal is triggered - */ - - /// @todo Add limit node when implemented - if (error == EINPROGRESS) { - /* - Conveyor<void> write_ready = io_stream->writeReady(); - return write_ready.then( - [ios{std::move(io_stream)}]() mutable { - ios->write_ready = nullptr; - return std::move(ios); - }); - */ - success = true; - break; - } else if (error != EINTR) { - /// @todo Push error message from - return conveyor<own<io_stream>>{make_error<err::disconnected>()}; - } - } else { - success = true; - break; - } - } - - if (!success) { - return conveyor<own<io_stream>>{make_error<err::disconnected>()}; - } - - return conveyor<own<io_stream>>{std::move(io_str)}; -} - -own<datagram> unix_network::datagram(network_address &addr) { - auto unix_addr_storage = - translate_network_address_to_unix_network_address(addr); - unix_network_address &address = - translate_to_unix_address_ref(unix_addr_storage); - - SAW_ASSERT(address.unix_address_size() > 0) { return nullptr; } - - int fd = address.unix_address(0).socket(SOCK_DGRAM); - - int optval = 1; - int rc = - ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - if (rc < 0) { - ::close(fd); - return nullptr; - } - - bool failed = address.unix_address(0).bind(fd); - if (failed) { - ::close(fd); - return nullptr; - } - /// @todo - return heap<unix_datagram>(event_port_, fd, 0); -} - -const std::string &unix_network_address::address() const { return path_; } - -uint16_t unix_network_address::port() const { return port_hint_; } - -socket_address &unix_network_address::unix_address(size_t i) { - assert(i < addresses_.size()); - /// @todo change from list to vector? - return addresses_.at(i); -} - -size_t unix_network_address::unix_address_size() const { - return addresses_.size(); -} - -unix_network::unix_network(unix_event_port &event) : event_port_{event} {} - -conveyor<own<network_address>> -unix_network::resolve_address(const std::string &path, uint16_t port_hint) { - std::string_view addr_view{path}; - { - std::string_view str_begins_with = "unix:"; - if (begins_with(addr_view, str_begins_with)) { - addr_view.remove_prefix(str_begins_with.size()); - } - } - - std::vector<socket_address> addresses = - socket_address::resolve(addr_view, port_hint); - - return conveyor<own<network_address>>{ - heap<unix_network_address>(path, port_hint, std::move(addresses))}; -} - -unix_io_provider::unix_io_provider(unix_event_port &port_ref, - own<event_port> port) - : event_port_{port_ref}, event_loop_{std::move(port)}, unix_network_{ - port_ref} {} - -own<input_stream> unix_io_provider::wrap_input_fd(int fd) { - return heap<unix_io_stream>(event_port_, fd, 0, EPOLLIN); -} - -class network &unix_io_provider::get_network() { - return static_cast<class network &>(unix_network_); -} - -class event_loop &unix_io_provider::event_loop() { - return event_loop_; -} - -} // namespace unix - -error_or<async_io_context> setup_async_io() { - using namespace unix; - try { - own<unix_event_port> prt = heap<unix_event_port>(); - unix_event_port &prt_ref = *prt; - - own<unix_io_provider> io_provider = - heap<unix_io_provider>(prt_ref, std::move(prt)); - - event_loop &loop_ref = io_provider->event_loop(); - - return {{std::move(io_provider), loop_ref, prt_ref}}; - } catch (std::bad_alloc &) { - return make_error<err::out_of_memory>(); - } -} -} // namespace saw -#endif diff --git a/c++/io_codec/.nix/derivation.nix b/c++/io_codec/.nix/derivation.nix deleted file mode 100644 index 7cd55a8..0000000 --- a/c++/io_codec/.nix/derivation.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-io_codec"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.io - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/io_codec/SConscript b/c++/io_codec/SConscript deleted file mode 100644 index 0afd6d6..0000000 --- a/c++/io_codec/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -io_env = env.Clone(); - -io_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -io_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += io_env.sources; -env.headers += io_env.headers; - -## Shared lib -objects_shared = [] -io_env.add_source_files(objects_shared, io_env.sources, shared=True); -io_env.library_shared = io_env.SharedLibrary('#build/forstio-io_codec', [objects_shared]); - -## Static lib -objects_static = [] -io_env.add_source_files(objects_static, io_env.sources, shared=False); -io_env.library_static = io_env.StaticLibrary('#build/forstio-io_codec', [objects_static]); - -# Set Alias -env.Alias('library_io_codec', [io_env.library_shared, io_env.library_static]); - -env.targets += ['library_io_codec']; - -# Install -env.Install('$prefix/lib/', [io_env.library_shared, io_env.library_static]); -env.Install('$prefix/include/forstio/io_codec/', [io_env.headers]); diff --git a/c++/io_codec/SConstruct b/c++/io_codec/SConstruct deleted file mode 100644 index 4e6e150..0000000 --- a/c++/io_codec/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-io']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/io_codec/io_peer.h b/c++/io_codec/io_peer.h deleted file mode 100644 index b9a4b34..0000000 --- a/c++/io_codec/io_peer.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include <forstio/async/async.h> -#include <forstio/buffer.h> -#include <forsto/io/io.h> -#include <forstio/schema/message.h> - -namespace saw { - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer = message_container<Incoming>, - typename OutContainer = message_container<Outgoing>, - typename BufferT = ring_buffer> -class streaming_io_peer { -public: - /** - * - */ - streaming_io_peer( - own<conveyor_feeder<heap_message_root<Incoming, InContainer>>> feed, - own<async_io_stream> stream, Codec codec, BufferT in, BufferT out); - /** - * - */ - streaming_io_peer( - own<conveyor_feeder<heap_message_root<Incoming, InContainer>>> feed, - own<async_io_stream> stream); - - /** - * Deleted copy and move constructors - */ - SAW_FORBID_COPY(streaming_io_peer); - SAW_FORBID_MOVE(streaming_io_peer); - - /** - * Send a message to the remote peer - */ - error send(heap_message_root<Outgoing, OutContainer> builder); - - /** - * A phantom conveyor feeder. Meant for interfacing with other components - */ - conveyor_feeder<heap_message_root<Outgoing, OutContainer>> &feeder(); - - conveyor<void> on_read_disconnected(); - -private: - /// @unimplemented - class peer_conveyor_feeder final - : public conveyor_feeder<heap_message_root<Outgoing, OutContainer>> { - public: - peer_conveyor_feeder( - streaming_io_peer<Codec, Incoming, Outgoing, InContainer, - OutContainer, BufferT> &peer_) - : peer_{peer_} {} - - void feed(heap_message_root<Outgoing, OutContainer> &&data) override { - (void)data; - } - - void fail(error &&error) override { (void)error; } - - size_t space() const override { return 0; } - - size_t queued() const override { return 0; } - - private: - streaming_io_peer<Codec, Incoming, Outgoing, InContainer, OutContainer, - BufferT> &peer_; - }; - -private: - own<conveyor_feeder<heap_message_root<Incoming, InContainer>>> - incoming_feeder_ = nullptr; - - own<async_io_stream> io_stream_; - - Codec codec_; - - BufferT in_buffer_; - BufferT out_buffer_; - - conveyor_sink sink_read_; - conveyor_sink sink_write_; - - peer_conveyor_feeder conveyor_feeder_; -}; - -/** - * Setup new streaming io peer with the provided network protocols. - * This is a convenience wrapper intended for a faster setup of this class - */ -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer = message_container<Incoming>, - typename OutContainer = message_container<Outgoing>, - typename BufferT = ring_buffer> -std::pair<own<streaming_io_peer<Codec, Incoming, Outgoing, InContainer, - OutContainer, BufferT>>, - conveyor<heap_message_root<Incoming, InContainer>>> -new_streaming_io_peer(own<async_io_stream> stream); - -} // namespace saw - -#include "io_peer.tmpl.h" diff --git a/c++/io_codec/io_peer.tmpl.h b/c++/io_codec/io_peer.tmpl.h deleted file mode 100644 index 880a58a..0000000 --- a/c++/io_codec/io_peer.tmpl.h +++ /dev/null @@ -1,117 +0,0 @@ -namespace saw { - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer, typename OutContainer, typename BufferT> -streaming_io_peer<Codec, Incoming, Outgoing, InContainer, OutContainer, - BufferT>:: - streaming_io_peer( - own<conveyor_feeder<heap_message_root<Incoming, InContainer>>> feed, - own<async_io_stream> str) - : streaming_io_peer{std::move(feed), std::move(str), {}, {}, {}} {} - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer, typename OutContainer, typename BufferT> -streaming_io_peer<Codec, Incoming, Outgoing, InContainer, OutContainer, - BufferT>:: - streaming_io_peer( - own<conveyor_feeder<heap_message_root<Incoming, InContainer>>> feed, - own<async_io_stream> stream, Codec codec, BufferT in, BufferT out) - : incoming_feeder_{std::move(feed)}, - io_stream_{std::move(stream)}, codec_{std::move(codec)}, - in_buffer_{std::move(in)}, out_buffer_{std::move(out)}, - sink_read_{ - io_stream_->read_done() - .then([this](size_t bytes) -> error_or<void> { - in_buffer_.write_advance(bytes); - - if (in_buffer_.write_segment_length() == 0) { - return critical_error("Message too long"); - } - - io_stream_->read(&in_buffer_.write(), 1, - in_buffer_.write_segment_length()); - - while (true) { - auto root = heap_message_root<Incoming, InContainer>(); - auto builder = root.build(); - - error err = codec_.template decode<Incoming, InContainer>( - builder, in_buffer_); - if (err.is_critical()) { - return err; - } - - if (!err.failed()) { - incoming_feeder_->feed(std::move(root)); - } else { - break; - } - } - - return void_t{}; - }) - .sink([this](error err) { - incoming_feeder_->fail(err.copy_error()); - - return err; - })}, - sink_write_{io_stream_->write_done() - .then([this](size_t bytes) -> error_or<void> { - out_buffer_.read_advance(bytes); - if (out_buffer_.readCompositeLength() > 0) { - io_stream_->write( - &out_buffer_.read(), - out_buffer_.read_segment_length()); - } - - return void_t{}; - }) - .sink()} { - io_stream_->read(&in_buffer_.write(), 1, in_buffer_.write_segment_length()); -} - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer, typename OutContainer, typename BufferT> -error streaming_io_peer<Codec, Incoming, Outgoing, InContainer, OutContainer, - BufferT>::send(heap_message_root<Outgoing, OutContainer> - msg) { - bool restart_write = out_buffer_.read_segment_length() == 0; - - error err = - codec_.template encode<Outgoing, OutContainer>(msg.read(), out_buffer_); - if (err.failed()) { - return err; - } - - if (restart_write) { - io_stream_->write(&out_buffer_.read(), - out_buffer_.read_segment_length()); - } - - return no_error(); -} - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer, typename OutContainer, typename BufferT> -conveyor<void> -streaming_io_peer<Codec, Incoming, Outgoing, InContainer, OutContainer, - BufferT>::on_read_disconnected() { - return io_stream_->on_read_disconnected(); -} - -template <typename Codec, typename Incoming, typename Outgoing, - typename InContainer, typename OutContainer, typename BufferT> -std::pair<own<streaming_io_peer<Codec, Incoming, Outgoing, InContainer, - OutContainer, BufferT>>, - conveyor<heap_message_root<Incoming, InContainer>>> -newstreaming_io_peer(own<async_io_stream> stream) { - auto caf = - new_conveyor_and_feeder<heap_message_root<Incoming, InContainer>>(); - - return {heap<streaming_io_peer<Codec, Incoming, Outgoing, InContainer, - OutContainer, BufferT>>( - std::move(caf.feeder), std::move(stream)), - std::move(caf.conveyor)}; -} - -} // namespace saw diff --git a/c++/io_codec/rpc.h b/c++/io_codec/rpc.h deleted file mode 100644 index 020bf96..0000000 --- a/c++/io_codec/rpc.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include <forstio/codec/rpc.h> - -namespace saw { -namespace rmt { -struct Network {}; -} - -template<> -class remote<rmt::Network> { -private: - std::string addr_str_; -public: - remote(std::string addr_str); - - template<typename Interface> - conveyor<rpc_client<rmt::Network, Interface>> create_client(); -}; - -template<template Interface> -class rpc_client<rmt::Network, Interface> { -private: - own<io_stream> stream_; -public: - rpc_client(own<io_stream> stream); - - template<typename T> - remote_result<typename response<T>::type> call(typename request<T>::type req); -}; -} diff --git a/c++/test/.nix/derivation.nix b/c++/test/.nix/derivation.nix deleted file mode 100644 index c15421d..0000000 --- a/c++/test/.nix/derivation.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-test"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/test/SConscript b/c++/test/SConscript deleted file mode 100644 index 6379b24..0000000 --- a/c++/test/SConscript +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -test_env = env.Clone(); - -test_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -test_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += test_env.sources; -env.headers += test_env.headers; - -## Shared lib -objects = [] -test_env.add_source_files(objects, test_env.sources, shared=False); -test_env.library = test_env.StaticLibrary('#build/forstio-test', [objects]); - -# Set Alias -env.Alias('library_test', [test_env.library]); - -env.targets += ['library_test']; - -# Install -env.Install('$prefix/lib/', [test_env.library]); -env.Install('$prefix/include/forstio/test/', [test_env.headers]); diff --git a/c++/test/SConstruct b/c++/test/SConstruct deleted file mode 100644 index 0d7b7c6..0000000 --- a/c++/test/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-core']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/test/suite.cpp b/c++/test/suite.cpp deleted file mode 100644 index 0fca8f9..0000000 --- a/c++/test/suite.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "suite.h" - -#include <map> -#include <string> -#include <chrono> -#include <iostream> - -namespace saw { -namespace test { - test_case* testCaseHead = nullptr; - test_case** testCaseTail = &testCaseHead; - - test_case::test_case(const std::string& file_, uint line_, const std::string& description_): - file{file_}, - line{line_}, - description{description_}, - matched_filter{false}, - next{nullptr}, - prev{testCaseTail} - { - *prev = this; - testCaseTail = &next; - } - - test_case::~test_case(){ - *prev = next; - if( next == nullptr ){ - testCaseTail = prev; - }else{ - next->prev = prev; - } - } - - class test_runner { - private: - enum Colour { - RED, - GREEN, - BLUE, - WHITE - }; - - void write(Colour colour, const std::string& front, const std::string& message){ - std::string start_col, end_col; - switch(colour){ - case RED: start_col = "\033[0;1;31m"; break; - case GREEN: start_col = "\033[0;1;32m"; break; - case BLUE: start_col = "\033[0;1;34m"; break; - case WHITE: start_col = "\033[0m"; break; - } - end_col = "\033[0m"; - std::cout<<start_col<<front<<end_col<<message<<'\n'; - } - public: - void allowAll(){ - for(test_case* testCase = testCaseHead; testCase != nullptr; testCase = testCase->next){ - testCase->matched_filter = true; - } - } - - int run() { - size_t passed_count = 0; - size_t failed_count = 0; - - for(test_case* testCase = testCaseHead; testCase != nullptr; testCase =testCase->next){ - if(testCase->matched_filter){ - std::string name = testCase->file + std::string(":") + std::to_string(testCase->line) + std::string(": ") + testCase->description; - write(BLUE, "[ TEST ] ", name); - bool failed = true; - std::string fail_message; - auto start_clock = std::chrono::steady_clock::now(); - try { - testCase->run(); - failed = false; - }catch(std::exception& e){ - fail_message = e.what(); - failed = true; - } - auto stop_clock = std::chrono::steady_clock::now(); - - auto runtime_duration_intern = stop_clock - start_clock; - auto runtime_duration = std::chrono::duration_cast<std::chrono::microseconds>(runtime_duration_intern); - std::string message = name + std::string(" (") + std::to_string(runtime_duration.count()) + std::string(" µs)"); - if(failed){ - write(RED, "[ FAIL ] ", message + " " + fail_message); - ++failed_count; - }else{ - write(GREEN, "[ PASS ] ", message); - ++passed_count; - } - } - } - - if(passed_count>0) write(GREEN, std::to_string(passed_count) + std::string(" test(s) passed"), ""); - if(failed_count>0) write(RED, std::to_string(failed_count) + std::string(" test(s) failed"), ""); - return -failed_count; - } - }; -} -} - -int main() { - saw::test::test_runner runner; - runner.allowAll(); - int rv = runner.run(); - return rv<0?-1:0; -} diff --git a/c++/test/suite.h b/c++/test/suite.h deleted file mode 100644 index 34f29bf..0000000 --- a/c++/test/suite.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include <string> -#include <memory> -#include <stdexcept> -#include <type_traits> - -#include <forstio/core/common.h> - -namespace saw { -namespace test { -class test_runner; -class test_case { -private: - std::string file; - uint line; - std::string description; - bool matched_filter; - test_case* next; - test_case** prev; - - friend class test_runner; -public: - test_case(const std::string& file_, uint line_, const std::string& description_); - ~test_case(); - - virtual void run() = 0; -}; -} -} -#define SAW_TEST(description) \ - class SAW_UNIQUE_NAME(test_case) : public ::saw::test::test_case { \ - public: \ - SAW_UNIQUE_NAME(test_case)(): ::saw::test::test_case(__FILE__,__LINE__,description) {} \ - void run() override; \ - }SAW_UNIQUE_NAME(test_case_); \ - void SAW_UNIQUE_NAME(test_case)::run() - -#define SAW_EXPECT(expr, msg_split) \ - if( ! (expr) ){ \ - auto msg = msg_split; \ - throw std::runtime_error{std::string{msg}};\ - } diff --git a/c++/tools/.nix/derivation.nix b/c++/tools/.nix/derivation.nix deleted file mode 100644 index 6e3fbe1..0000000 --- a/c++/tools/.nix/derivation.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-tools"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.io - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/tools/SConscript b/c++/tools/SConscript deleted file mode 100644 index 7c9efd7..0000000 --- a/c++/tools/SConscript +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -tools_env = env.Clone(); - -tools_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -tools_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += tools_env.sources; -env.headers += tools_env.headers; - -## Static lib -objects_static = [] -tools_env.add_source_files(objects_static, tools_env.sources, shared=False); -tools_env.c_array_example = tools_env.Program('#build/forstio-c-array-example', [objects_static]); - -# Set Alias -env.Alias('tools_c_array_example', [tools_env.c_array_example]); - -env.targets += ['tools_c_array_example']; - -# Install -env.Install('$prefix/bin/', [tools_env.c_array_example]); diff --git a/c++/tools/SConstruct b/c++/tools/SConstruct deleted file mode 100644 index 9a02291..0000000 --- a/c++/tools/SConstruct +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=[ - 'forstio-core', - 'forstio-async', - 'forstio-codec' - ] -); -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/tools/c_gen_iface.cpp b/c++/tools/c_gen_iface.cpp deleted file mode 100644 index 996f3c3..0000000 --- a/c++/tools/c_gen_iface.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "c_gen_iface.hpp" - -int main(){ - // saw::generate_array_example(); - - auto eov = saw::generate_iface_example(); - if(eov.is_error()){ - return -1; - } - return 0; -} diff --git a/c++/tools/c_gen_iface.hpp b/c++/tools/c_gen_iface.hpp deleted file mode 100644 index e79e27f..0000000 --- a/c++/tools/c_gen_iface.hpp +++ /dev/null @@ -1,535 +0,0 @@ -#include <forstio/core/error.h> -#include <forstio/core/templates.h> -#include <forstio/codec/schema.h> - -#include <string> -#include <sstream> -#include <map> - -#include <iostream> - -#include <forstio/codec/schema_stringify.h> - -namespace saw { - -namespace impl { -/** - * Type meant to provide future help if I decide to introduce more maps - */ -struct c_types { - struct c_member { - std::string key; - std::string name; - bool is_primitive; - }; - - struct c_struct { - std::string kind; - std::string type; - std::string cpp_schema; - std::vector<c_member> members; - }; - - struct c_response { - std::string key; - bool is_primitive; - }; - - struct c_func { - std::string cpp_schema; - std::string cpp_name; - c_response response; - std::vector<c_member> requests; - }; - - using c_struct_map = std::map<std::string, c_struct>; - using c_func_map = std::map<std::string, c_func>; - - struct state { - std::string interface_schema; - c_struct_map struct_map; - c_func_map func_map; - std::string prefix; - std::string postfix; - std::string encoding; - }; -}; - -namespace schema { -using namespace saw::schema; -/** -Pseudo flattened -using Foo = Struct< - Member<Array<Int32>, "a"> - Member<Array<Float32>, "b"> ->; - -Needs to be flattened to - -template<typename InnerSchema> -using FlattenedSchemaElement = Struct< - Member<Array<String>, "path">, - Member<InnerSchema, "inner_schema"> ->; - -// Illegal, but doable with more lines of code -// Just use typename... T and -// "T..." for -// "Member<FlattenedSchemaElement<Ele>,Names>...>" -// and specialize somewhere else -template<typename... Ele, string_literal... Names> -using FlattenedSchema = Struct< - Member<String, "top_schema">, - Member<FlattenedSchemaElement<Ele>, Names>... ->; - */ -template<typename T> -struct schema_flattener { - static_assert(always_false<T>, "Not supported"); -}; - -template<typename... T, string_literal... Names> -struct schema_flattener<schema::Struct<schema::Member<T,Names>...>> { - -}; - ->; - -using StructBindingSchema = Struct< - Member<String, "kind">, - Member<String, "key">, - Member<String, "cpp_schema">, - Member<Array<String>, "members"> ->; - -using FunctionBindingSchema = Struct< - Member<String, "cpp_schema">, - Member<String, "name">, - Member<String, "foo"> ->; - -using BindingSchema = Struct< - Member<String, "interface_schema">, - Member<String, "prefix">, - Member<String, "postfix">, - Member<String, "encoding">, - Member<Array<StructBindingSchema>, "structs">, - Member<Array<FunctionBindingSchema>, "functions"> ->; -} - -/** - * Helper to determine if we are dealing with primitive types - */ -template<typename Schema> -struct c_is_primitive { - static constexpr bool value = false; -}; - -template<typename T, size_t N> -struct c_is_primitive<schema::Primitive<T,N>> { - static constexpr bool value = true; -}; - -template<typename Schema> -struct c_primitive_string { - static_assert(always_false<Schema>, "Not supported"); -}; - -template<> -struct c_primitive_string<schema::Int8> { - static constexpr std::string_view value = "int8_t"; -}; - -template<> -struct c_primitive_string<schema::Int16> { - static constexpr std::string_view value = "int16_t"; -}; - -template<> -struct c_primitive_string<schema::Int32> { - static constexpr std::string_view value = "int32_t"; -}; - -template<> -struct c_primitive_string<schema::Int64> { - static constexpr std::string_view value = "int64_t"; -}; - -template<> -struct c_primitive_string<schema::UInt8> { - static constexpr std::string_view value = "uint8_t"; -}; - -template<> -struct c_primitive_string<schema::UInt16> { - static constexpr std::string_view value = "uint16_t"; -}; - -template<> -struct c_primitive_string<schema::UInt32> { - static constexpr std::string_view value = "uint32_t"; -}; - -template<> -struct c_primitive_string<schema::UInt64> { - static constexpr std::string_view value = "uint64_t"; -}; - -template<> -struct c_primitive_string<schema::Float32> { - static constexpr std::string_view value = "float"; -}; - -template<> -struct c_primitive_string<schema::Float64> { - static constexpr std::string_view value = "double"; -}; - -template<typename Schema> -struct c_data_translater { - static_assert(always_false<Schema>, "Not supported"); -}; - -template<typename T, size_t N> -struct c_data_translater<schema::Primitive<T,N>> { - using StructMap = typename c_types::c_struct_map; - using Schema = schema::Primitive<T,N>; - - static error_or<void> generate(c_types::state& c_state, std::string& str){ - (void) c_state; - str += c_primitive_string<Schema>::value; - return void_t{}; - } -}; - -template<typename T, size_t Dim> -struct c_data_translater<schema::Array<T,Dim>> { - using Schema = schema::Array<T,Dim>; - using StructMap = typename c_types::c_struct_map; - - static error_or<void> generate(c_types::state& c_state, std::string& type_str){ - type_str = "array_"; - - std::string inner_type_str; - auto eov = impl::c_data_translater<T>::generate(c_state, inner_type_str); - if(eov.is_error()){ - return eov; - } - - type_str += inner_type_str; - - if(Dim > 1){ - type_str += "_"; - type_str += std::to_string(Dim); - type_str += "d"; - } - - if(c_state.struct_map.find(type_str) != c_state.struct_map.end()){ - return void_t{}; - } - - c_types::c_struct str; - - try { - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - str.cpp_schema = iss.str(); - }catch(const std::exception& e){ - return make_error<err::critical>(); - } - - /** - * Adding heap alloc data ptr - */ - { - c_types::c_member memb; - memb.key = inner_type_str; - memb.name = "data"; - memb.is_primitive = c_is_primitive<T>::value; - // fn.members.emplace_back(std::move(memb)); - - str.members.emplace_back(std::move(memb)); - } - { - c_types::c_member memb; - memb.key - } - - - str.def = "struct "; - str.def += type_str; - - str.def += " {\n"; - - str.def += "\t" + inner_type_str + "* data;\n"; - str.def += "\tsize_t size;\n"; - if( Dim > 1 ){ - str.def += "\tsize_t dims["+std::to_string(Dim)+"];\n"; - } - - str.def += "};\n"; - - c_state.struct_map.emplace(std::make_pair(type_str, std::move(str))); - return void_t{}; - } -}; - -template<typename Interface> -struct c_iface_translater { - static_assert(always_false<Interface>,"Not supported"); -}; - -template<class... Request, class Response, string_literal... Lits> -struct c_iface_translater<schema::Function<schema::Struct<schema::Member<Request, Lits>...>, Response>> { - using StructMap = typename c_types::c_struct_map; - using FuncMap = typename c_types::c_func_map; - - template<size_t i> - static error_or<void> generate_request_member(c_types::state& c_state, std::array<std::string, sizeof...(Request)>& type_arr){ - using Type = typename parameter_pack_type<i, Request...>::type; - // constexpr string_literal lit = parameter_key_pack_type<i, Lits...>::literal; - - auto eov = c_data_translater<Type>::generate(c_state, type_arr.at(i)); - if(eov.is_error()){ - return eov; - } - - if constexpr ((i+1) < sizeof...(Request)){ - auto eov = generate_request_member<i+1>(c_state, type_arr); - return eov; - } - - return void_t{}; - } - - template<size_t i> - static error_or<void> generate_parameter(std::string& param_use, const std::array<std::string, sizeof...(Request)>& req_type_arr){ - using Type = typename parameter_pack_type<i, Request...>::type; - constexpr string_literal lit = parameter_key_pack_type<i, Lits...>::literal; - - std::string used_param; - if constexpr (c_is_primitive<Type>::value){ - used_param += req_type_arr.at(i); - } else { - used_param += "const " + req_type_arr.at(i) + "*"; - } - param_use += used_param + " " + std::string{lit.view()}; - - if constexpr ( (i+1) < sizeof...(Request) ){ - param_use += ", "; - return generate_parameter<i+1>(param_use, req_type_arr); - } - - return void_t{}; - } - - static error_or<void> generate(c_types::state& c_state, const std::string& func_name){ - std::array<std::string, sizeof...(Request)> request_type_arr; - - if constexpr (sizeof...(Request) > 0){ - auto eov = generate_request_member<0>(c_state, request_type_arr); - if(eov.is_error()){ - return eov; - } - } - std::string response_type_str; - { - auto eov = c_data_translater<Response>::generate(c_state, response_type_str); - if(eov.is_error()){ - return eov; - } - } - std::string c_func_name = c_state.prefix + "_" + func_name; - - c_types::c_func fn; - fn.cpp_name = func_name; - fn.def = "int"; - std::string iface_ctx = c_state.prefix + "_iface_context* ctx"; - fn.def += " " + c_func_name + "(" + iface_ctx; - fn.def += ", " + response_type_str + "* out"; - if constexpr ( sizeof...(Request) > 0 ){ - fn.def += ", "; - auto eov = generate_parameter<0>(fn.def, request_type_arr); - if(eov.is_error()){ - return eov; - } - } - fn.def += ")"; - - fn.source = "{\n"; - // Check necessary pointers - fn.source += "\tassert(ctx);\n"; - fn.source += "\tif(!ctx){return -1;}\n\n"; - fn.source += "\tauto rmt = reinterpret_cast<interface<IfaceSchema, "; - fn.source += c_state.encoding; - fn.source += ">*>(ctx);\n"; - - // translate the input data - if constexpr (sizeof...(Request) > 0){ - // I need a recursive search for the types - } - - // Call the remote interface - fn.source += "\tauto eov = rmt->template call<\"" + fn.cpp_name + "\">(std::move(input));"; - fn.source += ");\n"; - - // translate the output data - fn.source += ""; - - // Close the brace - - fn.source += "}\n"; - - c_state.func_map.emplace(std::make_pair(c_func_name, std::move(fn))); - - return void_t{}; - } -}; - -template<class... Requests, class... Responses, string_literal... Names> -struct c_iface_translater<schema::Interface<schema::Member<schema::Function<Requests, Responses>, Names>...>> { - using Schema = schema::Interface<schema::Member<schema::Function<Requests, Responses>, Names>...>; - - template<size_t i> - static error_or<void> generate_member(c_types::state& c_state){ - using Req = typename parameter_pack_type<i,Requests...>::type; - using Resp = typename parameter_pack_type<i,Responses...>::type; - constexpr string_literal lit = parameter_key_pack_type<i, Names...>::literal; - - try{ - std::stringstream iss; - schema_stringify<Schema>::apply(iss); - c_state.interface_schema = iss.str(); - }catch(const std::exception& e){ - (void) e; - return make_error<err::critical>(); - } - - std::string c_func_name = c_state.prefix + "_" + std::string{lit.view()}; - if(c_state.func_map.find(c_func_name) != c_state.func_map.end()){ - return make_error<err::already_exists>(); - } - - { - std::string type_str; - auto eov = c_iface_translater<schema::Function<Req, Resp>>::generate(c_state, std::string{lit.view()}); - if(eov.is_error()){ - return eov; - } - } - - if constexpr ((i+1) < sizeof...(Requests) ){ - return generate_member<i+1>(c_state); - } - return void_t{}; - } - - static error_or<void> generate(c_types::state& c_state){ - if constexpr ( sizeof...(Requests) > 0 ){ - return generate_member<0>(c_state); - } - - return void_t{}; - } -}; -} - -template<typename Interface> -error_or<void> generate_c_interface(typename impl::c_types::state& state){ - auto eov = impl::c_iface_translater<Interface>::generate(state); - return eov; -} - -error_or<void> generate_iface_example(){ - using Request1 = schema::Struct< - schema::Member<schema::Int32, "foo">, - schema::Member<schema::Float64, "bar">, - schema::Member<schema::Array<schema::Float32,1>, "baz"> - >; - using Response1 = schema::Int32; - - using Func1 = schema::Function<Request1, Response1>; - - using Iface = schema::Interface< - schema::Member<Func1, "func_one"> - >; - - impl::c_types::state c_state; - c_state.prefix = "c_saw"; - c_state.encoding = "saw::encode::Native"; - - typename impl::c_types::c_struct_map& type_map = c_state.struct_map; - typename impl::c_types::c_func_map& func_map = c_state.func_map; - auto eov = generate_c_interface<Iface>(c_state); - if(eov.is_error()){ - return eov; - } - std::cout<<"Interface: "<<c_state.interface_schema<<std::endl; - std::cout<<"Prefix: "<<c_state.prefix<<std::endl; - std::cout<<"\nTypes: "<<std::endl; - - for(auto& iter : type_map){ - std::cout<<"\nType: \""<<iter.first<<"\""<<std::endl; - std::cout<<"Definition:\n\"\"\"\n"; - std::cout<<iter.second.def; - std::cout<<"\"\"\""<<std::endl; - std::cout<<"Schema: "<<iter.second.cpp_schema<<std::endl; - } - std::cout<<"\nFunctions: "<<std::endl; - - for(auto& iter : func_map){ - std::cout<<"\nSymbol: \""<<iter.first<<"\""<<std::endl; - std::cout<<"Definition:\n\"\"\"\n"; - std::cout<<iter.second.def<<";\n"; - std::cout<<"\"\"\""<<std::endl; - std::cout<<"\nSource:\n"<<iter.second.source<<std::endl; - } - - return eov; -} - -error_or<void> generate_array_example(){ - using Schema1 = schema::Array<schema::Int32,2>; - - using Schema2 = schema::Array<schema::Float64,5>; - - using Schema3 = schema::Array<schema::UInt16,1>; - - std::string prefix = "c_saw"; - impl::c_types::state c_state; - c_state.prefix = prefix; - { - std::string type_str; - auto eov = impl::c_data_translater<Schema1>::generate(c_state, type_str); - if(eov.is_error()){ - return eov; - } - } - { - std::string type_str; - auto eov = impl::c_data_translater<Schema2>::generate(c_state, type_str); - if(eov.is_error()){ - return eov; - } - } - { - std::string type_str; - auto eov = impl::c_data_translater<Schema3>::generate(c_state, type_str); - if(eov.is_error()){ - return eov; - } - } - - std::cout<<"Prefix: "<<c_state.prefix<<std::endl; - - for(auto& iter : c_state.struct_map){ - std::cout<<"\nType: \""<<iter.first<<"\""<<std::endl; - std::cout<<"Definition:\n\"\"\"\n"; - std::cout<<iter.second.def; - std::cout<<"\"\"\""<<std::endl; - } - - return void_t{}; -} -} diff --git a/c++/tools/cli_analyzer.hpp b/c++/tools/cli_analyzer.hpp deleted file mode 100644 index 295ddf6..0000000 --- a/c++/tools/cli_analyzer.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once - -#include <forstio/codec/schema.h> - -#include <iostream> - -namespace saw { -namespace impl { -struct cli_mode { - struct read {}; - struct write {}; -}; - -template<typename T, typename Encoding> -struct cli_traverser { - static_assert(always_false<T,Encoding>, "Not supported"); -}; - -template<typename Schema, typename Encoding> -struct cli_modifier { - codec<Schema, encode::Json> json; - codec<Schema, Encoding> encoded; - - error_or<void> read(data<Schema, Encoding>& enc_data, std::deque<std::string>& sch_path, std::string& json_data_str){ - data<Schema, encode::Native> native; - { - auto eov = encoded.decode<encode::Native>(enc_data, native); - if(eov.is_error()){ - return eov; - } - } - { - data<Schema, encode::Json> json_data; - auto eov = json.encode<encode::Native>(native, json_data); - if(eov.is_error()){ - return eov; - } - - json_data_str = convert_to_string(json_data.get_buffer()); - } - - return void_t{}; - } - - error_or<void> write(data<Schema, Encoding>& enc_data, std::deque<std::string>& sch_path, std::string& json_data_str){ - data<Schema, encode::Native> native; - { - /// @todo string to data - data<Schema, encode::Json> json_data{ std::string_view{json_data_str} }; - auto eov = json.decode<encode::Native>(json_data, native); - if(eov.is_error()){ - return eov; - } - } - { - auto eov = encoded.encode<encode::Native>(native, enc_data); - if(eov.is_error()){ - return eov; - } - }i - - return void_t{}; - - } -}; - -template<typename... T, string_literal... Lits, typename Encoding> -struct cli_traverser<schema::Struct<schema::Member<T,Lits>...>, Encoding> { - using Schema = schema::Struct<schema::Member<T,Lits>...>; - - template<typename Traversal> - static error_or<void> traverse(std::deque<std::string>& sch_path, std::string& json_data){ - if(sch_path.empty()){ - cli_modifier<Schema, Encoding> mod; - if constexpr (std::is_same_v<Traversal, cli_mode::read>){ - return mod.read(sch_path, json_data); - } else if constexpr (std::is_same_v<Traversal, cli_mode::write>) { - return mod.write(sch_path, json_data); - } else { - return make_error<err::invalid_state>(); - } - } else { - - } - - return void_t{}; - } -}; -} - -template<typename Schema, typename Encoding> -int modify_data_on_cli(int argc, char** argv){ - - /// @todo parse cli data - bool read_mode = true; - - std::deque<std::string> sch_path; - std::string json_data; - - if (read_mode) { - auto eov = impl::cli_modifier<Schema, Encoding>::traverse<impl::cli_mode::read>(sch_path, json_data); - if(eov.is_error()){ - return -1; - } - } else { - auto eov = impl::cli_modifier<Schema, Encoding>::traverse<impl::cli_mode::write>(sch_path, json_data); - if(eov.is_error()){ - return -1; - } - } - - return 0; -} -} diff --git a/c++/window-opengl/.nix/derivation.nix b/c++/window-opengl/.nix/derivation.nix deleted file mode 100644 index 40c25bb..0000000 --- a/c++/window-opengl/.nix/derivation.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -, xorg -, libGL -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-window-opengl"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.io - forstio.codec - forstio.window - xorg.libX11 - xorg.libxcb - libGL - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/window-opengl/SConscript b/c++/window-opengl/SConscript deleted file mode 100644 index 7beee1a..0000000 --- a/c++/window-opengl/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -window_env = env.Clone(); - -window_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -window_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += window_env.sources; -env.headers += window_env.headers; - -## Shared lib -objects_shared = [] -window_env.add_source_files(objects_shared, window_env.sources, shared=True); -window_env.library_shared = window_env.SharedLibrary('#build/forstio-window-opengl', [objects_shared]); - -## Static lib -objects_static = [] -window_env.add_source_files(objects_static, window_env.sources, shared=False); -window_env.library_static = window_env.StaticLibrary('#build/forstio-window-opengl', [objects_static]); - -# Set Alias -env.Alias('library_window_opengl', [window_env.library_shared, window_env.library_static]); - -env.targets += ['library_window_opengl']; - -# Install -env.Install('$prefix/lib/', [window_env.library_shared, window_env.library_static]); -env.Install('$prefix/include/forstio/window/opengl/', [window_env.headers]); diff --git a/c++/window-opengl/SConstruct b/c++/window-opengl/SConstruct deleted file mode 100644 index fc2c398..0000000 --- a/c++/window-opengl/SConstruct +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX', 'SAW_UNIX_XCB', 'SAW_OGL'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=[ - 'forstio-core', - 'forstio-io', - 'forstio-async', - 'forstio-codec' - ] -); -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/window-opengl/gl_backends.h b/c++/window-opengl/gl_backends.h deleted file mode 100644 index 652954f..0000000 --- a/c++/window-opengl/gl_backends.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace saw { -namespace gfx { -namespace backend { -struct gl_linux_xcb {}; -struct gl_wasm {}; -} -} -} diff --git a/c++/window-opengl/gl_context.h b/c++/window-opengl/gl_context.h deleted file mode 100644 index 685e527..0000000 --- a/c++/window-opengl/gl_context.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -namespace saw { -namespace gfx { -class gl_settings { -public: - uint8_t gl_major = 3; - uint8_t gl_minor = 3; - - enum class render_type : int32_t { rgba }; - - render_type render_t = render_type::rgba; - - bool renderable = true; - - bool window_type = true; - - enum class drawable_type : int32_t { - window_bit = 0x01, - pixmap_bit = 0x02, - pbuffer_bit = 0x04 - }; - - drawable_type drawable_t = drawable_type::window_bit; - - bool double_buffer = true; - int red_bits = 8; - int green_bits = 8; - int blue_bits = 8; - int alpha_bits = 8; - - int depth_bits = 24; - int stencil_bits = 8; - - bool core_profile = true; -}; - -template<typename T> -class gpu_context; - - -} -} diff --git a/c++/window-opengl/gl_window.h b/c++/window-opengl/gl_window.h deleted file mode 100644 index 3bb9f83..0000000 --- a/c++/window-opengl/gl_window.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace saw { -namespace gfx { -template<typename T> -class gpu_window; -} -} diff --git a/c++/window-opengl/gl_xcb.cpp b/c++/window-opengl/gl_xcb.cpp deleted file mode 100644 index 5ea03f3..0000000 --- a/c++/window-opengl/gl_xcb.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "gl_xcb.h" - -#include <cassert> -#include <cstdint> -#include <set> - -namespace saw { -namespace gfx { -namespace { -glx_library_extensions load_glx_library_extensions(const char* extension_string){ - std::string_view extensions_view{extension_string}; - - std::set<std::string_view> extensions; - - for(;;){ - size_t n = extensions_view.find_first_of(' '); - if( n != extensions_view.npos && n < extensions_view.size()){ - std::string_view sub_glx_ext = extensions_view.substr(0,n); - extensions.insert(sub_glx_ext); - extensions_view.remove_prefix(n+1); - } else { - break; - } - } - - auto find = extensions.find("GLX_ARB_create_context"); - GLXContext (*glXCreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, Bool, const int*) = nullptr; - if(find != extensions.end()){ - glXCreateContextAttribsARB = reinterpret_cast<GLXContext(*)( - Display*, GLXFBConfig, GLXContext, Bool, const int*)>( - glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"))); - } - - return {extensions_view, glXCreateContextAttribsARB}; -} - -int translate_render_type_settings(gl_settings::render_type cmp){ - switch(cmp){ - case gl_settings::render_type::rgba: - return GLX_RGBA_BIT; - } - return 0; -} - -int translate_drawable_type_settings(gl_settings::drawable_type cmp){ - int i = 0; - if (static_cast<int32_t>(cmp) & - static_cast<int32_t>(gl_settings::drawable_type::window_bit)) { - i |= static_cast<int32_t>(GLX_WINDOW_BIT); - } - if (static_cast<int32_t>(cmp) & - static_cast<int32_t>(gl_settings::drawable_type::pixmap_bit)) { - i |= static_cast<int32_t>(GLX_PIXMAP_BIT); - } - if (static_cast<int32_t>(cmp) & - static_cast<int32_t>(gl_settings::drawable_type::pbuffer_bit)) { - i |= static_cast<int32_t>(GLX_PBUFFER_BIT); - } - return i; -} -} - -gpu_context<backend::gl_linux_xcb>::gpu_context(const glx_library_extensions& ext_lib, - own<device<backend::linux_xcb>> dev, int visual_id, GLXContext context, GLXFBConfig fb_config): ext_lib_{ext_lib}, device_{std::move(dev)}, visual_id_{visual_id}, context_{context}, fb_config_{fb_config}{} - -gpu_context<backend::gl_linux_xcb>::~gpu_context(){ - assert(device_); - assert(device_->get_xcb_display()); - - if(context_){ - /// @todo Check if this context is bound and only unbind if that is the case - // ::glXMakeContextCurrent(device_->get_xcb_display(), None, None, nullptr); - ::glXDestroyContext(device_->get_xcb_display(), context_); - } - device_->flush(); -} - -own<gpu_window<backend::gl_linux_xcb>> gpu_context<backend::gl_linux_xcb>::create_window(const video_mode& vid_mode, std::string_view title_view){ - - SAW_ASSERT(device_){ - return nullptr; - } - - own<window<backend::linux_xcb>> win = device_->create_xcb_window(vid_mode, title_view, visual_id_); - if(!win){ - return nullptr; - } - - ::GLXWindow glx_win = glXCreateWindow(device_->get_xcb_display(), fb_config_, win->get_xcb_window_handle(), nullptr); - return heap<gpu_window<backend::gl_linux_xcb>>(std::move(win), *this, glx_win); -} - -void gpu_context<backend::gl_linux_xcb>::flush(){ - assert(device_); - if(device_){ - device_->flush(); - } -} - -own<gpu_context<backend::gl_linux_xcb> > create_gl_context(io_provider& prov, const gl_settings& settings){ - auto eodev = create_xcb_device(prov); - if(eodev.is_error()){ - return nullptr; - } - own<device<backend::linux_xcb>>& device = eodev.get_value(); - if (!device) { - return nullptr; - } - - /* - * Translate all attributes - */ - std::vector<int> attributes; - attributes.reserve(33); - - attributes.push_back(GLX_X_RENDERABLE); - attributes.push_back(settings.renderable ? True : False); - - attributes.push_back(GLX_RENDER_TYPE); - attributes.push_back(translate_render_type_settings(settings.render_t)); - - attributes.push_back(GLX_RED_SIZE); - attributes.push_back(settings.red_bits); - - attributes.push_back(GLX_GREEN_SIZE); - attributes.push_back(settings.green_bits); - - attributes.push_back(GLX_BLUE_SIZE); - attributes.push_back(settings.blue_bits); - - attributes.push_back(GLX_ALPHA_SIZE); - attributes.push_back(settings.alpha_bits); - - attributes.push_back(GLX_DEPTH_SIZE); - attributes.push_back(settings.depth_bits); - - attributes.push_back(GLX_STENCIL_SIZE); - attributes.push_back(settings.stencil_bits); - - attributes.push_back(GLX_DOUBLEBUFFER); - attributes.push_back(settings.double_buffer ? True : False); - - attributes.push_back(GLX_DRAWABLE_TYPE); - attributes.push_back( - translate_drawable_type_settings(settings.drawable_t)); - - attributes.push_back(GLX_X_VISUAL_TYPE); - attributes.push_back(GLX_TRUE_COLOR); - - attributes.push_back(None); - - int num_fb_configs = 0; - - glx_library_extensions lib_ext = load_glx_library_extensions( - glXQueryExtensionsString(device->get_xcb_display(), device->get_xcb_screen())); - - GLXFBConfig *fb_configs = glXChooseFBConfig( - device->get_xcb_display(), device->get_xcb_screen(), &attributes[0], &num_fb_configs); - if (!fb_configs || num_fb_configs == 0) { - /// @todo log errors - return nullptr; - } - - if (lib_ext.glXCreateContextAttribsARB) { - ::GLXFBConfig fb_config = fb_configs[0]; - - ::GLXContext context; - - std::vector<int> glx_attribs; - glx_attribs.reserve(11); - - glx_attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); - glx_attribs.push_back(settings.gl_major); - glx_attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); - glx_attribs.push_back(settings.gl_minor); - glx_attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); - glx_attribs.push_back(settings.core_profile - ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB - : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); - glx_attribs.push_back(None); - - context = lib_ext.glXCreateContextAttribsARB( - device->get_xcb_display(), fb_config, NULL, True, &glx_attribs[0]); - ::XFree(fb_configs); - if (!context) { - return nullptr; - } - - int visual_id = 0; - glXGetFBConfigAttrib(device->get_xcb_display(), fb_config, GLX_VISUAL_ID, - &visual_id); - return heap<gpu_context<backend::gl_linux_xcb>>(lib_ext, std::move(device), visual_id, - context, fb_config); - } - - return nullptr; -} - -gpu_window<backend::gl_linux_xcb>::gpu_window(own<window<backend::linux_xcb>> win, gpu_context<backend::gl_linux_xcb> &ctx, - ::GLXWindow glx_win) - : window_{std::move(win)}, context_{&ctx}, glx_window_handle_{glx_win} {} - -gpu_window<backend::gl_linux_xcb>::~gpu_window() { - assert(context_->device_); - if (context_->device_) { - ::glXDestroyWindow(context_->device_->get_xcb_display(), glx_window_handle_); - } -} - -void gpu_window<backend::gl_linux_xcb>::bind() { - assert(window_ && context_->device_ && context_->device_->get_xcb_display()); - if (window_) { - if (context_->device_ && context_->device_->get_xcb_display()) { - ::glXMakeContextCurrent(context_->device_->get_xcb_display(), glx_window_handle_, - glx_window_handle_, context_->context_); - } - } -} - -void gpu_window<backend::gl_linux_xcb>::show() { - assert(window_); - if (window_) { - window_->show(); - } -} - -void gpu_window<backend::gl_linux_xcb>::hide() { - assert(window_); - if (window_) { - window_->hide(); - } -} - -void gpu_window<backend::gl_linux_xcb>::swap() { - assert(context_->device_); - assert(context_->device_->get_xcb_display()); - if (context_->device_ && context_->device_->get_xcb_display()) { - ::glXSwapBuffers(context_->device_->get_xcb_display(), glx_window_handle_); - } -} - -const video_mode &gpu_window<backend::gl_linux_xcb>::get_video_mode() const { - assert(window_); - return window_->get_video_mode(); -} - -const std::string_view gpu_window<backend::gl_linux_xcb>::get_title() const { - assert(window_); - if (window_) { - return window_->get_title(); - } - // Kinky - return "Bad window"; -} - -void gpu_window<backend::gl_linux_xcb>::resize(size_t height, size_t width) { - assert(window_); - if (window_) { - window_->resize(height, width); - } -} - -conveyor<data<schema::WindowEvents>> gpu_window<backend::gl_linux_xcb>::on_event() { - assert(window_); - return window_->on_event(); -} - -} -} diff --git a/c++/window-opengl/gl_xcb.h b/c++/window-opengl/gl_xcb.h deleted file mode 100644 index 0d84662..0000000 --- a/c++/window-opengl/gl_xcb.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include <forstio/window/xcb.h> - -#ifndef SAW_OGL -#error "OpenGL is not supported" -#endif - -#include "gl_backends.h" -#include "gl_context.h" -#include "gl_window.h" - -#include <GL/glx.h> - -namespace saw { -namespace gfx { - -struct glx_library_extensions { -public: - std::string_view raw_extension_string; - GLXContext (*glXCreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, Bool, const int*) = nullptr; -}; - -template<> -class gpu_context<backend::gl_linux_xcb> final { -private: - glx_library_extensions ext_lib_; - own<device<backend::linux_xcb>> device_; - int visual_id_; - GLXContext context_; - GLXFBConfig fb_config_; - - friend class gpu_window<backend::gl_linux_xcb>; -public: - gpu_context(const glx_library_extensions&, own<device<backend::linux_xcb>>, int, GLXContext, GLXFBConfig); - ~gpu_context(); - - own<gpu_window<backend::gl_linux_xcb>> create_window(const video_mode&, std::string_view); - - void flush(); -}; - -template<> -class gpu_window<backend::gl_linux_xcb> final { -private: - own<window<backend::linux_xcb>> window_; - gpu_context<backend::gl_linux_xcb>* context_; - - ::GLXWindow glx_window_handle_; -public: - gpu_window(own<window<backend::linux_xcb>> window, gpu_context<backend::gl_linux_xcb>& ctx, - ::GLXWindow); - ~gpu_window(); - - void bind(); - void swap(); - void show(); - void hide(); - - const video_mode& get_video_mode() const; - const std::string_view get_title() const; - - void resize(size_t height, size_t width); - - conveyor<data<schema::WindowEvents>> on_event(); -}; -} -} diff --git a/c++/window/.nix/derivation.nix b/c++/window/.nix/derivation.nix deleted file mode 100644 index 67a682c..0000000 --- a/c++/window/.nix/derivation.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ lib -, stdenv -, scons -, clang-tools -, version -, forstio -, xorg -}: - -let - -in stdenv.mkDerivation { - pname = "forstio-window"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.io - forstio.codec - xorg.libX11 - xorg.libxcb - ]; - - outputs = ["out" "dev"]; -} diff --git a/c++/window/SConscript b/c++/window/SConscript deleted file mode 100644 index bd830b9..0000000 --- a/c++/window/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -window_env = env.Clone(); - -window_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -window_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += window_env.sources; -env.headers += window_env.headers; - -## Shared lib -objects_shared = [] -window_env.add_source_files(objects_shared, window_env.sources, shared=True); -window_env.library_shared = window_env.SharedLibrary('#build/forstio-window', [objects_shared]); - -## Static lib -objects_static = [] -window_env.add_source_files(objects_static, window_env.sources, shared=False); -window_env.library_static = window_env.StaticLibrary('#build/forstio-window', [objects_static]); - -# Set Alias -env.Alias('library_window', [window_env.library_shared, window_env.library_static]); - -env.targets += ['library_window']; - -# Install -env.Install('$prefix/lib/', [window_env.library_shared, window_env.library_static]); -env.Install('$prefix/include/forstio/window/', [window_env.headers]); diff --git a/c++/window/SConstruct b/c++/window/SConstruct deleted file mode 100644 index 05fc016..0000000 --- a/c++/window/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX', 'SAW_UNIX_XCB'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-core', 'forstio-io', 'forstio-async', 'forstio-codec']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/c++/window/backends.h b/c++/window/backends.h deleted file mode 100644 index e129037..0000000 --- a/c++/window/backends.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace saw { -namespace gfx { -namespace backend { -struct linux_xcb {}; -struct wasm {}; -} -} -} diff --git a/c++/window/device.h b/c++/window/device.h deleted file mode 100644 index 7d3cdb1..0000000 --- a/c++/window/device.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "window.h" - -#include <forstio/async/async.h> -#include <forstio/core/common.h> -#include <forstio/codec/data.h> -#include <forstio/io/io.h> - -#include <string_view> -#include <variant> - -namespace saw { -namespace gfx { -template<typename T> -class device; -} -} diff --git a/c++/window/linux_xcb.h b/c++/window/linux_xcb.h deleted file mode 100644 index 65ff94d..0000000 --- a/c++/window/linux_xcb.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#ifdef SAW_UNIX_XCB -#include "xcb.h" -#endif diff --git a/c++/window/old.dummy b/c++/window/old.dummy deleted file mode 100644 index c762945..0000000 --- a/c++/window/old.dummy +++ /dev/null @@ -1,399 +0,0 @@ -#include <X11/Xlib-xcb.h> -#include <X11/Xlib.h> -#include <xcb/xcb.h> -#include <forstio/io/io.h> - -#include <map> -#include <vector> - -#include "device.h" - -namespace saw { -class xcb_window; -class xcb_device final : public device { -public: - ::Display *display; - int screen; - - xcb_connection_t *xcb_connection; - xcb_screen_t *xcb_screen; - - own<input_stream> async_notifier; - conveyor_sink async_conveyor; - - std::map<xcb_window_t, xcb_window *> windows; - - std::vector<xcb_generic_event_t *> pending_events; - -public: - xcb_device(::Display *display, int screen, xcb_connection_t *xcb_connection, - xcb_screen_t *xcb_screen, own<input_stream> &&an); - ~xcb_device(); - - void window_destroyed(xcb_window_t window_id); - void handle_events(); - - own<xcb_window> create_xcb_window(const video_mode &mode, - std::string_view title_view, - int visual_id); - own<window> create_window(const video_mode &video_mode, - std::string_view title_view) override; - - void flush() override; -}; - -own<xcb_device> create_xcb_device(io_provider &provider); - -class xcb_window final : public window { -public: - xcb_device &device_; - - xcb_window_t xcb_window_; - xcb_colormap_t xcb_colormap_; - - video_mode video_mode_; - std::string window_title_; - - own<conveyor_feeder<window::variant_event>> event_feeder = nullptr; - -public: - xcb_window(xcb_device &dev, xcb_window_t xcb_win, - xcb_colormap_t xcb_colormap_, const video_mode &video_mode_, - std::string_view title_view_); - ~xcb_window(); - - void show() override; - void hide() override; - - const video_mode &get_video_mode() const override; - const std::string_view title() const override; - - void resize(size_t width, size_t height) override; - - conveyor<window::variant_event> on_event() override; - - void resize_event(size_t x, size_t y, size_t width, size_t height); - void mouse_event(int16_t x, int16_t y, uint16_t state, bool pressed); - void mouse_move_event(int16_t x, int16_t y); - void keyboard_event(int16_t x, int16_t y, uint32_t keycode, bool pressed, - bool repeat); -}; - -xcb_device::xcb_device(::Display *display, int screen, - xcb_connection_t *xcb_connection, - xcb_screen_t *xcb_screen, own<input_stream> &&an) - : display{display}, screen{screen}, xcb_connection{xcb_connection}, - xcb_screen{xcb_screen}, async_notifier{std::move(an)}, - async_conveyor{async_notifier->read_ready() - .then([this]() { handle_events(); }) - .sink()} {} - -xcb_device::~xcb_device() { - if (display) { - xcb_flush(xcb_connection); - ::XCloseDisplay(display); - } -} - -void xcb_device::window_destroyed(xcb_window_t window_id) { - windows.erase(window_id); -} - -void xcb_device::handle_events() { - while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection)) { - pending_events.push_back(event); - } - for (size_t i = 0; i < pending_events.size(); ++i) { - xcb_generic_event_t *event = pending_events.at(i); - switch (event->response_type & ~0x80) { - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *motion = - reinterpret_cast<xcb_motion_notify_event_t *>(event); - auto find = windows.find(motion->event); - if (find != windows.end()) { - assert(find->second); - find->second->mouse_move_event(motion->event_x, - motion->event_y); - } - } break; - case XCB_EXPOSE: { - xcb_expose_event_t *expose = - reinterpret_cast<xcb_expose_event_t *>(event); - auto find = windows.find(expose->window); - if (find != windows.end()) { - assert(find->second); - find->second->resize_event(static_cast<size_t>(expose->x), - static_cast<size_t>(expose->y), - static_cast<size_t>(expose->width), - static_cast<size_t>(expose->height)); - } - } break; - case XCB_BUTTON_RELEASE: { - xcb_button_release_event_t *button = - reinterpret_cast<xcb_button_release_event_t *>(event); - auto find = windows.find(button->event); - if (find != windows.end()) { - assert(find->second); - find->second->mouse_event(button->event_x, button->event_y, - button->detail, false); - } - } break; - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *button = - reinterpret_cast<xcb_button_press_event_t *>(event); - auto find = windows.find(button->event); - if (find != windows.end()) { - assert(find->second); - find->second->mouse_event(button->event_x, button->event_y, - button->detail, true); - } - } break; - case XCB_KEY_RELEASE: { - xcb_key_release_event_t *key = - reinterpret_cast<xcb_key_release_event_t *>(event); - - bool repeat = false; - /* - * Peek into future events - */ - for (size_t j = i + 1; j < pending_events.size(); ++j) { - xcb_generic_event_t *f_ev = pending_events.at(j); - - if ((f_ev->response_type & ~0x80) == XCB_KEY_PRESS) { - xcb_key_press_event_t *f_key = - reinterpret_cast<xcb_key_press_event_t *>(f_ev); - - if (key->detail == f_key->detail && - key->event == f_key->event) { - auto iterator = pending_events.begin() + j; - assert(iterator != pending_events.end()); - free(*iterator); - pending_events.erase(iterator); - repeat = true; - break; - } - } - } - - auto find = windows.find(key->event); - if (find != windows.end()) { - assert(find->second); - find->second->keyboard_event(key->event_x, key->event_y, - key->detail, repeat, repeat); - } - } break; - case XCB_KEY_PRESS: { - xcb_key_press_event_t *key = - reinterpret_cast<xcb_key_press_event_t *>(event); - auto find = windows.find(key->event); - if (find != windows.end()) { - assert(find->second); - find->second->keyboard_event(key->event_x, key->event_y, - key->detail, true, false); - } - } break; - default: - break; - } - } - - for (xcb_generic_event_t *event : pending_events) { - free(event); - } - pending_events.clear(); -} - -own<xcb_window> xcb_device::create_xcb_window(const video_mode &video_mode, - std::string_view title_view, - int visual_id) { - assert(xcb_screen); - assert(xcb_connection); - - xcb_colormap_t xcb_colormap = xcb_generate_id(xcb_connection); - xcb_window_t xcb_window = xcb_generate_id(xcb_connection); - - xcb_create_colormap(xcb_connection, XCB_COLORMAP_ALLOC_NONE, xcb_colormap, - xcb_screen->root, visual_id); - - uint32_t eventmask = - XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | - XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_BUTTON_MOTION; - uint32_t valuelist[] = {eventmask, xcb_colormap, 0}; - uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; - - xcb_create_window(xcb_connection, XCB_COPY_FROM_PARENT, xcb_window, - xcb_screen->root, 0, 0, video_mode.width, - video_mode.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, - visual_id, valuemask, valuelist); - - xcb_change_property(xcb_connection, XCB_PROP_MODE_REPLACE, xcb_window, - XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, title_view.size(), - title_view.data()); - - xcb_flush(xcb_connection); - auto window = heap<class xcb_window>(*this, xcb_window, xcb_colormap, - video_mode, title_view); - windows[xcb_window] = window.get(); - - return window; -} - -own<window> xcb_device::create_window(const video_mode &video_mode, - std::string_view title_view) { - assert(xcb_screen); - return create_xcb_window(video_mode, title_view, xcb_screen->root_visual); -} - -void xcb_device::flush() { - assert(xcb_connection); - xcb_flush(xcb_connection); -} - -own<xcb_device> create_xcb_device(io_provider &provider) { - ::Display *display = ::XOpenDisplay(nullptr); - if (!display) { - /// @todo log errors - return nullptr; - } - - int screen = ::XDefaultScreen(display); - - xcb_connection_t *xcb_connection = ::XGetXCBConnection(display); - if (!xcb_connection) { - /// @todo log errors - ::XCloseDisplay(display); - return nullptr; - } - - int fd = xcb_get_file_descriptor(xcb_connection); - - own<input_stream> fd_wrapped = provider.wrap_input_fd(fd); - if (!fd_wrapped) { - ::XCloseDisplay(display); - return nullptr; - } - - ::XSetEventQueueOwner(display, XCBOwnsEventQueue); - - xcb_screen_iterator_t screen_iter = - xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)); - for (int screen_i = screen; screen_iter.rem && screen_i > 0; - --screen_i, xcb_screen_next(&screen_iter)) - ; - - xcb_screen_t *xcb_screen = screen_iter.data; - - return heap<xcb_device>(display, screen, xcb_connection, xcb_screen, - std::move(fd_wrapped)); -} - -own<device> createdevice(io_provider &provider) { - return create_xcb_device(provider); -} - -xcb_window::xcb_window(xcb_device &dev, xcb_window_t xcb_win, - xcb_colormap_t xcb_colmap, const video_mode &vid_mode, - std::string_view title_view_) - : device_{dev}, xcb_window_{xcb_win}, xcb_colormap_{xcb_colmap}, - video_mode_{vid_mode}, window_title_{title_view_} {} - -xcb_window::~xcb_window() { - device_.window_destroyed(xcb_window_); - xcb_destroy_window(device_.xcb_connection, xcb_window_); - device_.flush(); -} - -void xcb_window::show() { - assert(device_.xcb_connection); - xcb_map_window(device_.xcb_connection, xcb_window_); -} - -void xcb_window::hide() { - assert(device_.xcb_connection); - xcb_unmap_window(device_.xcb_connection, xcb_window_); -} - -const video_mode &xcb_window::get_video_mode() const { return video_mode_; } - -const std::string_view xcb_window::title() const { return window_title_; } - -void xcb_window::resize(size_t width, size_t height) { - const uint32_t values[2] = {static_cast<uint32_t>(width), - static_cast<uint32_t>(height)}; - - xcb_configure_window(device_.xcb_connection, xcb_window_, - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, - values); - video_mode_.width = width; - video_mode_.height = height; -} - -conveyor<window::variant_event> xcb_window::on_event() { - auto caf = new_conveyor_and_feeder<window::variant_event>(); - event_feeder = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void xcb_window::resize_event(size_t x, size_t y, size_t width, size_t height) { - (void)x; - (void)y; - /// @todo maybe include x and y? - video_mode_.width = width; - video_mode_.height = height; - - if (event_feeder) { - event_feeder->feed( - window::variant_event{window::event::resize{width, height}}); - } -} - -void xcb_window::mouse_event(int16_t x, int16_t y, uint16_t state, - bool pressed) { - if (x < 0 || y < 0) { - return; - } - uint32_t ux = static_cast<uint32_t>(x); - uint32_t uy = static_cast<uint32_t>(y); - if (ux >= video_mode_.width || uy >= video_mode_.height) { - return; - } - if (event_feeder) { - event_feeder->feed(window::variant_event{ - window::event::mouse{state, pressed, ux, uy}}); - } -} - -void xcb_window::mouse_move_event(int16_t x, int16_t y) { - if (x < 0 || y < 0) { - return; - } - uint32_t ux = static_cast<uint32_t>(x); - uint32_t uy = static_cast<uint32_t>(y); - if (ux >= video_mode_.width || uy >= video_mode_.height) { - return; - } - if (event_feeder) { - event_feeder->feed( - window::variant_event{window::event::mouse_move{ux, uy}}); - } -} - -void xcb_window::keyboard_event(int16_t x, int16_t y, uint32_t keycode, - bool pressed, bool repeat) { - if (x < 0 || y < 0) { - return; - } - uint32_t ux = static_cast<uint32_t>(x); - uint32_t uy = static_cast<uint32_t>(y); - if (ux >= video_mode_.width || uy >= video_mode_.height) { - return; - } - if (event_feeder) { - event_feeder->feed(window::variant_event{ - window::event::keyboard{keycode, keycode, pressed, repeat}}); - } -} - -} // namespace saw diff --git a/c++/window/video_mode.h b/c++/window/video_mode.h deleted file mode 100644 index a8f1695..0000000 --- a/c++/window/video_mode.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include <cstddef> - -namespace saw { -class video_mode { -public: - size_t width = 64; - size_t height = 64; -}; -} // namespace saw diff --git a/c++/window/window.h b/c++/window/window.h deleted file mode 100644 index 36786de..0000000 --- a/c++/window/window.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "video_mode.h" - -#include <forstio/async/async.h> -#include <forstio/core/common.h> -#include <forstio/codec/schema.h> - -#include <string_view> -#include <variant> - -namespace saw { -namespace gfx { -namespace schema { -using namespace saw::schema; -using WindowResize = Struct< - Member<UInt32, "width">, - Member<UInt32, "height"> ->; -using WindowEvents = Union< - Member<WindowResize, "resize"> ->; -} - -template<typename T> -class window; -} -} - -#include "linux_xcb.h" - -/** -namespace saw { -class window { -public: - class event { - public: - struct resize { - size_t width; - size_t height; - }; - - struct keyboard { - uint32_t key; - uint32_t scan; - bool pressed; - bool repeat; - }; - - struct mouse { - uint16_t button_mask; - bool pressed; - uint32_t x; - uint32_t y; - }; - - struct mouse_move { - uint32_t x; - uint32_t y; - }; - }; - - using variant_event = std::variant<event::resize, event::keyboard, - event::mouse, event::mouse_move>; - - virtual ~window() = default; - - virtual void show() = 0; - virtual void hide() = 0; - - virtual const video_mode &get_video_mode() const = 0; - virtual const std::string_view title() const = 0; - - virtual void resize(size_t width, size_t height) = 0; - - virtual conveyor<variant_event> on_event() = 0; -}; -} // namespace saw -*/ diff --git a/c++/window/xcb.cpp b/c++/window/xcb.cpp deleted file mode 100644 index 1b804ba..0000000 --- a/c++/window/xcb.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef SAW_UNIX_XCB -#error "XCB is not supported" -#endif - -#include "xcb.h" - -namespace saw { -namespace gfx { -device<backend::linux_xcb>::device(::Display* disp, int screen, xcb_connection_t *xcb_connection, xcb_screen_t *xcb_screen, own<input_stream>&& an): - display_{disp}, screen_{screen}, xcb_connection_{xcb_connection}, xcb_screen_{xcb_screen}, async_notifier_{std::move(an)}, - async_conveyor_{async_notifier_->read_ready() - .then([this]() { handle_events(); }) - .sink()} {} - -device<backend::linux_xcb>::~device(){ - if (display_) { - xcb_flush(xcb_connection_); - ::XCloseDisplay(display_); - } -} - -void device<backend::linux_xcb>::xcb_window_was_destroyed(xcb_window_t window_id){ - windows_.erase(window_id); -} - -void device<backend::linux_xcb>::handle_events(){ - while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection_)) { - pending_events_.push_back(event); - } - for (size_t i = 0; i < pending_events_.size(); ++i) { - xcb_generic_event_t *event = pending_events_.at(i); - switch (event->response_type & ~0x80) { - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *motion = - reinterpret_cast<xcb_motion_notify_event_t *>(event); - auto find = windows_.find(motion->event); - if (find != windows_.end()) { - assert(find->second); - find->second->mouse_move_event(motion->event_x, - motion->event_y); - } - } break; - case XCB_EXPOSE: { - xcb_expose_event_t *expose = - reinterpret_cast<xcb_expose_event_t *>(event); - auto find = windows_.find(expose->window); - if (find != windows_.end()) { - assert(find->second); - find->second->resize_event(static_cast<size_t>(expose->x), - static_cast<size_t>(expose->y), - static_cast<size_t>(expose->width), - static_cast<size_t>(expose->height)); - } - } break; - case XCB_BUTTON_RELEASE: { - xcb_button_release_event_t *button = - reinterpret_cast<xcb_button_release_event_t *>(event); - auto find = windows_.find(button->event); - if (find != windows_.end()) { - assert(find->second); - find->second->mouse_event(button->event_x, button->event_y, - button->detail, false); - } - } break; - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *button = - reinterpret_cast<xcb_button_press_event_t *>(event); - auto find = windows_.find(button->event); - if (find != windows_.end()) { - assert(find->second); - find->second->mouse_event(button->event_x, button->event_y, - button->detail, true); - } - } break; - case XCB_KEY_RELEASE: { - xcb_key_release_event_t *key = - reinterpret_cast<xcb_key_release_event_t *>(event); - - bool repeat = false; - /* - * Peek into future events - */ - for (size_t j = i + 1; j < pending_events_.size(); ++j) { - xcb_generic_event_t *f_ev = pending_events_.at(j); - - if ((f_ev->response_type & ~0x80) == XCB_KEY_PRESS) { - xcb_key_press_event_t *f_key = - reinterpret_cast<xcb_key_press_event_t *>(f_ev); - - if (key->detail == f_key->detail && - key->event == f_key->event) { - auto iterator = pending_events_.begin() + j; - assert(iterator != pending_events_.end()); - free(*iterator); - pending_events_.erase(iterator); - repeat = true; - break; - } - } - } - - auto find = windows_.find(key->event); - if (find != windows_.end()) { - assert(find->second); - find->second->keyboard_event(key->event_x, key->event_y, - key->detail, repeat, repeat); - } - } break; - case XCB_KEY_PRESS: { - xcb_key_press_event_t *key = - reinterpret_cast<xcb_key_press_event_t *>(event); - auto find = windows_.find(key->event); - if (find != windows_.end()) { - assert(find->second); - find->second->keyboard_event(key->event_x, key->event_y, - key->detail, true, false); - } - } break; - default: - break; - } - } - - for (xcb_generic_event_t *event : pending_events_) { - free(event); - } - pending_events_.clear(); -} - -own<window<backend::linux_xcb>> device<backend::linux_xcb>::create_xcb_window(const video_mode &vid_mode, - std::string_view title_view, - int visual_id) { - assert(xcb_screen_); - assert(xcb_connection_); - - xcb_colormap_t xcb_colormap = xcb_generate_id(xcb_connection_); - xcb_window_t xcb_window = xcb_generate_id(xcb_connection_); - - xcb_create_colormap(xcb_connection_, XCB_COLORMAP_ALLOC_NONE, xcb_colormap, - xcb_screen_->root, visual_id); - - uint32_t eventmask = - XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | - XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_BUTTON_MOTION; - uint32_t valuelist[] = {eventmask, xcb_colormap, 0}; - uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; - - xcb_create_window(xcb_connection_, XCB_COPY_FROM_PARENT, xcb_window, - xcb_screen_->root, 0, 0, vid_mode.width, - vid_mode.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, - visual_id, valuemask, valuelist); - - xcb_change_property(xcb_connection_, XCB_PROP_MODE_REPLACE, xcb_window, - XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, title_view.size(), - title_view.data()); - - xcb_flush(xcb_connection_); - auto win = heap<window<backend::linux_xcb>>(*this, xcb_window, xcb_colormap, - vid_mode, title_view); - // Insert into map - windows_[xcb_window] = win.get(); - - return win; -} - -own<window<backend::linux_xcb>> device<backend::linux_xcb>::create_window(const video_mode& vid_mode, std::string_view title_view){ - assert(xcb_screen_); - return create_xcb_window(vid_mode, title_view, xcb_screen_->root_visual); -} - -void device<backend::linux_xcb>::flush(){ - assert(xcb_connection_); - xcb_flush(xcb_connection_); -} - -error_or<own<device<backend::linux_xcb>>> create_xcb_device(io_provider& provider){ - ::Display *display = ::XOpenDisplay(nullptr); - if (!display) { - /// @todo log errors - return make_error<err::critical>(); - } - - int screen = ::XDefaultScreen(display); - - xcb_connection_t *xcb_connection = ::XGetXCBConnection(display); - if (!xcb_connection) { - /// @todo log errors - ::XCloseDisplay(display); - return make_error<err::critical>(); - } - - int fd = xcb_get_file_descriptor(xcb_connection); - - own<input_stream> fd_wrapped = provider.wrap_input_fd(fd); - if (!fd_wrapped) { - ::XCloseDisplay(display); - return make_error<err::critical>(); - } - - ::XSetEventQueueOwner(display, XCBOwnsEventQueue); - - xcb_screen_iterator_t screen_iter = - xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)); - for (int screen_i = screen; screen_iter.rem && screen_i > 0; - --screen_i, xcb_screen_next(&screen_iter)) - ; - - xcb_screen_t *xcb_screen = screen_iter.data; - - return heap<device<backend::linux_xcb>>(display, screen, xcb_connection, xcb_screen, std::move(fd_wrapped)); -} - -window<backend::linux_xcb>::window(device<backend::linux_xcb>& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, const std::string_view& title_view_): - device_{&dev_}, - xcb_window_{xcb_win}, - xcb_colormap_{xcb_colormap_}, - video_mode_{vid_mode_}, - window_title_{title_view_} -{} - -window<backend::linux_xcb>::~window(){ - assert(device_); - device_->xcb_window_was_destroyed(xcb_window_); - xcb_destroy_window(device_->xcb_connection_, xcb_window_); - device_->flush(); -} - -void window<backend::linux_xcb>::show(){ - assert(device_->xcb_connection_); - xcb_map_window(device_->xcb_connection_, xcb_window_); -} - -void window<backend::linux_xcb>::hide(){ - assert(device_->xcb_connection_); - xcb_unmap_window(device_->xcb_connection_, xcb_window_); -} - -const video_mode& window<backend::linux_xcb>::get_video_mode() const { - return video_mode_; -} - -const std::string_view window<backend::linux_xcb>::get_title() const { - return window_title_; -} - -void window<backend::linux_xcb>::resize(uint64_t w, uint64_t h){ - const uint32_t values[2] = { - static_cast<uint32_t>(w), - static_cast<uint32_t>(h) - }; - - xcb_configure_window(device_->xcb_connection_, xcb_window_, - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, - values); - - video_mode_.width = w; - video_mode_.height = h; -} - -conveyor<data<schema::WindowEvents>> window<backend::linux_xcb>::on_event() { - auto caf = new_conveyor_and_feeder<data<schema::WindowEvents>>(); - event_feeder = std::move(caf.feeder); - return std::move(caf.conveyor); -} - -void window<backend::linux_xcb>::resize_event(uint64_t x, uint64_t y, uint64_t width, uint64_t height){ - /// @todo implement - assert(false); -} -void window<backend::linux_xcb>::mouse_event(int16_t x, int16_t y, uint16_t state, bool pressed){ - /// @todo implement - assert(false); -} -void window<backend::linux_xcb>::mouse_move_event(int16_t x, int16_t y){ - /// @todo implement - assert(false); -} -void window<backend::linux_xcb>::keyboard_event(int16_t x, int16_t y, uint32_t keycode, bool pressed, bool repeat){ - /// @todo implement - assert(false); -} - -xcb_window_t window<backend::linux_xcb>::get_xcb_window_handle() const{ - return xcb_window_; -} - -} -} diff --git a/c++/window/xcb.h b/c++/window/xcb.h deleted file mode 100644 index a2a9b0b..0000000 --- a/c++/window/xcb.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#ifndef SAW_UNIX_XCB -#error "XCB is not supported" -#endif - -#include "backends.h" -#include "device.h" -#include "window.h" - -#include <map> - -#include <X11/Xlib-xcb.h> -#include <X11/Xlib.h> - -namespace saw { -namespace gfx { -template<typename T> -class window; - -template<typename T> -class device; - -template<> -class device<backend::linux_xcb> final { -private: - ::Display *display_; - int screen_; - - xcb_connection_t *xcb_connection_; - xcb_screen_t *xcb_screen_; - - own<input_stream> async_notifier_; - conveyor_sink async_conveyor_; - - std::map<xcb_window_t, window<backend::linux_xcb> *> windows_; - - std::vector<xcb_generic_event_t *> pending_events_; - - friend class window<backend::linux_xcb>; -public: - own<window<backend::linux_xcb>> create_xcb_window(const video_mode& vid_mod, std::string_view title_view, int visual_id); - void xcb_window_was_destroyed(xcb_window_t window_id); -public: - device(::Display *display, int screen, xcb_connection_t *xcb_connection, - xcb_screen_t *xcb_screen, own<input_stream> && an); - - ~device(); - - void handle_events(); - - own<window<backend::linux_xcb>> create_window(const video_mode& vid_mod, std::string_view title_view); - - void flush(); - - // XCB specific info for other classes - ::Display* get_xcb_display() { - return display_; - } - - int get_xcb_screen() const { - return screen_; - } -}; - -error_or<own<device<backend::linux_xcb>>> create_xcb_device(io_provider& provider); - -template<> -class window<backend::linux_xcb> final { -private: - device<backend::linux_xcb> *device_; - - xcb_window_t xcb_window_; - xcb_colormap_t xcb_colormap_; - - video_mode video_mode_; - std::string window_title_; - - own<conveyor_feeder<data<schema::WindowEvents>>> event_feeder = nullptr; -public: - window(device<backend::linux_xcb>& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, const std::string_view& title_view_); - - ~window(); - - void show(); - void hide(); - - const video_mode& get_video_mode() const; - - const std::string_view get_title() const; - - void resize(uint64_t width, uint64_t height); - - conveyor<data<schema::WindowEvents>> on_event(); - - void resize_event(uint64_t x, uint64_t y, uint64_t width, uint64_t height); - void mouse_event(int16_t x, int16_t y, uint16_t state, bool pressed); - void mouse_move_event(int16_t x, int16_t y); - void keyboard_event(int16_t x, int16_t y, uint32_t keycode, bool pressed, bool repeat); - - // XCB specific things - xcb_window_t get_xcb_window_handle() const; -}; -} -} |