Moved write to header, added read, seperated test and started using flint
This commit is contained in:
106
src/write.cpp
106
src/write.cpp
@@ -1,105 +1,3 @@
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include "io/write.h"
|
||||
|
||||
namespace io {
|
||||
template <typename T>
|
||||
void write(std::ostream&, T) {
|
||||
static_assert(!std::is_same_v<T,T>, "No known specialization of io::write for type");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
concept NumberByte = std::is_integral_v<T> && sizeof(T) == 1;
|
||||
|
||||
template <NumberByte T>
|
||||
void write(std::ostream& os, T value) {
|
||||
os.write(reinterpret_cast<const char*>(&value), sizeof(T));
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
void write_bytes(std::ostream& os, T value, size_t length) {
|
||||
for (auto i = length; i > 0; --i) {
|
||||
uint8_t byte = (value >> (i-1)*8) & 0xFF;
|
||||
write<uint8_t>(os, byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> requires std::is_integral_v<T>
|
||||
void write(std::ostream& os, T value) {
|
||||
write_bytes(os, value, sizeof(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);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> requires std::is_convertible_v<T, std::string_view>
|
||||
void write(std::ostream& os, T value) {
|
||||
std::string_view s = value;
|
||||
write<size_t>(os, s.length());
|
||||
os << s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
concept Container = requires (T a) {
|
||||
typename T::value_type;
|
||||
typename T::size_type;
|
||||
typename T::iterator;
|
||||
typename T::const_iterator;
|
||||
a.size();
|
||||
a.begin();
|
||||
a.end();
|
||||
a.cbegin();
|
||||
a.cend();
|
||||
} && !std::is_convertible_v<T, std::string_view>;
|
||||
|
||||
template <Container T>
|
||||
void write(std::ostream& os, T value) {
|
||||
write<size_t>(os, value.size());
|
||||
for (const auto& entry : value) {
|
||||
write<typename T::value_type>(os, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
struct A {
|
||||
int b;
|
||||
};
|
||||
|
||||
namespace io {
|
||||
template <>
|
||||
void write(std::ostream& os, A value) {
|
||||
write(os, value.b);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "TEST\n";
|
||||
io::write<size_t>(std::cout, 50);
|
||||
|
||||
std::array<char, 2> a = {'a', 'b'};
|
||||
io::write(std::cout, a);
|
||||
io::write(std::cout, "test");
|
||||
io::write(std::cout, A{4});
|
||||
std::cout << '\n';
|
||||
}
|
||||
// We do not implement anything without templates
|
||||
|
||||
Reference in New Issue
Block a user