diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-12-04 12:18:14 +0100 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-12-04 12:18:14 +0100 |
commit | a14896f9ed209dd3f9597722e5a5697bd7dbf531 (patch) | |
tree | 089ca5cbbd206d1921f8f6b53292f5bc1902ca5c /c++/core | |
parent | 84ecdcbca9e55b1f57fbb832e12ff4fdbb86e7c9 (diff) |
meta: Renamed folder containing source
Diffstat (limited to 'c++/core')
-rw-r--r-- | c++/core/.nix/derivation.nix | 21 | ||||
-rw-r--r-- | c++/core/SConscript | 38 | ||||
-rw-r--r-- | c++/core/SConstruct | 66 | ||||
-rw-r--r-- | c++/core/array.h | 96 | ||||
-rw-r--r-- | c++/core/buffer.cpp | 436 | ||||
-rw-r--r-- | c++/core/buffer.h | 199 | ||||
-rw-r--r-- | c++/core/common.h | 75 | ||||
-rw-r--r-- | c++/core/error.cpp | 156 | ||||
-rw-r--r-- | c++/core/error.h | 248 | ||||
-rw-r--r-- | c++/core/id.h | 54 | ||||
-rw-r--r-- | c++/core/id_map.h | 137 | ||||
-rw-r--r-- | c++/core/mcts.h | 52 | ||||
-rw-r--r-- | c++/core/platonic.h | 103 | ||||
-rw-r--r-- | c++/core/string_literal.h | 57 | ||||
-rw-r--r-- | c++/core/templates.h | 150 | ||||
-rw-r--r-- | c++/core/tree.h | 248 |
16 files changed, 0 insertions, 2136 deletions
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); - } -}; -} |