alpaqa no-casadi-dep
Nonconvex constrained optimization
Loading...
Searching...
No Matches
csv.tpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cassert>
5#include <charconv>
6#include <ios>
7#include <iostream>
8
9#if !__cpp_lib_to_chars
10#include <cerrno>
11#include <cstdlib> // strtod
12#endif
13
14namespace alpaqa::csv {
15
16template <class F>
17 requires(std::floating_point<F> || std::integral<F>)
18struct CSVReader {
19 static constexpr std::streamsize bufmaxsize = 64;
20 std::array<char, bufmaxsize + 1> s;
21 std::streamsize bufidx = 0;
22 bool keep_reading = true;
23 static constexpr char end = '\n';
24
25 [[nodiscard]] F read(std::istream &is, char sep) {
26 // Get some characters to process
27 if (keep_reading)
28 read_chunk(is);
29 // Parse a number
30 F v;
31 char *bufend = s.data() + bufidx;
32 const char *ptr = read_single(s.data(), bufend, v);
33 // Check separator
34 if (ptr != bufend && *ptr != sep)
35 throw read_error("csv::read_row unexpected character '" +
36 std::string{*ptr} + "'");
37 // Shift the buffer over
38 if (ptr != bufend) {
39 std::copy(ptr + 1, static_cast<const char *>(bufend), s.data());
40 bufidx -= ptr + 1 - s.data();
41 } else {
42 bufidx = 0;
43 }
44 return v;
45 }
46
47 void read_chunk(std::istream &is) {
48 if (!is)
49 throw read_error(
50 "csv::read_row invalid stream: " + std::to_string(is.bad()) +
51 " " + std::to_string(is.fail()) + " " +
52 std::to_string(is.eof()));
53 if (bufmaxsize == bufidx)
54 return;
55 if (!is.get(s.data() + bufidx, bufmaxsize - bufidx + 1, end))
56 throw read_error(
57 "csv::read_row extraction failed: " + std::to_string(is.bad()) +
58 " " + std::to_string(is.fail()) + " " +
59 std::to_string(is.eof()));
60 bufidx += is.gcount();
61 keep_reading = is.peek() != end && !is.eof();
62 assert(bufidx <= bufmaxsize);
63 }
64
65 void skip_comments(std::istream &is) {
66 assert(bufidx == 0);
67 if (is.eof() || is.peek() == end)
68 return;
69 while (!is.eof()) {
70 read_chunk(is);
71 if (bufidx == 0 || s.front() != '#')
72 break;
73 while (keep_reading) {
74 bufidx = 0;
75 read_chunk(is);
76 }
77 bufidx = 0;
78 next_line(is);
79 }
80 }
81
82#if __cpp_lib_to_chars
83 static const char *read_single(const char *bufbegin, const char *bufend,
84 F &v) {
85 if (bufbegin != bufend && *bufbegin == '+')
86 ++bufbegin;
87 const auto [ptr, ec] = std::from_chars(bufbegin, bufend, v);
88 const auto bufvw = std::string_view(bufbegin, bufend);
89 if (ec != std::errc{})
90 throw read_error("csv::read_row conversion failed '" +
91 std::string(bufvw) +
92 "': " + std::make_error_code(ec).message());
93 return ptr;
94 }
95#else
96 static void strtod_ovl(const char *str, char **str_end, float &v) {
97 v = std::strtof(str, str_end);
98 }
99 static void strtod_ovl(const char *str, char **str_end, double &v) {
100 v = std::strtod(str, str_end);
101 }
102 static void strtod_ovl(const char *str, char **str_end, long double &v) {
103 v = std::strtold(str, str_end);
104 }
105 static void strtod_ovl(const char *str, char **str_end, long long &v) {
106 v = std::strtoll(str, str_end, 10);
107 }
108 static void strtod_ovl(const char *str, char **str_end, long &v) {
109 v = std::strtol(str, str_end, 10);
110 }
111 static void strtod_ovl(const char *str, char **str_end, int &v) {
112 v = static_cast<int>(std::strtol(str, str_end, 10));
113 }
114 static const char *read_single(const char *bufbegin, char *bufend, F &v) {
115 *bufend = '\0';
116 char *ptr;
117 errno = 0;
118 strtod_ovl(bufbegin, &ptr, v);
119 if (errno || ptr == bufbegin)
120 throw read_error("csv::read_row conversion failed '" +
121 std::string(bufbegin) +
122 "': " + std::to_string(errno));
123 return ptr;
124 }
125#endif
126
127 void next_line(std::istream &is) const {
128 if (bufidx > 0 || (!is.eof() && is.get() != end))
129 throw read_error("csv::read_row line not fully consumed");
130 }
131
132 [[nodiscard]] bool done(std::istream &is) const {
133 bool keep_reading = is.peek() != end && !is.eof();
134 return bufidx == 0 && !keep_reading;
135 }
136};
137
138#ifdef ALPAQA_WITH_QUAD_PRECISION
139template <>
140const char *CSVReader<__float128>::read_single(const char *bufbegin,
141 const char *bufend,
142 __float128 &v) {
143 long double ld;
145 v = static_cast<__float128>(ld);
146 return ret;
147}
148#endif
149
150template <class F>
151 requires(std::floating_point<F> || std::integral<F>)
152void read_row_impl(std::istream &is, Eigen::Ref<Eigen::VectorX<F>> v,
153 char sep) {
156 for (auto &vv : v)
157 vv = reader.read(is, sep);
158 reader.next_line(is);
159}
160
161template <class F>
162 requires(std::floating_point<F> || std::integral<F>)
163std::vector<F> read_row_std_vector(std::istream &is, char sep) {
165 std::vector<F> v;
167 while (!reader.done(is))
168 v.push_back(reader.read(is, sep));
169 reader.next_line(is);
170 return v;
171}
172
173} // namespace alpaqa::csv
std::vector< F > read_row_std_vector(std::istream &is, char sep)
Definition csv.tpp:163
void read_row_impl(std::istream &is, Eigen::Ref< Eigen::VectorX< F > > v, char sep)
Definition csv.tpp:152
constexpr const auto inf
Definition config.hpp:112
void read_chunk(std::istream &is)
Definition csv.tpp:47
static void strtod_ovl(const char *str, char **str_end, long &v)
Definition csv.tpp:108
static void strtod_ovl(const char *str, char **str_end, int &v)
Definition csv.tpp:111
static const char * read_single(const char *bufbegin, char *bufend, F &v)
Definition csv.tpp:114
bool done(std::istream &is) const
Definition csv.tpp:132
std::array< char, bufmaxsize+1 > s
Definition csv.tpp:20
static void strtod_ovl(const char *str, char **str_end, long long &v)
Definition csv.tpp:105
void next_line(std::istream &is) const
Definition csv.tpp:127
F read(std::istream &is, char sep)
Definition csv.tpp:25
static void strtod_ovl(const char *str, char **str_end, double &v)
Definition csv.tpp:99
static void strtod_ovl(const char *str, char **str_end, long double &v)
Definition csv.tpp:102
static void strtod_ovl(const char *str, char **str_end, float &v)
Definition csv.tpp:96
void skip_comments(std::istream &is)
Definition csv.tpp:65