diff options
| author | hovertank3d <[email protected]> | 2025-11-14 20:05:59 +0100 |
|---|---|---|
| committer | hovertank3d <[email protected]> | 2025-11-15 14:03:07 +0100 |
| commit | fa318825ef0404816728f733484caa1bc23afa53 (patch) | |
| tree | 154d51e23f907102cbb8367b8cdc4d3bb4153dc1 /include/util | |
| parent | 6c1a6c62bb13d09a0beb51ebb5cd5e4a69d9fe5a (diff) | |
| download | ogurec-fa318825ef0404816728f733484caa1bc23afa53.tar.gz ogurec-fa318825ef0404816728f733484caa1bc23afa53.zip | |
george droid
Diffstat (limited to 'include/util')
| -rw-r--r-- | include/util/bitset.hpp | 45 | ||||
| -rw-r--r-- | include/util/io.hpp | 202 |
2 files changed, 247 insertions, 0 deletions
diff --git a/include/util/bitset.hpp b/include/util/bitset.hpp index de5bd49..cd1dbd0 100644 --- a/include/util/bitset.hpp +++ b/include/util/bitset.hpp @@ -3,6 +3,7 @@ #include <array> #include <cassert> #include <cstdint> +#include <vector> constexpr int bits_ceil(int bits) { @@ -50,4 +51,48 @@ public: assert(i < flags); return bit_ref(*this, i / 8, (1 << (i % 8))); } +}; + +// FIXME: ?? +template <> +struct bitset<0> : std::vector<std::uint8_t> { + using container_type = std::vector<std::uint8_t>; + +private: + struct bit_ref { + bitset<0>& a; + int referenced_byte; + uint8_t referenced_bit_mask; + + bool operator=(bool b) + { + if (b) + a.at(referenced_byte) |= referenced_bit_mask; + else + a.at(referenced_byte) &= ~referenced_bit_mask; + return b; + } + + constexpr operator bool() const + { + return (a.at(referenced_byte) & referenced_bit_mask) > 0; + } + }; + +public: + template <class T> + constexpr bool operator[](T idx) const + { + unsigned int i = (unsigned int)(idx); + assert(i < container_type::size()); + return (container_type::at(i / 8) & (1 << (i % 8))) > 0; + } + + template <class T> + bit_ref operator[](T idx) + { + unsigned int i = (unsigned int)(idx); + assert(i < container_type::size()); + return bit_ref(*this, i / 8, (1 << (i % 8))); + } };
\ No newline at end of file diff --git a/include/util/io.hpp b/include/util/io.hpp new file mode 100644 index 0000000..8cfaf4c --- /dev/null +++ b/include/util/io.hpp @@ -0,0 +1,202 @@ +#pragma once + +#include "util/endian.hpp" +#include <boost/pfr/core.hpp> +#include <cassert> +#include <concepts> +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstring> +#include <fcntl.h> +#include <stdexcept> +#include <string> +#include <unistd.h> + +namespace io { + +template <class T, class K> +concept custom_write = requires(T t) { + { t.write(K()) } -> std::same_as<ssize_t>; +}; +template <class T, class K> +concept custom_read = requires(T& t, K& k) { + { t.read(k) } -> std::same_as<ssize_t>; +}; + +template <class T> +concept container = requires(T& t) { + { t.data() }; + { t.size() }; + { t.begin() }; + { t.end() }; +}; + +class file_io { + int fd; + +public: + file_io(int fd) + : fd(fd) + { + } + + file_io(std::string filename) + : fd(open(filename.c_str(), O_RDWR)) + { + if (fd < 0) + throw std::runtime_error(strerror(errno)); + } + + //~file_io() + //{ + // ::close(fd); + //} + + ssize_t read_data(char* buf, size_t nbytes) + { + auto bytes = ::read(fd, buf, nbytes); + assert(bytes >= 0); + return bytes; + } + + ssize_t write_data(const char* buf, size_t nbytes) + { + auto bytes = ::write(fd, buf, nbytes); + assert(bytes >= 0); + return bytes; + } +}; + +template <container T> +class buffered_io { + size_t cursor = 0; + T& buffer; + +public: + buffered_io(T& buffer) + : buffer(buffer) + { + } + + ssize_t read_data(char* buf, size_t nbytes) + { + auto bytes = nbytes > (buffer.size() - cursor) ? (buffer.size() - cursor) : nbytes; + + memcpy(buf, buffer.data() + cursor, bytes); + cursor += bytes; + return bytes; + } + + ssize_t write_data(const char* buf, size_t nbytes) + { + buffer.insert(buffer.end(), buf, buf + nbytes); + return nbytes; + } +}; + +template <class I> +class serialized_io { + I io; + +public: + serialized_io(I io) + : io(io) + { + } + + template <std::integral T> + ssize_t read(T& f) + { + auto bytes = io.read_data(reinterpret_cast<char*>(&f), sizeof(T)); + f = to_little(f); + return bytes; + } + + template <std::floating_point T> + ssize_t read(T& f) + { + auto bytes = io.read_data(reinterpret_cast<char*>(&f), sizeof(T)); + f = to_little(f); + return bytes; + } + + ssize_t read(std::string& f) + { + // FIXME: varint + uint8_t size; + auto bytes = read(size); + + f.resize(size); + bytes += io.read_data(f.data(), size); + return bytes; + } + + template <custom_read<serialized_io<I>> T> + ssize_t read(T& f) + { + return f.read(*this); + } + + template <container T> + ssize_t read(T& f) + { + return io.read_data(reinterpret_cast<char*>(f.data()), f.size() * sizeof(typename T::value_type)); + } + + template <class T> + ssize_t read(T& f) + { + ssize_t bytes = 0; + boost::pfr::for_each_field(f, [this, &bytes](auto& field) { + bytes += read(field); + }); + return bytes; + } + + template <std::integral T> + ssize_t write(const T f) + { + auto x = to_little(f); + return io.write_data(reinterpret_cast<char*>(&x), sizeof(T)); + } + + template <std::floating_point T> + ssize_t write(const T f) + { + // FIXME: endianness + return io.write_data(reinterpret_cast<char*>(&f), sizeof(T)); + } + + ssize_t write(const std::string f) + { + // FIXME: varint + auto bytes = write(f.size()); + bytes += io.write_data(f.data(), f.size()); + return bytes; + } + + template <container T> + ssize_t write(const T f) + { + return io.write_data(reinterpret_cast<const char*>(f.data()), f.size() * sizeof(typename T::value_type)); + } + + template <custom_write<serialized_io<I>> T> + ssize_t write(T& f) + { + return f.write(*this); + } + + template <class T> + ssize_t write(const T f) + { + ssize_t bytes = 0; + boost::pfr::for_each_field(f, [this, &bytes](auto field) { + bytes += write(field); + }); + return bytes; + } +}; + +}
\ No newline at end of file |
