Stared reimplementing iohelper using concepts
This commit is contained in:
commit
62343d06e0
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
### Git ###
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### premake-gmake ###
|
||||||
|
Makefile
|
||||||
|
*.make
|
||||||
|
build/
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-v][a-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
# session
|
||||||
|
Session.vim
|
||||||
|
# temporary
|
||||||
|
.netrwhist
|
||||||
|
# auto-generated tag files
|
||||||
|
tags
|
||||||
|
.clangd/
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
### Other stuff ###
|
||||||
|
.build
|
||||||
|
bootstrap/build/
|
||||||
|
bootstrap/vendor/
|
105
src/write.cpp
Normal file
105
src/write.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user