kblib 0.2.3
General utilities library for modern C++
io.cpp
Go to the documentation of this file.
1#include "kblib/io.h"
2#include "catch.hpp"
3
4#include "kblib/hash.h"
5
6#include <deque>
7#include <iostream>
8#include <sstream>
9#include <vector>
10
11TEST_CASE("get_line") {
12 std::istringstream is{"line1\nline2\nline3\n"};
13 std::string line;
14 std::vector<std::string> v;
15 while (is >> kblib::get_line(line)) {
16 v.push_back(line);
17 }
18 REQUIRE(v == std::vector<std::string>{"line1", "line2", "line3"});
19}
20TEST_CASE("wide get_line") {
21 std::wistringstream is{L"line1\nline2\nline3\n"};
22 std::wstring line;
23 std::vector<std::wstring> v;
24 while (is >> kblib::get_line(line)) {
25 v.push_back(line);
26 }
27 REQUIRE(v == std::vector<std::wstring>{L"line1", L"line2", L"line3"});
28}
29
30TEST_CASE("nl") {
31 std::istringstream is("abc \t \n"
32 " xyz \n"
33 "shd sgdf ");
34 std::string v;
35 is >> v;
36 CHECK(v == "abc");
37 is >> kblib::nl;
38 CHECK(is.peek() == ' ');
39 std::getline(is, v);
40 CHECK(v == " xyz ");
41 is >> v;
42 CHECK(v == "shd");
43 is >> kblib::nl;
44 is >> v;
45 CHECK(v == "sgdf");
46 is >> kblib::nl;
47 CHECK(is.eof());
48}
49
50TEST_CASE("nl(wchar_t)") {
51 std::wistringstream is(L"abc \t \n"
52 " xyz \n"
53 "shd sgdf ");
54 std::wstring v;
55 is >> v;
56 REQUIRE(v == L"abc");
57 is >> kblib::nl;
58 REQUIRE(is.peek() == ' ');
59 std::getline(is, v);
60 REQUIRE(v == L" xyz ");
61 is >> v;
62 REQUIRE(v == L"shd");
63 is >> kblib::nl;
64 is >> v;
65 REQUIRE(v == L"sgdf");
66 is >> kblib::nl;
67 REQUIRE(is.eof());
68}
69
70TEST_CASE("expect(good)") {
71 std::istringstream is("11/17/2020");
72 int day{}, month{}, year{};
73 is >> month >> kblib::expect('/');
74 REQUIRE(is);
75 is >> day >> kblib::expect('/') >> year;
76 REQUIRE(is);
77 REQUIRE(month == 11);
78 REQUIRE(day == 17);
79 REQUIRE(year == 2020);
80}
81
82TEST_CASE("expect(fail)") {
83 std::istringstream is("11-17-2020");
84 int day{}, month{}, year{};
85 is >> month >> kblib::expect('/');
86 REQUIRE(is.fail());
87 is.clear();
88 is >> kblib::expect('-');
89 REQUIRE(is);
90 is >> day >> kblib::expect('/');
91 REQUIRE(is.fail());
92 is.clear();
93 is >> kblib::expect('-');
94 REQUIRE(is);
95 is >> year;
96 REQUIRE(is);
97 REQUIRE(month == 11);
98 REQUIRE(day == 17);
99 REQUIRE(year == 2020);
100}
101
102TEST_CASE("expect(wchar_t, good)") {
103 std::wistringstream is(L"11/17/2020");
104 int day{}, month{}, year{};
105 is >> month >> kblib::expect(L'/');
106 REQUIRE(is);
107 is >> day >> kblib::expect(L'/') >> year;
108 REQUIRE(is);
109 REQUIRE(month == 11);
110 REQUIRE(day == 17);
111 REQUIRE(year == 2020);
112}
113
114TEST_CASE("expect(wchar_t, fail)") {
115 std::wistringstream is(L"11-17-2020");
116 int day{}, month{}, year{};
117 is >> month >> kblib::expect(L'/');
118 REQUIRE(is.fail());
119 is.clear();
120 is >> kblib::expect(L'-');
121 REQUIRE(is);
122 is >> day >> kblib::expect(L'/');
123 REQUIRE(is.fail());
124 is.clear();
125 is >> kblib::expect(L'-');
126 REQUIRE(is);
127 is >> year;
128 REQUIRE(is);
129 REQUIRE(month == 11);
130 REQUIRE(day == 17);
131 REQUIRE(year == 2020);
132}
133
134TEST_CASE("expect(widening, good)") {
135 std::wistringstream is(L"11/17/2020");
136 int day{}, month{}, year{};
137 is >> month >> kblib::expect('/');
138 REQUIRE(is);
139 is >> day >> kblib::expect('/') >> year;
140 REQUIRE(is);
141 REQUIRE(month == 11);
142 REQUIRE(day == 17);
143 REQUIRE(year == 2020);
144}
145
146TEST_CASE("expect(widening, fail)") {
147 std::wistringstream is(L"11-17-2020");
148 int day{}, month{}, year{};
149 is >> month >> kblib::expect('/');
150 REQUIRE(is.fail());
151 is.clear();
152 is >> kblib::expect('-');
153 REQUIRE(is);
154 is >> day >> kblib::expect('/');
155 REQUIRE(is.fail());
156 is.clear();
157 is >> kblib::expect('-');
158 REQUIRE(is);
159 is >> year;
160 REQUIRE(is);
161 REQUIRE(month == 11);
162 REQUIRE(day == 17);
163 REQUIRE(year == 2020);
164}
165
166// No locale support for unicode
167#if 0
168TEST_CASE("expect(widening, UFT-16, good)") {
169 std::basic_istringstream<char16_t> is(u"11/17/2020");
170 int day{}, month{}, year{};
171 is >> month >> kblib::expect('/');
172 REQUIRE(is);
173 is >> day >> kblib::expect('/') >> year;
174 REQUIRE(is);
175 REQUIRE(month == 11);
176 REQUIRE(day == 17);
177 REQUIRE(year == 2020);
178}
179
180TEST_CASE("expect(widening, UTF-16, fail)") {
181 std::basic_istringstream<char16_t> is(u"11-17-2020");
182 int day{}, month{}, year{};
183 is >> month >> kblib::expect('/');
184 REQUIRE(is.fail());
185 is.clear();
186 is >> kblib::expect('-');
187 REQUIRE(is);
188 is >> day >> kblib::expect('/');
189 REQUIRE(is.fail());
190 is.clear();
191 is >> kblib::expect('-');
192 REQUIRE(is);
193 is >> year;
194 REQUIRE(is);
195 REQUIRE(month == 11);
196 REQUIRE(day == 17);
197 REQUIRE(year == 2020);
198}
199
200TEST_CASE("expect(widening, UFT-32, good)") {
201 std::basic_istringstream<char32_t> is(U"11/17/2020");
202 int day{}, month{}, year{};
203 is >> month >> kblib::expect('/');
204 REQUIRE(is);
205 is >> day >> kblib::expect('/') >> year;
206 REQUIRE(is);
207 REQUIRE(month == 11);
208 REQUIRE(day == 17);
209 REQUIRE(year == 2020);
210}
211
212TEST_CASE("expect(widening, UTF-32, fail)") {
213 std::basic_istringstream<char32_t> is(U"11-17-2020");
214 int day{}, month{}, year{};
215 is >> month >> kblib::expect('/');
216 REQUIRE(is.fail());
217 is.clear();
218 is >> kblib::expect('-');
219 REQUIRE(is);
220 is >> day >> kblib::expect('/');
221 REQUIRE(is.fail());
222 is.clear();
223 is >> kblib::expect('-');
224 REQUIRE(is);
225 is >> year;
226 REQUIRE(is);
227 REQUIRE(month == 11);
228 REQUIRE(day == 17);
229 REQUIRE(year == 2020);
230}
231
232TEST_CASE("expect(widening, UTF-16 to UFT-32, good)") {
233 std::basic_istringstream<char32_t> is(U"11/17/2020");
234 int day{}, month{}, year{};
235 is >> month >> kblib::expect(u'/');
236 REQUIRE(is);
237 is >> day >> kblib::expect(u'/') >> year;
238 REQUIRE(is);
239 REQUIRE(month == 11);
240 REQUIRE(day == 17);
241 REQUIRE(year == 2020);
242}
243
244TEST_CASE("expect(widening, UTF-16 to UTF-32, fail)") {
245 std::basic_istringstream<char32_t> is(U"11-17-2020");
246 int day{}, month{}, year{};
247 is >> month >> kblib::expect(u'/');
248 REQUIRE(is.fail());
249 is.clear();
250 is >> kblib::expect(u'-');
251 REQUIRE(is);
252 is >> day >> kblib::expect(u'/');
253 REQUIRE(is.fail());
254 is.clear();
255 is >> kblib::expect(u'-');
256 REQUIRE(is);
257 is >> year;
258 REQUIRE(is);
259 REQUIRE(month == 11);
260 REQUIRE(day == 17);
261 REQUIRE(year == 2020);
262}
263#endif
264
265#if 0 // Compile error
266TEST_CASE("expect(narrowing, good)") {
267 std::istringstream is("11/17/2020");
268 int day{}, month{}, year{};
269 is >> month >> kblib::expect(L'/');
270 REQUIRE(is);
271 is >> day >> kblib::expect(L'/') >> year;
272 REQUIRE(is);
273 REQUIRE(month == 11);
274 REQUIRE(day == 17);
275 REQUIRE(year == 2020);
276}
277
278TEST_CASE("expect(narrowing, fail)") {
279 std::istringstream is("11-17-2020");
280 int day{}, month{}, year{};
281 is >> month >> kblib::expect(L'/');
282 REQUIRE(is.fail());
283 is.clear();
284 is >> kblib::expect(L'-');
285 REQUIRE(is);
286 is >> day >> kblib::expect(L'/');
287 REQUIRE(is.fail());
288 is.clear();
289 is >> kblib::expect(L'-');
290 REQUIRE(is);
291 is >> year;
292 REQUIRE(is);
293 REQUIRE(month == 11);
294 REQUIRE(day == 17);
295 REQUIRE(year == 2020);
296}
297#endif
298
299#if KBLIB_USE_CXX17
300TEST_CASE("get_file_contents") {
301 auto filename = "kblib";
302 auto filestr = kblib::get_file_contents(filename);
303 if (filestr) {
304 std::cout << "FNV32a(" << filename << "): " << kblib::FNV32a(*filestr)
305 << '\n';
306 } else {
307 std::cout << "failed to open " << filename << "\n";
308 }
309 auto filevec = kblib::get_file_contents<std::vector<uint8_t>>(filename);
310 if (filevec) {
311 std::cout << "FNV32a(" << filename
312 << "): " << kblib::FNVa<std::uint32_t>(*filevec) << '\n';
313 } else {
314 std::cout << "failed to open " << filename << "\n";
315 }
316 // D must be a sequence of char-sized objects, char32_t doesn't work.
317 // auto filewstr = kblib::get_file_contents<std::u32string>(filename);
318
319 // deque is not a contiguous container, and does not provide a .data() member
320 // so the second overload of get_file_contents will be used.
321 auto fileerror = kblib::get_file_contents<std::deque<char>>(filename);
322}
323#endif
324
325TEST_CASE("tee_stream") {
326 std::ostringstream a, b;
327#if KBLIB_USE_CXX17
328 auto os = kblib::tee(a, b);
329#else
330 // kblib::basic_teestream<std::ostringstream, std::ostringstream> os(a, b);
331 auto&& os = kblib::tee(a, b);
332#endif
333
334 os << "test" << std::flush;
335 REQUIRE(os);
336 CHECK(a.str() == "test");
337 CHECK(b.str() == "test");
338 CHECK(a.str() == b.str());
339
340 os << 's' << std::flush;
341 REQUIRE(os);
342 CHECK(a.str() == "tests");
343 CHECK(b.str() == "tests");
344 CHECK(a.str() == b.str());
345
346 os << std::setw(8) << 42 << std::flush;
347 REQUIRE(os);
348 CHECK(a.str() == "tests 42");
349 CHECK(b.str() == "tests 42");
350 CHECK(a.str() == b.str());
351
352 {
353 auto len = a.str().length();
354 for (KBLIB_UNUSED auto _ : kblib::range(2048)) {
355 os << '.' << std::flush;
356 CHECK(a.str() == b.str());
357 CHECK(a.str().length() == ++len);
358 CHECK(a.str().back() == '.');
359 }
360 }
361 a.str("");
362 b.str("");
363
364 {
365 auto big_str = std::string(2048, '?');
366 os << big_str << std::flush;
367 REQUIRE(os);
368 CHECK(a.str() == big_str);
369 CHECK(a.str() == b.str());
370 }
371}
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
TEST_CASE("get_line")
Definition: io.cpp:11
Provides I/O utilities.
auto nl(std::basic_istream< CharT, Traits > &is) -> std::basic_istream< CharT, Traits > &
Read in spaces until the end of the line is found.
Definition: io.h:212
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
auto tee(StreamA &a, StreamB &b) -> basic_teestream< StreamA, StreamB >
Definition: io.h:525
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
Definition: iterators.h:621
auto get_file_contents(const string &filename) -> std::optional< D >
Read the entire contents of a file into a container, such as std::string or std::vector<char>....
Definition: io.h:97
constexpr auto FNV32a(std::string_view s, std::uint32_t hval=fnv::fnv_offset< std::uint32_t >::value) noexcept -> std::uint32_t
A standard FNV32a hash function, for string_views.
Definition: hash.h:194
auto getline(std::istream &is) -> std::string
By-value std::getline wrapper.
Definition: io.h:146
auto expect(CharT c) -> auto
Read a character from an input stream only if it equals c. Acts as a FormattedInputOperation,...
Definition: io.h:321
auto get_line(string< CharT, O... > &str) -> auto
Read a whole line into a std::basic_string-like class template.
Definition: io.h:340
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.
Definition: tdecl.h:130