#include "io.h" #include "test_framework.h" #include #include #include #include #include struct A { int b; bool operator==(const A& other) { return b == other.b; } }; namespace io { template <> void write(std::ostream& os, A value) { write(os, value.b); } template <> A read(std::istream& is) { return A{read(is)}; } } int main() { Test("Write for bool false", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, false); bool succes = 1 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x00; return succes; }()); Test("Read for bool false", [] { std::ifstream f("test.bin"); return io::read(f) == false; }()); Test("Write for bool true", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, true); bool succes = 1 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x01; return succes; }()); Test("Read for bool true", [] { std::ifstream f("test.bin"); return io::read(f) == true; }()); Test("Write for int", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 80085); bool succes = 4 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x00; f.read(&c,1); succes &= (c & 0xff) == 0x01; f.read(&c,1); succes &= (c & 0xff) == 0x38; f.read(&c,1); succes &= (c & 0xff) == 0xd5; return succes; }()); Test("Read for int", [] { std::ifstream f("test.bin"); return io::read(f) == 80085; }()); Test("Write for float", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 123.654f); bool succes = 4 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x42; f.read(&c,1); succes &= (c & 0xff) == 0xf7; f.read(&c,1); succes &= (c & 0xff) == 0x4e; f.read(&c,1); succes &= (c & 0xff) == 0xd9; return succes; }()); Test("Read for float", [] { std::ifstream f("test.bin"); return io::read(f) == 123.654f; }()); Test("Write for short size_t", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 12); bool succes = 1 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x0C; return succes; }()); Test("Read for short size_t", [] { std::ifstream f("test.bin"); return io::read(f) == 12; }()); Test("Write for border size_t", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 0b10000000); bool succes = 2 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0b10000001; f.read(&c,1); succes &= (c & 0xff) == 0b10000000; return succes; }()); Test("Read for border size_t", [] { std::ifstream f("test.bin"); return io::read(f) == 0b10000000; }()); Test("Write for medium size_t", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 123456); bool succes = 4 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 3); f.read(&c,1); succes &= (c & 0xff) == 0x01; f.read(&c,1); succes &= (c & 0xff) == 0xe2; f.read(&c,1); succes &= (c & 0xff) == 0x40; return succes; }()); Test("Read for medium size_t", [] { std::ifstream f("test.bin"); return io::read(f) == 123456; }()); Test("Write for long size_t", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, std::numeric_limits::max()); bool succes = 9 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 8); f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; f.read(&c,1); succes &= (c & 0xff) == 0xff; return succes; }()); Test("Read for long size_t", [] { std::ifstream f("test.bin"); return io::read(f) == std::numeric_limits::max(); }()); Test("Write for short std::string", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::string value = "test"; io::write(f, value); bool succes = 5 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 4; f.read(&c,1); succes &= (c & 0xff) == 't'; f.read(&c,1); succes &= (c & 0xff) == 'e'; f.read(&c,1); succes &= (c & 0xff) == 's'; f.read(&c,1); succes &= (c & 0xff) == 't'; return succes; }()); Test("Read for short std::string", [] { std::ifstream f("test.bin"); std::string value = "test"; return !value.compare(io::read(f)); }()); Test("Write for short std::string (no length)", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::string value = "test"; io::write(f, value, false); bool succes = 4 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 't'; f.read(&c,1); succes &= (c & 0xff) == 'e'; f.read(&c,1); succes &= (c & 0xff) == 's'; f.read(&c,1); succes &= (c & 0xff) == 't'; return succes; }()); Test("Read for short std::string (no length)", [] { std::ifstream f("test.bin"); std::string value = "test"; return !value.compare(io::read(f,4)); }()); // Test long string seperately since short strings might get optimized Test("Write for long std::string", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::string value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla rhoncus accumsan mauris, vitae mollis ipsum. Ut in ultrices enim. Aenean ac risus nec nulla porttitor egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer molestie tellus urna, sit amet scelerisque ligula porttitor et. Maecenas efficitur tortor vitae dui tincidunt, sit amet ultricies mi consectetur. Quisque eu pellentesque ex. Morbi nibh dolor, rutrum a tortor et, ornare tempor nisi. Nam ornare quam eget orci volutpat sagittis et eu risus. Cras dignissim felis eu libero interdum, a condimentum elit mollis. Quisque sagittis vel ante eget mattis. Quisque non nibh lectus."; io::write(f, value); bool succes = 667 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 2); f.read(&c,1); succes &= (c & 0xff) == 0x02; f.read(&c,1); succes &= (c & 0xff) == 0x98; for (size_t i = 0; i < 664; ++i) { f.read(&c,1); succes &= (c & 0xff) == value[i]; } return succes; }()); Test("Read for long std::string", [] { std::ifstream f("test.bin"); std::string value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla rhoncus accumsan mauris, vitae mollis ipsum. Ut in ultrices enim. Aenean ac risus nec nulla porttitor egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer molestie tellus urna, sit amet scelerisque ligula porttitor et. Maecenas efficitur tortor vitae dui tincidunt, sit amet ultricies mi consectetur. Quisque eu pellentesque ex. Morbi nibh dolor, rutrum a tortor et, ornare tempor nisi. Nam ornare quam eget orci volutpat sagittis et eu risus. Cras dignissim felis eu libero interdum, a condimentum elit mollis. Quisque sagittis vel ante eget mattis. Quisque non nibh lectus."; return !value.compare(io::read(f)); }()); // Only do one test with const char* as everything else should behave the same Test("Write for short const char*", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); const char* value = "test"; io::write(f, value); bool succes = 5 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 4; f.read(&c,1); succes &= (c & 0xff) == 't'; f.read(&c,1); succes &= (c & 0xff) == 'e'; f.read(&c,1); succes &= (c & 0xff) == 's'; f.read(&c,1); succes &= (c & 0xff) == 't'; return succes; }()); Test("Read for short const char* (as std::string)", [] { std::ifstream f("test.bin"); const char* value = "test"; return !io::read(f).compare(value); }()); Test("Write for std::array", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::array value = {'a', 'b'}; io::write>(f, value); bool succes = 2 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 'a'; f.read(&c,1); succes &= (c & 0xff) == 'b'; return succes; }()); Test("Read for std::array", [] { std::ifstream f("test.bin"); std::array value = io::read>(f); return value[0] == 'a' && value[1] == 'b'; }()); Test("Read for std::array (as std::vector)", [] { std::ifstream f("test.bin"); std::vector value = io::read>(f,2); return value.size() == 2 && value[0] == 'a' && value[1] == 'b'; }()); Test("Read for std::array (as std::list)", [] { std::ifstream f("test.bin"); std::list value = io::read>(f,2); return value.size() == 2 && value.front() == 'a' && value.back() == 'b'; }()); // Test("Read for std::array (as std::forward_list)", [] { // std::ifstream f("test.bin"); // std::forward_list value = io::read>(f,2); // return *(value.begin()) == 'a' && *(value.begin()++) == 'a'; // }()); 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); bool succes = 3 == 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) == 'd'; return succes; }()); Test("Read for std::array (as std::vector, length)", [] { std::ifstream f("test.bin"); std::vector value = io::read>(f); return value.size() == 2 && value[0] == 'c' && value[1] == 'd'; }()); Test("Write for std::vector", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::vector value = {'e', 'f'}; io::write>(f, value); bool succes = 3 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 2; f.read(&c,1); succes &= (c & 0xff) == 'e'; f.read(&c,1); succes &= (c & 0xff) == 'f'; return succes; }()); Test("Read for std::vector", [] { std::ifstream f("test.bin"); std::vector value = io::read>(f); return value.size() == 2 && value[0] == 'e' && value[1] == 'f'; }()); Test("Read for std::vector (as std::array)", [] { std::ifstream f("test.bin"); bool succes = io::read(f) == 2; std::array value = io::read>(f); return succes && value[0] == 'e' && value[1] == 'f'; }()); Test("Read for std::vector (as std::list)", [] { std::ifstream f("test.bin"); std::list value = io::read>(f); return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; }()); // Test("Read for std::vector (as std::forward_list)", [] { // std::ifstream f("test.bin"); // std::forward_list value = io::read>(f); // return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; // }()); Test("Write for std::vector (no length)", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::vector value = {'g', 'h'}; io::write>(f, value, false); bool succes = 2 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 'g'; f.read(&c,1); succes &= (c & 0xff) == 'h'; return succes; }()); Test("Read for std::vector (no length)", [] { std::ifstream f("test.bin"); std::vector value = io::read>(f, 2); return value.size() == 2 && value[0] == 'g' && value[1] == 'h'; }()); Test("Write for std::list", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); std::list value = {'i', 'j'}; io::write>(f, value); bool succes = 3 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 2; f.read(&c,1); succes &= (c & 0xff) == 'i'; f.read(&c,1); succes &= (c & 0xff) == 'j'; return succes; }()); Test("Read for std::list", [] { std::ifstream f("test.bin"); std::list value = io::read>(f); return value.size() == 2 && value.front() == 'i' && value.back() == 'j'; }()); Test("Read for std::list (as std::vector)", [] { std::ifstream f("test.bin"); std::vector value = io::read>(f); return value.size() == 2 && value[0] == 'i' && value[1] == 'j'; }()); Test("Read for std::list (as std::array)", [] { std::ifstream f("test.bin"); bool succes = io::read(f) == 2; std::array value = io::read>(f); return succes && value[0] == 'i' && value[1] == 'j'; }()); // Test("Read for std::vector (as std::forward_list)", [] { // std::ifstream f("test.bin"); // std::forward_list value = io::read>(f); // return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; // }()); Test("Write for custom struct", [] { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); A value = {5}; io::write(f, value); bool succes = 4 == f.tellg(); f.seekg(0); char c; f.read(&c,1); succes &= (c & 0xff) == 0x00; f.read(&c,1); succes &= (c & 0xff) == 0x00; f.read(&c,1); succes &= (c & 0xff) == 0x00; f.read(&c,1); succes &= (c & 0xff) == 0x05; return succes; }()); Test("Read for custom struct", [] { std::ifstream f("test.bin"); A value = io::read(f); return value == A{5}; }()); return !Test::evaluate(); }