C++ Utilities 5.27.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Loading...
Searching...
No Matches
iotests.cpp
Go to the documentation of this file.
1#include "./testutils.h"
2
3using namespace CppUtilities;
4
6
7#ifndef CPP_UTILITIES_NO_ICONV
11std::ostream &operator<<(std::ostream &out, const std::wstring &s)
12{
13 const auto utf8 = CppUtilities::
14#ifdef CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN
16#else
18#endif
19 (reinterpret_cast<const char *>(s.data()), s.size() * (sizeof(std::wstring::value_type) / sizeof(char)));
20 out.write(utf8.first.get(), static_cast<std::streamsize>(utf8.second));
21 return out;
22}
23#endif
24
27
29#include "../io/binaryreader.h"
30#include "../io/binarywriter.h"
31#include "../io/bitreader.h"
32#include "../io/buffersearch.h"
33#include "../io/copy.h"
34#include "../io/inifile.h"
35#include "../io/misc.h"
37#include "../io/path.h"
38
39#ifdef CPP_UTILITIES_USE_LIBARCHIVE
40#include "../io/archive.h"
41#endif
42
43#include <cppunit/TestFixture.h>
44#include <cppunit/extensions/HelperMacros.h>
45
46#include <algorithm>
47#include <cstddef>
48#include <fstream>
49#include <regex>
50#include <sstream>
51
52#ifdef PLATFORM_WINDOWS
53#include <cstdio>
54#endif
55
56#ifdef PLATFORM_UNIX
57#include <sys/fcntl.h>
58#include <sys/types.h>
59#endif
60
61using namespace std;
62using namespace CppUtilities::Literals;
63using namespace CPPUNIT_NS;
64
68class IoTests : public TestFixture {
69 CPPUNIT_TEST_SUITE(IoTests);
70 CPPUNIT_TEST(testBinaryReader);
71 CPPUNIT_TEST(testBinaryWriter);
72 CPPUNIT_TEST(testBitReader);
73 CPPUNIT_TEST(testBufferSearch);
74 CPPUNIT_TEST(testPathUtilities);
75 CPPUNIT_TEST(testIniFile);
76 CPPUNIT_TEST(testAdvancedIniFile);
77 CPPUNIT_TEST(testCopy);
78 CPPUNIT_TEST(testCopyWithNativeFileStream);
79 CPPUNIT_TEST(testReadFile);
80 CPPUNIT_TEST(testWriteFile);
81 CPPUNIT_TEST(testAnsiEscapeCodes);
82#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
83 CPPUNIT_TEST(testNativeFileStream);
84#endif
85#ifdef CPP_UTILITIES_USE_LIBARCHIVE
86 CPPUNIT_TEST(testExtractingArchive);
87#endif
88 CPPUNIT_TEST_SUITE_END();
89
90public:
91 void setUp() override;
92 void tearDown() override;
93
94 void testBinaryReader();
95 void testBinaryWriter();
96 void testBitReader();
97 void testBufferSearch();
98 void testPathUtilities();
99 void testIniFile();
100 void testAdvancedIniFile();
101 void testCopy();
103 void testReadFile();
104 void testWriteFile();
105 void testAnsiEscapeCodes();
106#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
107 void testNativeFileStream();
108#endif
109#ifdef CPP_UTILITIES_USE_LIBARCHIVE
110 void testExtractingArchive();
111#endif
112};
113
115
117{
118}
119
121{
122}
123
128{
129 // read test file
130 fstream testFile;
131 testFile.exceptions(ios_base::failbit | ios_base::badbit);
132 testFile.open(testFilePath("some_data"), ios_base::in | ios_base::binary);
133 BinaryReader reader(&testFile);
134 CPPUNIT_ASSERT_EQUAL(static_cast<istream::pos_type>(398), reader.readStreamsize());
135 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0x0102u), reader.readUInt16LE());
136 CPPUNIT_ASSERT_EQUAL(static_cast<istream::pos_type>(396), reader.readRemainingBytes());
137 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0x0102u), reader.readUInt16BE());
138 CPPUNIT_ASSERT_EQUAL(0x010203u, reader.readUInt24LE());
139 CPPUNIT_ASSERT_EQUAL(0x010203u, reader.readUInt24BE());
140 CPPUNIT_ASSERT_EQUAL(0x01020304u, reader.readUInt32LE());
141 CPPUNIT_ASSERT_EQUAL(0x01020304u, reader.readUInt32BE());
142 CPPUNIT_ASSERT_EQUAL(0x0102030405u, reader.readUInt40LE());
143 CPPUNIT_ASSERT_EQUAL(0x0102030405u, reader.readUInt40BE());
144 CPPUNIT_ASSERT_EQUAL(0x01020304050607u, reader.readUInt56LE());
145 CPPUNIT_ASSERT_EQUAL(0x01020304050607u, reader.readUInt56BE());
146 CPPUNIT_ASSERT_EQUAL(0x0102030405060708u, reader.readUInt64LE());
147 CPPUNIT_ASSERT_EQUAL(0x0102030405060708u, reader.readUInt64BE());
148 testFile.seekg(0);
149 CPPUNIT_ASSERT_EQUAL(reader.readInt16LE(), static_cast<std::int16_t>(0x0102));
150 CPPUNIT_ASSERT_EQUAL(reader.readInt16BE(), static_cast<std::int16_t>(0x0102));
151 CPPUNIT_ASSERT_EQUAL(0x010203, reader.readInt24LE());
152 CPPUNIT_ASSERT_EQUAL(0x010203, reader.readInt24BE());
153 CPPUNIT_ASSERT_EQUAL(0x01020304, reader.readInt32LE());
154 CPPUNIT_ASSERT_EQUAL(0x01020304, reader.readInt32BE());
155 CPPUNIT_ASSERT_EQUAL(0x0102030405, reader.readInt40LE());
156 CPPUNIT_ASSERT_EQUAL(0x0102030405, reader.readInt40BE());
157 CPPUNIT_ASSERT_EQUAL(0x01020304050607, reader.readInt56LE());
158 CPPUNIT_ASSERT_EQUAL(0x01020304050607, reader.readInt56BE());
159 CPPUNIT_ASSERT_EQUAL(0x0102030405060708, reader.readInt64LE());
160 CPPUNIT_ASSERT_EQUAL(0x0102030405060708, reader.readInt64BE());
161 CPPUNIT_ASSERT_EQUAL(1.125f, reader.readFloat32LE());
162 CPPUNIT_ASSERT_EQUAL(1.625, reader.readFloat64LE());
163 CPPUNIT_ASSERT_EQUAL(1.125f, reader.readFloat32BE());
164 CPPUNIT_ASSERT_EQUAL(reader.readFloat64BE(), 1.625);
165 CPPUNIT_ASSERT_EQUAL(false, reader.readBool());
166 CPPUNIT_ASSERT_EQUAL(true, reader.readBool());
167 CPPUNIT_ASSERT_EQUAL("abc"s, reader.readString(3));
168 CPPUNIT_ASSERT_EQUAL(reader.readLengthPrefixedString(), "ABC"s);
169 CPPUNIT_ASSERT_EQUAL("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
170 "23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
171 "45678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"
172 "678901234567890123456789"s,
173 reader.readLengthPrefixedString());
174 CPPUNIT_ASSERT_EQUAL("def"s, reader.readTerminatedString());
175 testFile.seekg(-4, ios_base::cur);
176 CPPUNIT_ASSERT_EQUAL("def"s, reader.readTerminatedString(5, 0));
177 CPPUNIT_ASSERT_THROW(reader.readLengthPrefixedString(), ConversionException);
178 CPPUNIT_ASSERT_MESSAGE("pos in stream not advanced on conversion error", reader.readByte() == 0);
179
180 // test ownership
181 reader.setStream(nullptr, true);
182 reader.setStream(new fstream(), true);
183 BinaryReader reader2(reader);
184 CPPUNIT_ASSERT(reader2.stream() == reader.stream());
185 CPPUNIT_ASSERT(!reader2.hasOwnership());
186 reader.setStream(&testFile, false);
187 reader.setStream(new fstream(), true);
188}
189
194{
195 // prepare reading expected data
196 fstream testFile;
197 testFile.exceptions(ios_base::failbit | ios_base::badbit);
198 testFile.open(testFilePath("some_data"), ios_base::in | ios_base::binary);
199
200 // prepare output stream
201 stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary);
202 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
203 char testData[397];
204#if defined(__GLIBCXX__) && !defined(_LIBCPP_VERSION)
205#define USE_RDBUF_DIRECTLY
206 outputStream.rdbuf()->pubsetbuf(testData, sizeof(testData));
207#endif
208
209 // write test data
210 BinaryWriter writer(&outputStream);
211 writer.writeUInt16LE(0x0102u);
212 writer.writeUInt16BE(0x0102u);
213 writer.writeUInt24LE(0x010203u);
214 writer.writeUInt24BE(0x010203u);
215 writer.writeUInt32LE(0x01020304u);
216 writer.writeUInt32BE(0x01020304u);
217 writer.writeUInt40LE(0x0102030405u);
218 writer.writeUInt40BE(0x0102030405u);
219 writer.writeUInt56LE(0x01020304050607u);
220 writer.writeUInt56BE(0x01020304050607u);
221 writer.writeUInt64LE(0x0102030405060708u);
222 writer.writeUInt64BE(0x0102030405060708u);
223
224#ifndef USE_RDBUF_DIRECTLY
225 outputStream.seekg(0);
226 outputStream.read(testData, 58);
227#endif
228
229 // test written values
230 for (char c : testData) {
231 const auto pos = static_cast<std::size_t>(testFile.tellg());
232 if (pos >= 58) {
233 break;
234 }
235 char expected;
236 testFile.read(&expected, 1);
237 CPPUNIT_ASSERT_EQUAL_MESSAGE(argsToString("offset ", pos), asHexNumber(expected), asHexNumber(c));
238 }
239 testFile.seekg(0);
240 outputStream.seekp(0);
241
242 // write more test data
243 writer.writeInt16LE(0x0102);
244 writer.writeInt16BE(0x0102);
245 writer.writeInt24LE(0x010203);
246 writer.writeInt24BE(0x010203);
247 writer.writeInt32LE(0x01020304);
248 writer.writeInt32BE(0x01020304);
249 writer.writeInt40LE(0x0102030405);
250 writer.writeInt40BE(0x0102030405);
251 writer.writeInt56LE(0x01020304050607);
252 writer.writeInt56BE(0x01020304050607);
253 writer.writeInt64LE(0x0102030405060708);
254 writer.writeInt64BE(0x0102030405060708);
255 writer.writeFloat32LE(1.125);
256 writer.writeFloat64LE(1.625);
257 writer.writeFloat32BE(1.125);
258 writer.writeFloat64BE(1.625);
259 writer.writeBool(false);
260 writer.writeBool(true);
261 writer.writeString("abc");
262 writer.writeLengthPrefixedString("ABC");
263 writer.writeLengthPrefixedString("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
264 "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
265 "234567890123456789012345678901234567890123456789012345678901234567890123456789");
266 writer.writeTerminatedString("def");
267
268#ifndef USE_RDBUF_DIRECTLY
269 outputStream.seekg(0);
270 outputStream.read(testData, 58);
271#endif
272
273 // test written values
274 for (char c : testData) {
275 const auto pos = static_cast<std::size_t>(testFile.tellg());
276 if (pos >= 58) {
277 break;
278 }
279 char expected;
280 testFile.read(&expected, 1);
281 CPPUNIT_ASSERT_EQUAL_MESSAGE(argsToString("offset ", pos), asHexNumber(expected), asHexNumber(c));
282 }
283
284 // test ownership
285 writer.setStream(nullptr, true);
286 writer.setStream(new fstream(), true);
287 BinaryWriter writer2(writer);
288 CPPUNIT_ASSERT(writer2.stream() == writer.stream());
289 CPPUNIT_ASSERT(!writer2.hasOwnership());
290 writer.setStream(&testFile, false);
291 writer.setStream(new fstream(), true);
292}
293
298{
299 const std::uint8_t testData[] = { 0x81, 0x90, 0x3C, 0x44, 0x28, 0x00, 0x44, 0x10, 0x20, 0xFF, 0xFA };
300 BitReader reader(reinterpret_cast<const char *>(testData), sizeof(testData));
301 CPPUNIT_ASSERT(reader.readBit() == 1);
302 reader.skipBits(6);
303 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(3), reader.showBits<std::uint8_t>(2));
304 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(3), reader.readBits<std::uint8_t>(2));
305 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint32_t>(0x103C4428 << 1), reader.readBits<std::uint32_t>(32));
306 reader.align();
307 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(0x44), reader.readBits<std::uint8_t>(8));
308 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(7), reader.readUnsignedExpGolombCodedBits<std::uint8_t>());
309 CPPUNIT_ASSERT_EQUAL(static_cast<std::int8_t>(4), reader.readSignedExpGolombCodedBits<std::int8_t>());
310 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(0), reader.readBit());
311 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(0), reader.readBit());
312 reader.skipBits(8 + 4);
313 CPPUNIT_ASSERT_EQUAL(4_st, reader.bitsAvailable());
314 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(0xA), reader.readBits<std::uint8_t>(4));
315 CPPUNIT_ASSERT_THROW(reader.readBit(), std::ios_base::failure);
316 CPPUNIT_ASSERT_THROW(reader.skipBits(1), std::ios_base::failure);
317 reader.reset(reinterpret_cast<const char *>(testData), sizeof(testData));
318 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(8 * sizeof(testData)), reader.bitsAvailable());
319}
320
325{
326 // setup search to test
327 auto expectedResult = std::string();
328 auto hasResult = false;
329 auto bs = BufferSearch("Updated version: ", "\t\n", "Starting build", [&](BufferSearch &, std::string &&result) {
330 CPPUNIT_ASSERT_EQUAL(expectedResult, result);
331 CPPUNIT_ASSERT_MESSAGE("callback only invoked once", !hasResult);
332 hasResult = true;
333 });
334
335 // feed data into the search
336 char buffer[30] = { 0 };
337 bs(buffer, 0);
338 CPPUNIT_ASSERT(!hasResult);
339 std::strcpy(buffer, "Starting Updated");
340 CPPUNIT_ASSERT(bs.process(std::string_view(buffer, 16)) == nullptr);
341 CPPUNIT_ASSERT(!hasResult);
342 std::strcpy(buffer, " version: some ");
343 bs(buffer, 15);
344 CPPUNIT_ASSERT(!hasResult);
345 expectedResult = "some version number";
346 std::strcpy(buffer, "version number\tmore chars");
347 CPPUNIT_ASSERT_EQUAL(static_cast<std::ptrdiff_t>(14), bs.process(buffer, 25) - buffer);
348 CPPUNIT_ASSERT(hasResult);
349 hasResult = false;
350 std::strcpy(buffer, "... Starting build ...");
351 bs(buffer, 22);
352 CPPUNIT_ASSERT(!hasResult);
353}
354
359{
360 CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("C:\\libs\\libc++utilities.so"));
361 CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("C:\\libs/libc++utilities.so"));
362 CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("/usr/lib/libc++utilities.so"));
363 CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("libc++utilities.so"));
364 CPPUNIT_ASSERT_EQUAL("/usr/lib/"s, directory("/usr/lib/libc++utilities.so"));
365 CPPUNIT_ASSERT_EQUAL(string(), directory("libc++utilities.so"));
366 CPPUNIT_ASSERT_EQUAL("C:\\libs\\"s, directory("C:\\libs\\libc++utilities.so"));
367 CPPUNIT_ASSERT_EQUAL("C:\\libs/"s, directory("C:\\libs/libc++utilities.so"));
368 string invalidPath("lib/c++uti*lities.so?");
369 removeInvalidChars(invalidPath);
370 CPPUNIT_ASSERT(invalidPath == "libc++utilities.so");
371
372 const auto input = std::string_view("some/path/täst");
373 const auto expected = input;
374 const auto output = makeNativePath(input);
375#ifdef PLATFORM_WINDOWS
376#ifndef CPP_UTILITIES_NO_ICONV
377 const auto outputAsUtf8 = convertUtf16LEToUtf8(reinterpret_cast<const char *>(output.data()), output.size() * 2);
378 const auto outputView = std::string_view(outputAsUtf8.first.get(), outputAsUtf8.second);
379 CPPUNIT_ASSERT_EQUAL_MESSAGE("makeNativePath()", expected, outputView);
380#else
381 CPP_UTILITIES_UNUSED(expected)
383#endif
384#else
385 CPPUNIT_ASSERT_EQUAL_MESSAGE("makeNativePath()", expected, output);
386#endif
387}
388
393{
394 // prepare reading test file
395 fstream inputFile;
396 inputFile.exceptions(ios_base::failbit | ios_base::badbit);
397 inputFile.open(testFilePath("test.ini"), ios_base::in);
398
399 IniFile ini;
400 ini.parse(inputFile);
401 const auto globalScope = ini.data().at(0);
402 const auto scope1 = ini.data().at(1);
403 const auto scope2 = ini.data().at(2);
404 CPPUNIT_ASSERT(globalScope.first.empty());
405 CPPUNIT_ASSERT(globalScope.second.find("key0") != globalScope.second.cend());
406 CPPUNIT_ASSERT(globalScope.second.find("key0")->second == "value 0");
407 CPPUNIT_ASSERT(globalScope.second.find("key1") == globalScope.second.cend());
408 CPPUNIT_ASSERT(scope1.first == "scope 1");
409 CPPUNIT_ASSERT(scope1.second.find("key1") != scope1.second.cend());
410 CPPUNIT_ASSERT(scope1.second.find("key1")->second == "value 1");
411 CPPUNIT_ASSERT(scope1.second.find("key2") != scope1.second.cend());
412 CPPUNIT_ASSERT(scope1.second.find("key2")->second == "value=2");
413 CPPUNIT_ASSERT(scope2.first == "scope 2");
414 CPPUNIT_ASSERT(scope2.second.find("key5") == scope2.second.cend());
415
416 // write values to another file
417 fstream outputFile;
418 outputFile.exceptions(ios_base::failbit | ios_base::badbit);
419 outputFile.open(workingCopyPath("output.ini", WorkingCopyMode::NoCopy), ios_base::out | ios_base::trunc);
420 ini.make(outputFile);
421
422 // parse written values (again)
423 outputFile.close();
424 outputFile.open(workingCopyPath("output.ini", WorkingCopyMode::NoCopy), ios_base::in);
425 IniFile ini2;
426 ini2.parse(outputFile);
427 CPPUNIT_ASSERT(ini.data() == ini2.data());
428}
429
434{
435 // prepare reading test file
436 fstream inputFile;
437 inputFile.exceptions(ios_base::failbit | ios_base::badbit);
438 inputFile.open(testFilePath("pacman.conf"), ios_base::in);
439
440 // parse the test file
441 AdvancedIniFile ini;
442 ini.parse(inputFile);
443
444 // check whether scope data is as expected
445 CPPUNIT_ASSERT_EQUAL_MESSAGE("5 scopes (taking implicit empty section at the end into account)", 5_st, ini.sections.size());
446 auto options = ini.findSection("options");
447 CPPUNIT_ASSERT(options != ini.sectionEnd());
448#if !defined(PLATFORM_WINDOWS) || defined(PLATFORM_MINGW) || defined(PLATFORM_CYGWIN)
449#define STD_REGEX_WORKS // the parsed data looks good, apparently std::regex behaves differently on MSVC
451 "comment block before section", "# Based on.*\n.*# GENERAL OPTIONS\n#\n"s, std::regex::extended, options->precedingCommentBlock);
452#endif
453 CPPUNIT_ASSERT_EQUAL(7_st, options->fields.size());
454 CPPUNIT_ASSERT_EQUAL("HoldPkg"s, options->fields[0].key);
455 CPPUNIT_ASSERT_EQUAL("pacman glibc"s, options->fields[0].value);
456 CPPUNIT_ASSERT_MESSAGE("value present", options->fields[0].flags && IniFileFieldFlags::HasValue);
457#ifdef STD_REGEX_WORKS
458 TESTUTILS_ASSERT_LIKE_FLAGS("comment block between section header and first field",
459 "# The following paths are.*\n.*#HookDir = /etc/pacman\\.d/hooks/\n"s, std::regex::extended, options->fields[0].precedingCommentBlock);
460#endif
461 CPPUNIT_ASSERT_EQUAL(""s, options->fields[0].followingInlineComment);
462 CPPUNIT_ASSERT_EQUAL("Foo"s, options->fields[1].key);
463 CPPUNIT_ASSERT_EQUAL("bar"s, options->fields[1].value);
464 CPPUNIT_ASSERT_MESSAGE("value present", options->fields[1].flags && IniFileFieldFlags::HasValue);
465#ifdef STD_REGEX_WORKS
466 TESTUTILS_ASSERT_LIKE_FLAGS("comment block between fields", "#XferCommand.*\n.*#CleanMethod = KeepInstalled\n"s, std::regex::extended,
467 options->fields[1].precedingCommentBlock);
468#endif
469 CPPUNIT_ASSERT_EQUAL("# inline comment"s, options->fields[1].followingInlineComment);
470 CPPUNIT_ASSERT_EQUAL("CheckSpace"s, options->fields[3].key);
471 CPPUNIT_ASSERT_EQUAL(""s, options->fields[3].value);
472 CPPUNIT_ASSERT_MESSAGE("no value present", !(options->fields[3].flags && IniFileFieldFlags::HasValue));
473#ifdef STD_REGEX_WORKS
474 TESTUTILS_ASSERT_LIKE_FLAGS("empty lines in comments preserved", "\n# Pacman.*\n.*\n\n#NoUpgrade =\n.*#TotalDownload\n"s, std::regex::extended,
475 options->fields[3].precedingCommentBlock);
476#endif
477 CPPUNIT_ASSERT_EQUAL(""s, options->fields[3].followingInlineComment);
478 auto extraScope = ini.findSection(options, "extra");
479 CPPUNIT_ASSERT(extraScope != ini.sectionEnd());
480 CPPUNIT_ASSERT_EQUAL_MESSAGE("comment block which is only an empty line", "\n"s, extraScope->precedingCommentBlock);
481 CPPUNIT_ASSERT_EQUAL_MESSAGE("inline comment after scope", "# an inline comment after a scope name"s, extraScope->followingInlineComment);
482 CPPUNIT_ASSERT_EQUAL(1_st, extraScope->fields.size());
483 CPPUNIT_ASSERT(ini.sections.back().flags && IniFileSectionFlags::Implicit);
484#ifdef STD_REGEX_WORKS
485 TESTUTILS_ASSERT_LIKE_FLAGS("comment block after last field present in implicitly added last scope", "\n# If you.*\n.*custompkgs\n"s,
486 std::regex::extended, ini.sections.back().precedingCommentBlock);
487#endif
488
489 // test finding a field from file level and const access
490 const auto *const constIniFile = &ini;
491 auto includeField = constIniFile->findField("extra", "Include");
492 CPPUNIT_ASSERT(includeField.has_value());
493 CPPUNIT_ASSERT_EQUAL("Include"s, includeField.value()->key);
494 CPPUNIT_ASSERT_EQUAL("/etc/pacman.d/mirrorlist"s, includeField.value()->value);
495 CPPUNIT_ASSERT_MESSAGE("field not present", !constIniFile->findField("extra", "Includ").has_value());
496 CPPUNIT_ASSERT_MESSAGE("scope not present", !constIniFile->findField("extr", "Includ").has_value());
497
498 // write values again; there shouldn't be a difference as the parser and the writer are supposed to
499 // preserve the order of all elements and comments
500 std::stringstream newFile;
501 ini.make(newFile);
502 std::string originalContents;
503 inputFile.clear();
504 inputFile.seekg(std::ios_base::beg);
505 // ignore warning about null pointer dereference from GCC 12 for now (which is *likely* not correct)
506#ifdef __GNUC__
507#pragma GCC diagnostic push
508#pragma GCC diagnostic ignored "-Wnull-dereference"
509#endif
510 originalContents.assign((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
511#ifdef __GNUC__
512#pragma GCC diagnostic pop
513#endif
514 CPPUNIT_ASSERT_EQUAL(originalContents, newFile.str());
515}
516
521{
522 // prepare streams
523 auto testFile = std::fstream();
524 testFile.exceptions(ios_base::failbit | ios_base::badbit);
525 testFile.open(testFilePath("some_data"), ios_base::in | ios_base::binary);
526 auto outputStream = std::stringstream(ios_base::in | ios_base::out | ios_base::binary);
527 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
528
529 // copy
530 auto copyHelper = CopyHelper<13>();
531 copyHelper.copy(testFile, outputStream, 50);
532 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(0), outputStream.tellg());
533 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), outputStream.tellp());
534 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellg());
535 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellp());
536
537 // verify
538 testFile.seekg(0);
539 for (auto i = 0; i < 50; ++i) {
540 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
541 }
542}
543
548{
549 // prepare streams
550 auto testFile = NativeFileStream();
551 testFile.exceptions(ios_base::failbit | ios_base::badbit);
552 testFile.open(testFilePath("some_data"), ios_base::in | ios_base::binary);
553 auto outputPath = workingCopyPath("copied_data", WorkingCopyMode::Cleanup);
554 auto outputStream = NativeFileStream();
555 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
556 outputStream.open(outputPath, ios_base::out | ios_base::binary);
557
558 // copy
559 auto copyHelper = CopyHelper<13>();
560 copyHelper.copy(testFile, outputStream, 50);
561 CPPUNIT_ASSERT(outputStream.is_open());
562 CPPUNIT_ASSERT(testFile.is_open());
563
564 // test seek positions (the expected values are from a run with normal std::fstream)
565 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), outputStream.tellg());
566 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), outputStream.tellp());
567 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellg());
568 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellp());
569
570 // add a few more bytes to output stream (to be sure it is still usable) and re-open for reading
571 const auto aFewMoreBytes = "a few more bytes"sv;
572 outputStream << aFewMoreBytes;
573 outputStream.close();
574 outputStream.open(outputPath, ios_base::in | ios_base::binary);
575
576 // verify
577 testFile.seekg(0);
578 for (auto i = 0; i < 50; ++i) {
579 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
580 }
581 auto tail = std::string(aFewMoreBytes.size(), '0');
582 outputStream.read(tail.data(), static_cast<std::streamsize>(tail.size()));
583 CPPUNIT_ASSERT_EQUAL(aFewMoreBytes, std::string_view(tail.data(), tail.size()));
584
585 // repeat with callback version
586 auto percentage = 0.0;
587 const auto isAborted = [] { return false; };
588 const auto callback = [&percentage](double p) { percentage = p; };
589 testFile.seekg(0);
590 outputStream.close();
591 outputStream.open(outputPath, ios_base::out | ios_base::trunc | ios_base::binary);
592 copyHelper.callbackCopy(testFile, outputStream, 50, isAborted, callback);
593 CPPUNIT_ASSERT_EQUAL(1.0, percentage);
594
595 // verify again
596 CPPUNIT_ASSERT(outputStream.is_open());
597 CPPUNIT_ASSERT(testFile.is_open());
598 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), outputStream.tellg());
599 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), outputStream.tellp());
600 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellg());
601 CPPUNIT_ASSERT_EQUAL(static_cast<std::fstream::pos_type>(50), testFile.tellp());
602 outputStream << aFewMoreBytes;
603 outputStream.close();
604 outputStream.open(outputPath, ios_base::in | ios_base::binary);
605 testFile.seekg(0);
606 for (auto i = 0; i < 50; ++i) {
607 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
608 }
609 tail.assign(aFewMoreBytes.size(), '0');
610 outputStream.read(tail.data(), static_cast<std::streamsize>(tail.size()));
611 CPPUNIT_ASSERT_EQUAL(aFewMoreBytes, std::string_view(tail.data(), tail.size()));
612}
613
618{
619 // read a file successfully
620 const string iniFilePath(testFilePath("test.ini"));
621 CPPUNIT_ASSERT_EQUAL("# file for testing INI parser\n"
622 "key0=value 0\n"
623 "\n"
624 "[scope 1]\n"
625 "key1=value 1 # comment\n"
626 "key2=value=2\n"
627 "key3=value 3\n"
628 "\n"
629 "[scope 2]\n"
630 "key4=value 4\n"
631 "#key5=value 5\n"
632 "key6=value 6\n"s,
633 readFile(iniFilePath));
634
635 // fail by exceeding max size
636 CPPUNIT_ASSERT_THROW(readFile(iniFilePath, 10), std::ios_base::failure);
637
638 // handle UTF-8 in path and file contents correctly via NativeFileStream
639#if !defined(PLATFORM_WINDOWS) || defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
640 CPPUNIT_ASSERT_EQUAL("file with non-ASCII character 'ä' in its name\n"s, readFile(testFilePath("täst.txt")));
641#endif
642}
643
648{
649 const string path(workingCopyPath("test.ini", WorkingCopyMode::NoCopy));
650 writeFile(path, "some contents");
651 CPPUNIT_ASSERT_EQUAL("some contents"s, readFile(path));
652}
653
658{
659 stringstream ss1;
661 ss1 << EscapeCodes::Phrases::Error << "some error" << EscapeCodes::Phrases::End;
662 ss1 << EscapeCodes::Phrases::Warning << "some warning" << EscapeCodes::Phrases::End;
663 ss1 << EscapeCodes::Phrases::Info << "some info" << EscapeCodes::Phrases::End;
664 ss1 << EscapeCodes::Phrases::ErrorMessage << "Arch-style error" << EscapeCodes::Phrases::End;
665 ss1 << EscapeCodes::Phrases::WarningMessage << "Arch-style warning" << EscapeCodes::Phrases::End;
666 ss1 << EscapeCodes::Phrases::PlainMessage << "Arch-style message" << EscapeCodes::Phrases::End;
667 ss1 << EscapeCodes::Phrases::SuccessMessage << "Arch-style success" << EscapeCodes::Phrases::End;
668 ss1 << EscapeCodes::Phrases::SubMessage << "Arch-style sub-message" << EscapeCodes::Phrases::End;
669 ss1 << EscapeCodes::color(EscapeCodes::Color::Blue, EscapeCodes::Color::Red, EscapeCodes::TextAttribute::Blink)
670 << "blue, blinking text on red background" << EscapeCodes::TextAttribute::Reset << '\n';
671 cout << "\noutput for formatting with ANSI escape codes:\n" << ss1.str() << "---------------------------------------------\n";
672 CPPUNIT_ASSERT_EQUAL("\033[1;31mError: \033[0m\033[1msome error\033[0m\n"
673 "\033[1;33mWarning: \033[0m\033[1msome warning\033[0m\n"
674 "\033[1;34mInfo: \033[0m\033[1msome info\033[0m\n"
675 "\033[1;31m==> ERROR: \033[0m\033[1mArch-style error\033[0m\n"
676 "\033[1;33m==> WARNING: \033[0m\033[1mArch-style warning\033[0m\n"
677 " \033[0m\033[1mArch-style message\033[0m\n"
678 "\033[1;32m==> \033[0m\033[1mArch-style success\033[0m\n"
679 "\033[1;32m -> \033[0m\033[1mArch-style sub-message\033[0m\n"
680 "\033[5;34;41mblue, blinking text on red background\033[0m\n"s,
681 ss1.str());
682
683 stringstream ss2;
684 EscapeCodes::enabled = false;
685 ss2 << EscapeCodes::Phrases::Info << "some info" << EscapeCodes::Phrases::End;
686 CPPUNIT_ASSERT_EQUAL("Info: some info\n"s, ss2.str());
687}
688
689#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
693void IoTests::testNativeFileStream()
694{
695 return;
696 // open file by path
697 const auto txtFilePath(workingCopyPath("täst.txt"));
698 NativeFileStream fileStream;
699 fileStream.exceptions(ios_base::badbit | ios_base::failbit);
700 CPPUNIT_ASSERT(!fileStream.is_open());
701 fileStream.open(txtFilePath, ios_base::in);
702 CPPUNIT_ASSERT(fileStream.is_open());
703#if defined(PLATFORM_WINDOWS) && defined(CPP_UTILITIES_USE_BOOST_IOSTREAMS)
704 CPPUNIT_ASSERT(fileStream.fileHandle() != nullptr);
705#else
706 CPPUNIT_ASSERT(fileStream.fileDescriptor() != -1);
707#endif
708 CPPUNIT_ASSERT_EQUAL(static_cast<char>(fileStream.get()), 'f');
709 fileStream.seekg(0, ios_base::end);
710 CPPUNIT_ASSERT_EQUAL(fileStream.tellg(), static_cast<NativeFileStream::pos_type>(47));
711 fileStream.close();
712 CPPUNIT_ASSERT(!fileStream.is_open());
713 try {
714 fileStream.open("non existing file", ios_base::in | ios_base::out | ios_base::binary);
715 CPPUNIT_FAIL("expected exception");
716 } catch (const std::ios_base::failure &failure) {
717#ifdef PLATFORM_WINDOWS
718#ifdef CPP_UTILITIES_USE_BOOST_IOSTREAMS
719 TESTUTILS_ASSERT_LIKE("expected error with some message", "CreateFileW failed: .+", failure.what());
720#else
721 TESTUTILS_ASSERT_LIKE("expected error with some message", "_wopen failed: .+", failure.what());
722#endif
723#else
724 TESTUTILS_ASSERT_LIKE("expected error with some message", "open failed: .+", failure.what());
725#endif
726 }
727 fileStream.clear();
728
729 // open file from file descriptor
730#ifndef PLATFORM_WINDOWS
731 auto readWriteFileDescriptor = open(txtFilePath.data(), O_RDWR);
732 CPPUNIT_ASSERT(readWriteFileDescriptor);
733 fileStream.open(readWriteFileDescriptor, ios_base::in | ios_base::out | ios_base::binary);
734 CPPUNIT_ASSERT(fileStream.is_open());
735 CPPUNIT_ASSERT_EQUAL(static_cast<char>(fileStream.get()), 'f');
736 fileStream.seekg(0, ios_base::end);
737 CPPUNIT_ASSERT_EQUAL(fileStream.tellg(), static_cast<NativeFileStream::pos_type>(47));
738 fileStream.flush();
739 fileStream.close();
740 CPPUNIT_ASSERT(!fileStream.is_open());
741#endif
742 try {
743 fileStream.open(-1, ios_base::in | ios_base::out | ios_base::binary);
744 fileStream.get();
745 CPPUNIT_FAIL("expected exception");
746 } catch (const std::ios_base::failure &failure) {
747#ifndef PLATFORM_WINDOWS
749 "expected error message", "(basic_ios::clear|failed reading: Bad file descriptor): iostream error"s, string(failure.what()));
750#else
751 CPP_UTILITIES_UNUSED(failure)
752#endif
753 }
754 fileStream.clear();
755
756 // append + write file via path
757 NativeFileStream fileStream2;
758 fileStream2.exceptions(ios_base::failbit | ios_base::badbit);
759 fileStream2.open(txtFilePath, ios_base::in | ios_base::out | ios_base::app);
760 CPPUNIT_ASSERT(fileStream2.is_open());
761 fileStream2 << "foo";
762 fileStream2.flush();
763 fileStream2.close();
764 CPPUNIT_ASSERT(!fileStream2.is_open());
765 CPPUNIT_ASSERT_EQUAL("file with non-ASCII character 'ä' in its name\nfoo"s, readFile(txtFilePath, 50));
766
767 // truncate + write file via path
768 fileStream2.open(txtFilePath, ios_base::out | ios_base::trunc);
769 CPPUNIT_ASSERT(fileStream2.is_open());
770 fileStream2 << "bar";
771 fileStream2.close();
772 CPPUNIT_ASSERT(!fileStream2.is_open());
773 CPPUNIT_ASSERT_EQUAL("bar"s, readFile(txtFilePath, 4));
774
775 // append + write via file descriptor from file handle
776#ifdef PLATFORM_WINDOWS
777 const auto wideTxtFilePath = NativeFileStream::makeWidePath(txtFilePath);
778 const auto appendFileHandle = _wfopen(wideTxtFilePath.get(), L"a+");
779#else
780 const auto appendFileHandle = fopen(txtFilePath.data(), "a");
781#endif
782 CPPUNIT_ASSERT(appendFileHandle);
783 fileStream2.open(fileno(appendFileHandle), ios_base::out | ios_base::app);
784 CPPUNIT_ASSERT(fileStream2.is_open());
785 fileStream2 << "foo";
786 fileStream2.close();
787 CPPUNIT_ASSERT(!fileStream2.is_open());
788 CPPUNIT_ASSERT_EQUAL("barfoo"s, readFile(txtFilePath, 7));
789}
790#endif
791
792#ifdef CPP_UTILITIES_USE_LIBARCHIVE
793void IoTests::testExtractingArchive()
794{
795 const auto archivePath = testFilePath("archive-test.zip");
796 const auto archiveContents = extractFiles(archivePath);
797 const auto &root = archiveContents.at(std::string());
798 const auto &subdir = archiveContents.at("subdir");
799 const auto &subsubdir = archiveContents.at("subdir/foo");
800
801 CPPUNIT_ASSERT_EQUAL(1_st, root.size());
802 CPPUNIT_ASSERT_EQUAL("test.txt"s, root.at(0).name);
803 CPPUNIT_ASSERT_EQUAL(ArchiveFileType::Regular, root.at(0).type);
804 CPPUNIT_ASSERT_EQUAL(DateTime::fromDate(1970, 1, 1), root.at(0).creationTime);
805 CPPUNIT_ASSERT_EQUAL(DateTime::fromDateAndTime(2024, 3, 3, 19, 46, 42), root.at(0).modificationTime);
806 CPPUNIT_ASSERT_EQUAL("testfile\n"s, root.at(0).content);
807
808 CPPUNIT_ASSERT_EQUAL(1_st, subdir.size());
809 CPPUNIT_ASSERT_EQUAL("nested-testfile.txt"s, subdir.at(0).name);
810 CPPUNIT_ASSERT_EQUAL(ArchiveFileType::Regular, subdir.at(0).type);
811 CPPUNIT_ASSERT_EQUAL("some file\n"s, subdir.at(0).content);
812
813 CPPUNIT_ASSERT_EQUAL(1_st, subsubdir.size());
814 CPPUNIT_ASSERT_EQUAL("bar"s, subsubdir.at(0).name);
815 CPPUNIT_ASSERT_EQUAL(ArchiveFileType::Regular, subsubdir.at(0).type);
816 CPPUNIT_ASSERT_EQUAL(std::string(), subsubdir.at(0).content);
817}
818#endif
#define CPP_UTILITIES_UNUSED(x)
Prevents warnings about unused variables.
Definition global.h:92
Reads primitive data types from a std::istream.
std::int64_t readInt64LE()
Reads a 64-bit little endian signed integer from the current stream and advances the current position...
float readFloat32BE()
Reads a 32-bit big endian floating point value from the current stream and advances the current posit...
std::string readTerminatedString(std::uint8_t termination=0)
Reads a terminated string from the current stream.
std::string readString(std::size_t length)
Reads a string from the current stream of the given length from the stream and advances the current p...
std::uint64_t readUInt64LE()
Reads a 64-bit little endian unsigned integer from the current stream and advances the current positi...
std::string readLengthPrefixedString()
Reads a length prefixed string from the current stream.
std::int64_t readInt40LE()
Reads a 40-bit little endian signed integer from the current stream and advances the current position...
std::int32_t readInt32BE()
Reads a 32-bit big endian signed integer from the current stream and advances the current position of...
std::int32_t readInt24LE()
Reads a 24-bit little endian signed integer from the current stream and advances the current position...
std::uint32_t readUInt32LE()
Reads a 32-bit little endian unsigned integer from the current stream and advances the current positi...
std::uint16_t readUInt16LE()
Reads a 16-bit little endian unsigned integer from the current stream and advances the current positi...
void setStream(std::istream *stream, bool giveOwnership=false)
Assigns the stream the reader will read from when calling one of the read-methods.
std::uint64_t readUInt56BE()
Reads a 56-bit big endian unsigned integer from the current stream and advances the current position ...
bool readBool()
Reads a boolean value from the current stream and advances the current position of the stream by one ...
std::uint32_t readUInt24BE()
Reads a 24-bit big endian unsigned integer from the current stream and advances the current position ...
std::int32_t readInt32LE()
Reads a 32-bit little endian signed integer from the current stream and advances the current position...
const std::istream * stream() const
Returns a pointer to the stream the reader will read from when calling one of the read-methods.
std::int16_t readInt16BE()
Reads a 16-bit big endian signed integer from the current stream and advances the current position of...
std::uint32_t readUInt24LE()
Reads a 24-bit little endian unsigned integer from the current stream and advances the current positi...
std::int64_t readInt56LE()
Reads a 56-bit little endian signed integer from the current stream and advances the current position...
std::istream::pos_type readRemainingBytes()
Returns the number of remaining bytes in the stream from the current offset.
std::uint64_t readUInt64BE()
Reads a 64-bit big endian unsigned integer from the current stream and advances the current position ...
bool hasOwnership() const
Returns whether the reader takes ownership over the assigned stream.
std::uint64_t readUInt40LE()
Reads a 40-bit little endian unsigned integer from the current stream and advances the current positi...
std::uint64_t readUInt56LE()
Reads a 56-bit little endian unsigned integer from the current stream and advances the current positi...
std::uint16_t readUInt16BE()
Reads a 16-bit big endian unsigned integer from the current stream and advances the current position ...
std::int32_t readInt24BE()
Reads a 24-bit big endian signed integer from the current stream and advances the current position of...
std::int64_t readInt40BE()
Reads a 40-bit big endian signed integer from the current stream and advances the current position of...
double readFloat64BE()
Reads a 64-bit big endian floating point value from the current stream and advances the current posit...
std::uint32_t readUInt32BE()
Reads a 32-bit big endian unsigned integer from the current stream and advances the current position ...
std::int64_t readInt56BE()
Reads a 56-bit big endian signed integer from the current stream and advances the current position of...
std::int16_t readInt16LE()
Reads a 16-bit little endian signed integer from the current stream and advances the current position...
double readFloat64LE()
Reads a 64-bit little endian floating point value from the current stream and advances the current po...
std::int64_t readInt64BE()
Reads a 64-bit big endian signed integer from the current stream and advances the current position of...
std::istream::pos_type readStreamsize()
Returns the size of the assigned stream.
std::uint64_t readUInt40BE()
Reads a 40-bit big endian unsigned integer from the current stream and advances the current position ...
float readFloat32LE()
Reads a 32-bit little endian floating point value from the current stream and advances the current po...
std::uint8_t readByte()
Reads a single byte/unsigned character from the current stream and advances the current position of t...
Writes primitive data types to a std::ostream.
void writeFloat32LE(float value)
Writes a 32-bit little endian floating point value to the current stream and advances the current pos...
void writeUInt40BE(std::uint64_t value)
Writes a 40-bit big endian unsigned integer to the current stream and advances the current position o...
void writeUInt64LE(std::uint64_t value)
Writes a 64-bit little endian unsigned integer to the current stream and advances the current positio...
void writeInt40LE(std::int64_t value)
Writes a 40-bit big endian signed integer to the current stream and advances the current position of ...
void writeUInt40LE(std::uint64_t value)
Writes a 40-bit big endian unsigned integer to the current stream and advances the current position o...
void writeInt64BE(std::int64_t value)
Writes a 64-bit big endian signed integer to the current stream and advances the current position of ...
void writeInt32LE(std::int32_t value)
Writes a 32-bit little endian signed integer to the current stream and advances the current position ...
bool hasOwnership() const
Returns whether the writer takes ownership over the assigned stream.
void writeUInt24LE(std::uint32_t value)
Writes a 24-bit little endian unsigned integer to the current stream and advances the current positio...
void writeFloat32BE(float value)
Writes a 32-bit big endian floating point value to the current stream and advances the current positi...
void writeInt24BE(std::int32_t value)
Writes a 24-bit big endian signed integer to the current stream and advances the current position of ...
void setStream(std::ostream *stream, bool giveOwnership=false)
Assigns the stream the writer will write to when calling one of the write-methods.
void writeUInt56BE(std::uint64_t value)
Writes a 56-bit big endian unsigned integer to the current stream and advances the current position o...
void writeUInt32BE(std::uint32_t value)
Writes a 32-bit big endian unsigned integer to the current stream and advances the current position o...
void writeFloat64BE(double value)
Writes a 64-bit big endian floating point value to the current stream and advances the current positi...
void writeFloat64LE(double value)
Writes a 64-bit little endian floating point value to the current stream and advances the current pos...
void writeString(const std::string &value)
Writes a string to the current stream and advances the current position of the stream by the length o...
void writeUInt56LE(std::uint64_t value)
Writes a 56-bit big endian unsigned integer to the current stream and advances the current position o...
void writeInt56LE(std::int64_t value)
Writes a 56-bit big endian signed integer to the current stream and advances the current position of ...
const std::ostream * stream() const
Returns a pointer to the stream the writer will write to when calling one of the write-methods.
void writeUInt16BE(std::uint16_t value)
Writes a 16-bit big endian unsigned integer to the current stream and advances the current position o...
void writeUInt64BE(std::uint64_t value)
Writes a 64-bit big endian unsigned integer to the current stream and advances the current position o...
void writeInt56BE(std::int64_t value)
Writes a 56-bit big endian signed integer to the current stream and advances the current position of ...
void writeInt16LE(std::int16_t value)
Writes a 16-bit little endian signed integer to the current stream and advances the current position ...
void writeUInt32LE(std::uint32_t value)
Writes a 32-bit little endian unsigned integer to the current stream and advances the current positio...
void writeUInt16LE(std::uint16_t value)
Writes a 16-bit little endian unsigned integer to the current stream and advances the current positio...
void writeInt16BE(std::int16_t value)
Writes a 16-bit big endian signed integer to the current stream and advances the current position of ...
void writeLengthPrefixedString(const std::string &value)
Writes the length of a string and the string itself to the current stream.
void writeInt24LE(std::int32_t value)
Writes a 24-bit little endian signed integer to the current stream and advances the current position ...
void writeUInt24BE(std::uint32_t value)
Writes a 24-bit big endian unsigned integer to the current stream and advances the current position o...
void writeTerminatedString(const std::string &value)
Writes a terminated string to the current stream and advances the current position of the stream by t...
void writeInt64LE(std::int64_t value)
Writes a 64-bit little endian signed integer to the current stream and advances the current position ...
void writeInt32BE(std::int32_t value)
Writes a 32-bit big endian signed integer to the current stream and advances the current position of ...
void writeInt40BE(std::int64_t value)
Writes a 40-bit big endian signed integer to the current stream and advances the current position of ...
void writeBool(bool value)
Writes a boolean value to the current stream and advances the current position of the stream by one b...
The BitReader class provides bitwise reading of buffered data.
Definition bitreader.h:13
void reset(const char *buffer, std::size_t bufferSize)
Resets the reader.
Definition bitreader.h:148
std::uint8_t readBit()
Reads the one bit from the buffer advancing the current position by one bit.
Definition bitreader.h:89
void skipBits(std::size_t bitCount)
Skips the specified number of bits without reading it.
Definition bitreader.cpp:43
void align()
Re-establishes alignment.
Definition bitreader.h:171
std::size_t bitsAvailable()
Returns the number of bits which are still available to read.
Definition bitreader.h:137
intType readSignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (signed).
Definition bitreader.h:119
intType readUnsignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (unsigned).
Definition bitreader.h:102
intType readBits(std::uint8_t bitCount)
Reads the specified number of bits from the buffer advancing the current position by bitCount bits.
Definition bitreader.h:67
intType showBits(std::uint8_t bitCount)
Reads the specified number of bits from the buffer without advancing the current position.
Definition bitreader.h:128
The BufferSearch struct invokes a callback if an initially given search term occurs in consecutively ...
The ConversionException class is thrown by the various conversion functions of this library when a co...
The CopyHelper class helps to copy bytes from one stream to another.
Definition copy.h:30
static DateTime fromDateAndTime(int year=1, int month=1, int day=1, int hour=0, int minute=0, int second=0, double millisecond=0.0)
Constructs a DateTime to the specified year, month, day, hour, minute, second and millisecond.
Definition datetime.h:230
static DateTime fromDate(int year=1, int month=1, int day=1)
Constructs a DateTime to the specified year, month, and day.
Definition datetime.h:211
The IniFile class allows parsing and writing INI files.
Definition inifile.h:16
void parse(std::istream &inputStream)
Parses all data from the specified inputStream.
Definition inifile.cpp:40
ScopeList & data()
Returns the data of the file.
Definition inifile.h:46
void make(std::ostream &outputStream)
Write the current data to the specified outputStream.
Definition inifile.cpp:159
The IoTests class tests classes and functions provided by the files inside the io directory.
Definition iotests.cpp:68
void testBufferSearch()
Tests the BufferSearch class.
Definition iotests.cpp:324
void testBinaryReader()
Tests the most important methods of the BinaryReader.
Definition iotests.cpp:127
void testAnsiEscapeCodes()
Tests formatting functions of CppUtilities::EscapeCodes namespace.
Definition iotests.cpp:657
void testIniFile()
Tests IniFile.
Definition iotests.cpp:392
void testBitReader()
Tests the BitReader class.
Definition iotests.cpp:297
void testBinaryWriter()
Tests the most important methods of the BinaryWriter.
Definition iotests.cpp:193
void testCopyWithNativeFileStream()
Tests CopyHelper in combination with NativeFileStream.
Definition iotests.cpp:547
void setUp() override
Definition iotests.cpp:116
void testCopy()
Tests CopyHelper.
Definition iotests.cpp:520
void testPathUtilities()
Tests fileName() and removeInvalidChars().
Definition iotests.cpp:358
void tearDown() override
Definition iotests.cpp:120
void testWriteFile()
Tests writeFile().
Definition iotests.cpp:647
void testReadFile()
Tests readFile().
Definition iotests.cpp:617
void testAdvancedIniFile()
Tests AdvancedIniFile.
Definition iotests.cpp:433
CPPUNIT_TEST_SUITE_REGISTRATION(IoTests)
constexpr auto color(Color foreground, Color background, TextAttribute displayAttribute=TextAttribute::Reset)
CPP_UTILITIES_EXPORT bool enabled
Controls whether the functions inside the EscapeCodes namespace actually make use of escape codes.
Contains literals to ease asserting with CPPUNIT_ASSERT_EQUAL.
Definition testutils.h:368
Contains all utilities provides by the c++utilities library.
CPP_UTILITIES_EXPORT std::string readFile(const std::string &path, std::string::size_type maxSize=std::string::npos)
Reads all contents of the specified file in a single call.
Definition misc.cpp:17
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::testFilePath().
Definition testutils.h:161
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPath().
Definition testutils.h:179
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
CPP_UTILITIES_EXPORT FileMap extractFiles(std::string_view archivePath, const FilePredicate &isFileRelevant=FilePredicate())
Extracts the specified archive.
Definition archive.cpp:259
CPP_UTILITIES_EXPORT std::ostream & operator<<(std::ostream &out, Indentation indentation)
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
std::fstream NativeFileStream
StringType argsToString(Args &&...args)
AsHexNumber< T > asHexNumber(const T &value)
Wraps a value to be printed using the hex system in the error case when asserted with cppunit (or sim...
Definition testutils.h:258
CPP_UTILITIES_EXPORT void writeFile(std::string_view path, std::string_view contents)
Writes all contents to the specified file in a single call.
Definition misc.cpp:58
CPP_UTILITIES_EXPORT void removeInvalidChars(std::string &fileName)
Removes invalid characters from the specified fileName.
Definition path.cpp:75
CPP_UTILITIES_EXPORT std::string fileName(const std::string &path)
Returns the file name and extension of the specified path string.
Definition path.cpp:17
NativePathStringView makeNativePath(PathStringView path)
Returns path in the platform's native encoding.
Definition path.h:82
CPP_UTILITIES_EXPORT std::string directory(const std::string &path)
Returns the directory of the specified path string (including trailing slash).
Definition path.cpp:25
STL namespace.
The AdvancedIniFile class allows parsing and writing INI files.
Definition inifile.h:79
void make(std::ostream &outputStream, IniFileMakeOptions options=IniFileMakeOptions::None)
Write the current data to the specified outputStream.
Definition inifile.cpp:412
std::optional< FieldList::iterator > findField(std::string_view sectionName, std::string_view key)
Returns an iterator to the first field within the first section with matching sectionName and key.
Definition inifile.h:170
void parse(std::istream &inputStream, IniFileParseOptions options=IniFileParseOptions::None)
Parses all data from the specified inputStream.
Definition inifile.cpp:217
SectionList::iterator sectionEnd()
Returns an iterator that points one past the last section.
Definition inifile.h:154
SectionList::iterator findSection(std::string_view sectionName)
Returns an iterator to the first section with the name sectionName.
Definition inifile.h:122
#define TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, regexFlags, actualString)
Asserts whether the specified string matches the specified regex.
Definition testutils.h:328
#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString)
Asserts whether the specified string matches the specified regex.
Definition testutils.h:338
constexpr int i