1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
#ifndef IO_UTILS_HPP
#define IO_UTILS_HPP
#include "utils.hpp"
#include <fstream>
#include <ostream>
#include <terraces/errors.hpp>
namespace terraces {
namespace utils {
template <typename T>
struct comma_separated_output {
const T* data;
};
template <typename T>
std::ostream& operator<<(std::ostream& stream, comma_separated_output<T> output) {
bool first = true;
for (auto el : *output.data) {
if (not first) {
stream << ",";
}
stream << el;
first = false;
}
return stream;
}
template <typename T1, typename T2>
struct comma_separated_mapped_output {
const T1* data;
const T2* names;
};
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& stream, comma_separated_mapped_output<T1, T2> output) {
bool first = true;
for (auto el : *output.data) {
if (not first) {
stream << ",";
}
stream << (*output.names)[el];
first = false;
}
return stream;
}
template <typename T1, typename T2, typename T3>
struct comma_separated_mapped_subset_output {
const T1* subset;
const T2* data;
const T3* names;
};
template <typename T2, typename T3>
struct named_output {
const typename T2::value_type entry;
const T3* names;
};
template <typename T1, typename T2, typename T3>
std::ostream& operator<<(std::ostream& stream,
comma_separated_mapped_subset_output<T1, T2, T3> output) {
bool first = true;
for (auto el : *output.subset) {
if (not first) {
stream << ",";
}
stream << named_output<T2, T3>{(*output.data)[el], output.names};
first = false;
}
return stream;
}
// helpers because c++14 can't deduce class template types
template <typename T>
comma_separated_output<T> as_comma_separated_output(const T& data) {
return {&data};
}
template <typename T1, typename T2>
comma_separated_mapped_output<T1, T2> as_comma_separated_output(const T1& data, const T2& names) {
return {&data, &names};
}
template <typename T1, typename T2, typename T3>
comma_separated_mapped_subset_output<T1, T2, T3>
as_comma_separated_output(const T1& subset, const T2& data, const T3& names) {
return {&subset, &data, &names};
}
inline std::ifstream open_ifstream(const std::string& filename) {
auto stream = std::ifstream{filename};
utils::ensure<file_open_error>(stream.is_open(), "failed to open " + filename);
return stream;
}
inline std::string read_ifstream_full(std::istream& stream) {
using it = std::istreambuf_iterator<char>;
return {it{stream}, it{}};
}
inline std::string read_file_full(const std::string& filename) {
auto file = open_ifstream(filename);
return read_ifstream_full(file);
}
} // namespace utils
} // namespace terraces
#endif // IO_UTILS_HPP
|