Fixed compile issues
This commit is contained in:
parent
96b6c7e764
commit
072167ccf4
|
@ -1,9 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace io {
|
namespace io {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept NumberByte = std::is_integral_v<T> && sizeof(T) == 1;
|
concept Array = requires (T a) {
|
||||||
|
std::tuple_size<T>::value;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept Container = requires (T a) {
|
concept Container = requires (T a) {
|
||||||
|
@ -16,5 +19,20 @@ namespace io {
|
||||||
a.end();
|
a.end();
|
||||||
a.cbegin();
|
a.cbegin();
|
||||||
a.cend();
|
a.cend();
|
||||||
} && !std::is_convertible_v<T, std::string_view>;
|
} && !std::is_convertible_v<T, std::string_view> && !Array<T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept Size = std::is_same_v<T, size_t>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept NumberByte = std::is_integral_v<T> && sizeof(T) == 1;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept Number = (std::is_integral_v<T> && !NumberByte<T>) && !Size<T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept Float = std::is_same_v<T, float>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept String = std::is_convertible_v<T, std::string_view>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,6 @@ namespace io {
|
||||||
return read<T>(is, length);
|
return read<T>(is, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <Container T>
|
template <Container T>
|
||||||
T read(std::istream& is, size_t length) {
|
T read(std::istream& is, size_t length) {
|
||||||
T v(length);
|
T v(length);
|
||||||
|
@ -74,12 +72,11 @@ namespace io {
|
||||||
return read<T>(is, length);
|
return read<T>(is, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static sized container
|
template <Array T>
|
||||||
template <Container T> requires requires (T a) { std::tuple_size<T>::value; }
|
|
||||||
T read(std::istream& is) {
|
T read(std::istream& is) {
|
||||||
T v;
|
T v;
|
||||||
for (size_t i = 0; i < std::tuple_size<T>::value; ++i) {
|
for (auto& e : v) {
|
||||||
v[i] = io::read<typename T::value_type>(is);
|
e = io::read<typename T::value_type>(is);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,23 @@
|
||||||
namespace io {
|
namespace io {
|
||||||
// This exists to allow for specialization and clearer errors
|
// This exists to allow for specialization and clearer errors
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void write(std::ostream&, T) {
|
void write(std::ostream&, const T&) {
|
||||||
|
static_assert(!std::is_same_v<T,T>, "No known specialization of io::write for type");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void write(std::ostream&, const T&, bool) {
|
||||||
static_assert(!std::is_same_v<T,T>, "No known specialization of io::write for type");
|
static_assert(!std::is_same_v<T,T>, "No known specialization of io::write for type");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <NumberByte T>
|
template <NumberByte T>
|
||||||
void write(std::ostream& os, T value) {
|
void write(std::ostream& os, const T& value) {
|
||||||
os.write(reinterpret_cast<const char*>(&value), sizeof(T));
|
os.write(reinterpret_cast<const char*>(&value), sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
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) {
|
for (size_t i = length; i > 0; --i) {
|
||||||
uint8_t byte = (value >> (i-1)*8) & 0xFF;
|
uint8_t byte = (value >> (i-1)*8) & 0xFF;
|
||||||
write<uint8_t>(os, byte);
|
write<uint8_t>(os, byte);
|
||||||
|
@ -26,20 +31,44 @@ namespace io {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> requires (std::is_integral_v<T> && !NumberByte<T>)
|
template <Number T>
|
||||||
void write(std::ostream& os, T value) {
|
void write(std::ostream& os, const T& value) {
|
||||||
write_bytes(os, value, sizeof(T));
|
write_bytes(os, value, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <Float T>
|
||||||
void write(std::ostream& os, float value);
|
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)
|
// Special implementation for size_t (also uint64_t, so maybe this is not that smart)
|
||||||
template <>
|
template <Size T>
|
||||||
void write(std::ostream& os, size_t value);
|
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 <typename T> requires std::is_convertible_v<T, std::string_view>
|
write<uint8_t>(os, length | 0b10000000);
|
||||||
void write(std::ostream& os, T value, bool store_length = true) {
|
write_bytes(os, value, length);
|
||||||
|
} else {
|
||||||
|
write<uint8_t>(os, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <String T>
|
||||||
|
void write(std::ostream& os, const T& value, bool store_length) {
|
||||||
std::string_view s = value;
|
std::string_view s = value;
|
||||||
if (store_length) {
|
if (store_length) {
|
||||||
write<size_t>(os, s.length());
|
write<size_t>(os, s.length());
|
||||||
|
@ -47,9 +76,14 @@ namespace io {
|
||||||
os << s;
|
os << s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <String T>
|
||||||
|
void write(std::ostream& os, const T& value) {
|
||||||
|
write(os, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
// @todo Merge this into one function with the proper default automatically
|
// @todo Merge this into one function with the proper default automatically
|
||||||
template <Container T>
|
template <Container T>
|
||||||
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) {
|
if (store_length) {
|
||||||
write<size_t>(os, value.size());
|
write<size_t>(os, value.size());
|
||||||
}
|
}
|
||||||
|
@ -58,11 +92,13 @@ namespace io {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Container T> requires requires (T a) { std::tuple_size<T>::value; }
|
template <Container T>
|
||||||
void write(std::ostream& os, const T& value, bool store_length = false) {
|
void write(std::ostream& os, const T& value) {
|
||||||
if (store_length) {
|
write(os, value, true);
|
||||||
write<size_t>(os, value.size());
|
}
|
||||||
}
|
|
||||||
|
template <Array T>
|
||||||
|
void write(std::ostream& os, const T& value) {
|
||||||
for (const auto& entry : value) {
|
for (const auto& entry : value) {
|
||||||
write<typename T::value_type>(os, entry);
|
write<typename T::value_type>(os, entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,4 @@
|
||||||
#include "io/write.h"
|
#include "io/write.h"
|
||||||
|
|
||||||
namespace io {
|
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<uint8_t>(os, length | 0b10000000);
|
|
||||||
write_bytes(os, value, length);
|
|
||||||
} else {
|
|
||||||
write<uint8_t>(os, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
struct A {
|
struct A {
|
||||||
int b;
|
int b;
|
||||||
|
@ -18,7 +19,7 @@ struct A {
|
||||||
|
|
||||||
namespace io {
|
namespace io {
|
||||||
template <>
|
template <>
|
||||||
void write(std::ostream& os, A value) {
|
void write(std::ostream& os, const A& value) {
|
||||||
write<int>(os, value.b);
|
write<int>(os, value.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,10 +281,9 @@ int main() {
|
||||||
Test("Write for std::array<char> (length)", [] {
|
Test("Write for std::array<char> (length)", [] {
|
||||||
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
|
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
|
||||||
std::array<char, 2> value = {'c', 'd'};
|
std::array<char, 2> value = {'c', 'd'};
|
||||||
io::write<std::array<char, 2>>(f, value, true);
|
io::write<std::array<char, 2>>(f, value);
|
||||||
|
|
||||||
bool succes = 3 == f.tellg(); f.seekg(0); char c;
|
bool succes = 2 == f.tellg(); f.seekg(0); char c;
|
||||||
f.read(&c,1); succes &= (c & 0xff) == 2;
|
|
||||||
f.read(&c,1); succes &= (c & 0xff) == 'c';
|
f.read(&c,1); succes &= (c & 0xff) == 'c';
|
||||||
f.read(&c,1); succes &= (c & 0xff) == 'd';
|
f.read(&c,1); succes &= (c & 0xff) == 'd';
|
||||||
return succes;
|
return succes;
|
||||||
|
@ -291,7 +291,7 @@ int main() {
|
||||||
|
|
||||||
Test("Read for std::array<char> (as std::vector<char>, length)", [] {
|
Test("Read for std::array<char> (as std::vector<char>, length)", [] {
|
||||||
std::ifstream f("test.bin");
|
std::ifstream f("test.bin");
|
||||||
std::vector<char> value = io::read<std::vector<char>>(f);
|
std::vector<char> value = io::read<std::vector<char>>(f, 2);
|
||||||
return value.size() == 2 && value[0] == 'c' && value[1] == 'd';
|
return value.size() == 2 && value[0] == 'c' && value[1] == 'd';
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user