From 072167ccf47c3070f588d32db5722740f4bcf294 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Tue, 30 Nov 2021 04:17:11 +0100 Subject: [PATCH] Fixed compile issues --- io/include/io/helper.h | 22 +++++++++++-- io/include/io/read.h | 9 ++---- io/include/io/write.h | 70 ++++++++++++++++++++++++++++++++---------- io/src/write.cpp | 30 ------------------ test/src/test.cpp | 10 +++--- 5 files changed, 81 insertions(+), 60 deletions(-) diff --git a/io/include/io/helper.h b/io/include/io/helper.h index 0b1c239..b094e9a 100644 --- a/io/include/io/helper.h +++ b/io/include/io/helper.h @@ -1,9 +1,12 @@ #pragma once #include +#include namespace io { template - concept NumberByte = std::is_integral_v && sizeof(T) == 1; + concept Array = requires (T a) { + std::tuple_size::value; + }; template concept Container = requires (T a) { @@ -16,5 +19,20 @@ namespace io { a.end(); a.cbegin(); a.cend(); - } && !std::is_convertible_v; + } && !std::is_convertible_v && !Array; + + template + concept Size = std::is_same_v; + + template + concept NumberByte = std::is_integral_v && sizeof(T) == 1; + + template + concept Number = (std::is_integral_v && !NumberByte) && !Size; + + template + concept Float = std::is_same_v; + + template + concept String = std::is_convertible_v; } diff --git a/io/include/io/read.h b/io/include/io/read.h index 32190d4..6f357b3 100644 --- a/io/include/io/read.h +++ b/io/include/io/read.h @@ -57,8 +57,6 @@ namespace io { return read(is, length); } - - template T read(std::istream& is, size_t length) { T v(length); @@ -74,12 +72,11 @@ namespace io { return read(is, length); } - // Static sized container - template requires requires (T a) { std::tuple_size::value; } + template T read(std::istream& is) { T v; - for (size_t i = 0; i < std::tuple_size::value; ++i) { - v[i] = io::read(is); + for (auto& e : v) { + e = io::read(is); } return v; } diff --git a/io/include/io/write.h b/io/include/io/write.h index 38a02db..05e7681 100644 --- a/io/include/io/write.h +++ b/io/include/io/write.h @@ -7,18 +7,23 @@ namespace io { // This exists to allow for specialization and clearer errors template - void write(std::ostream&, T) { + void write(std::ostream&, const T&) { + static_assert(!std::is_same_v, "No known specialization of io::write for type"); + } + + template + void write(std::ostream&, const T&, bool) { static_assert(!std::is_same_v, "No known specialization of io::write for type"); } template - void write(std::ostream& os, T value) { + void write(std::ostream& os, const T& value) { os.write(reinterpret_cast(&value), sizeof(T)); } namespace { template - void write_bytes(std::ostream& os, T value, size_t length) { + void write_bytes(std::ostream& os, const T& value, size_t length) { for (size_t i = length; i > 0; --i) { uint8_t byte = (value >> (i-1)*8) & 0xFF; write(os, byte); @@ -26,20 +31,44 @@ namespace io { } } - template requires (std::is_integral_v && !NumberByte) - void write(std::ostream& os, T value) { + template + void write(std::ostream& os, const T& value) { write_bytes(os, value, sizeof(T)); } - template <> - void write(std::ostream& os, float value); + template + void write(std::ostream& os, const float& value) { + union { + uint32_t a; + float b; + } u; + + u.b = value; + write_bytes(os, u.a, sizeof(uint32_t)); + } // Special implementation for size_t (also uint64_t, so maybe this is not that smart) - template <> - void write(std::ostream& os, size_t value); + template + void write(std::ostream& os, const size_t& value) { + // Check if we need more then one byte + if (value > 0b01111111) { + // Calculate how many bytes we need to store the number + uint8_t length = 0; + auto x = value; + while (x != 0) { + x >>= 8; + length++; + } - template requires std::is_convertible_v - void write(std::ostream& os, T value, bool store_length = true) { + write(os, length | 0b10000000); + write_bytes(os, value, length); + } else { + write(os, value); + } + } + + template + void write(std::ostream& os, const T& value, bool store_length) { std::string_view s = value; if (store_length) { write(os, s.length()); @@ -47,9 +76,14 @@ namespace io { os << s; } + template + void write(std::ostream& os, const T& value) { + write(os, value, true); + } + // @todo Merge this into one function with the proper default automatically template - void write(std::ostream& os, const T& value, bool store_length = true) { + void write(std::ostream& os, const T& value, bool store_length) { if (store_length) { write(os, value.size()); } @@ -58,11 +92,13 @@ namespace io { } } - template requires requires (T a) { std::tuple_size::value; } - void write(std::ostream& os, const T& value, bool store_length = false) { - if (store_length) { - write(os, value.size()); - } + template + void write(std::ostream& os, const T& value) { + write(os, value, true); + } + + template + void write(std::ostream& os, const T& value) { for (const auto& entry : value) { write(os, entry); } diff --git a/io/src/write.cpp b/io/src/write.cpp index 555fc8b..68af70b 100644 --- a/io/src/write.cpp +++ b/io/src/write.cpp @@ -1,34 +1,4 @@ #include "io/write.h" namespace io { - template<> - void write(std::ostream& os, float value) { - union { - uint32_t a; - float b; - } u; - - u.b = value; - write_bytes(os, u.a, sizeof(uint32_t)); - } - - // Special implementation for size_t (also uint64_t, so maybe this is not that smart) - template<> - void write(std::ostream& os, size_t value) { - // Check if we need more then one byte - if (value > 0b01111111) { - // Calculate how many bytes we need to store the number - uint8_t length = 0; - auto x = value; - while (x != 0) { - x >>= 8; - length++; - } - - write(os, length | 0b10000000); - write_bytes(os, value, length); - } else { - write(os, value); - } - } } diff --git a/test/src/test.cpp b/test/src/test.cpp index dce3c62..b121bdc 100644 --- a/test/src/test.cpp +++ b/test/src/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include struct A { int b; @@ -18,7 +19,7 @@ struct A { namespace io { template <> - void write(std::ostream& os, A value) { + void write(std::ostream& os, const A& value) { write(os, value.b); } @@ -280,10 +281,9 @@ int main() { Test("Write for std::array (length)", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::array value = {'c', 'd'}; - io::write>(f, value, true); + io::write>(f, value); - bool succes = 3 == f.tellg(); f.seekg(0); char c; - f.read(&c,1); succes &= (c & 0xff) == 2; + bool succes = 2 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 'c'; f.read(&c,1); succes &= (c & 0xff) == 'd'; return succes; @@ -291,7 +291,7 @@ int main() { Test("Read for std::array (as std::vector, length)", [] { std::ifstream f("test.bin"); - std::vector value = io::read>(f); + std::vector value = io::read>(f, 2); return value.size() == 2 && value[0] == 'c' && value[1] == 'd'; }());