8std::ostream &
operator<<(std::ostream &out,
const std::wstring &s)
11#ifdef CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN
16 (
reinterpret_cast<const char *
>(s.data()), s.size() * (
sizeof(std::wstring::value_type) /
sizeof(
char)));
17 out.write(utf8.first.get(),
static_cast<std::streamsize
>(utf8.second));
35#include <cppunit/TestFixture.h>
36#include <cppunit/extensions/HelperMacros.h>
43#ifdef PLATFORM_WINDOWS
55using namespace CPPUNIT_NS;
74#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
75 CPPUNIT_TEST(testNativeFileStream);
77 CPPUNIT_TEST_SUITE_END();
80 void setUp()
override;
95#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
96 void testNativeFileStream();
117 testFile.exceptions(ios_base::failbit | ios_base::badbit);
118 testFile.open(
testFilePath(
"some_data"), ios_base::in | ios_base::binary);
120 CPPUNIT_ASSERT_EQUAL(
static_cast<istream::pos_type
>(398), reader.
readStreamsize());
121 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0x0102u), reader.
readUInt16LE());
122 CPPUNIT_ASSERT_EQUAL(
static_cast<istream::pos_type
>(396), reader.
readRemainingBytes());
123 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0x0102u), reader.
readUInt16BE());
126 CPPUNIT_ASSERT_EQUAL(0x01020304u, reader.
readUInt32LE());
127 CPPUNIT_ASSERT_EQUAL(0x01020304u, reader.
readUInt32BE());
128 CPPUNIT_ASSERT_EQUAL(0x0102030405u, reader.
readUInt40LE());
129 CPPUNIT_ASSERT_EQUAL(0x0102030405u, reader.
readUInt40BE());
130 CPPUNIT_ASSERT_EQUAL(0x01020304050607u, reader.
readUInt56LE());
131 CPPUNIT_ASSERT_EQUAL(0x01020304050607u, reader.
readUInt56BE());
132 CPPUNIT_ASSERT_EQUAL(0x0102030405060708u, reader.
readUInt64LE());
133 CPPUNIT_ASSERT_EQUAL(0x0102030405060708u, reader.
readUInt64BE());
135 CPPUNIT_ASSERT_EQUAL(reader.
readInt16LE(),
static_cast<std::int16_t
>(0x0102));
136 CPPUNIT_ASSERT_EQUAL(reader.
readInt16BE(),
static_cast<std::int16_t
>(0x0102));
137 CPPUNIT_ASSERT_EQUAL(0x010203, reader.
readInt24LE());
138 CPPUNIT_ASSERT_EQUAL(0x010203, reader.
readInt24BE());
139 CPPUNIT_ASSERT_EQUAL(0x01020304, reader.
readInt32LE());
140 CPPUNIT_ASSERT_EQUAL(0x01020304, reader.
readInt32BE());
141 CPPUNIT_ASSERT_EQUAL(0x0102030405, reader.
readInt40LE());
142 CPPUNIT_ASSERT_EQUAL(0x0102030405, reader.
readInt40BE());
143 CPPUNIT_ASSERT_EQUAL(0x01020304050607, reader.
readInt56LE());
144 CPPUNIT_ASSERT_EQUAL(0x01020304050607, reader.
readInt56BE());
145 CPPUNIT_ASSERT_EQUAL(0x0102030405060708, reader.
readInt64LE());
146 CPPUNIT_ASSERT_EQUAL(0x0102030405060708, reader.
readInt64BE());
151 CPPUNIT_ASSERT_EQUAL(
false, reader.
readBool());
152 CPPUNIT_ASSERT_EQUAL(
true, reader.
readBool());
153 CPPUNIT_ASSERT_EQUAL(
"abc"s, reader.
readString(3));
155 CPPUNIT_ASSERT_EQUAL(
"01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
156 "23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
157 "45678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"
158 "678901234567890123456789"s,
161 testFile.seekg(-4, ios_base::cur);
164 CPPUNIT_ASSERT_MESSAGE(
"pos in stream not advanced on conversion error", reader.
readByte() == 0);
183 testFile.exceptions(ios_base::failbit | ios_base::badbit);
184 testFile.open(
testFilePath(
"some_data"), ios_base::in | ios_base::binary);
187 stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary);
188 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
190#if defined(__GLIBCXX__) && !defined(_LIBCPP_VERSION)
191#define USE_RDBUF_DIRECTLY
192 outputStream.rdbuf()->pubsetbuf(testData,
sizeof(testData));
210#ifndef USE_RDBUF_DIRECTLY
211 outputStream.seekg(0);
212 outputStream.read(testData, 58);
216 for (
char c : testData) {
217 const auto pos =
static_cast<std::size_t
>(testFile.tellg());
222 testFile.read(&expected, 1);
226 outputStream.seekp(0);
249 writer.
writeLengthPrefixedString(
"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
250 "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
251 "234567890123456789012345678901234567890123456789012345678901234567890123456789");
254#ifndef USE_RDBUF_DIRECTLY
255 outputStream.seekg(0);
256 outputStream.read(testData, 58);
260 for (
char c : testData) {
261 const auto pos =
static_cast<std::size_t
>(testFile.tellg());
266 testFile.read(&expected, 1);
285 const std::uint8_t testData[] = { 0x81, 0x90, 0x3C, 0x44, 0x28, 0x00, 0x44, 0x10, 0x20, 0xFF, 0xFA };
286 BitReader reader(
reinterpret_cast<const char *
>(testData),
sizeof(testData));
287 CPPUNIT_ASSERT(reader.
readBit() == 1);
289 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(3), reader.
showBits<std::uint8_t>(2));
290 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(3), reader.
readBits<std::uint8_t>(2));
291 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint32_t
>(0x103C4428 << 1), reader.
readBits<std::uint32_t>(32));
293 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0x44), reader.
readBits<std::uint8_t>(8));
296 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0), reader.
readBit());
297 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0), reader.
readBit());
300 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0xA), reader.
readBits<std::uint8_t>(4));
301 CPPUNIT_ASSERT_THROW(reader.
readBit(), std::ios_base::failure);
302 CPPUNIT_ASSERT_THROW(reader.
skipBits(1), std::ios_base::failure);
303 reader.
reset(
reinterpret_cast<const char *
>(testData),
sizeof(testData));
304 CPPUNIT_ASSERT_EQUAL(
static_cast<std::size_t
>(8 *
sizeof(testData)), reader.
bitsAvailable());
313 auto expectedResult = std::string();
314 auto hasResult =
false;
316 CPPUNIT_ASSERT_EQUAL(expectedResult, result);
317 CPPUNIT_ASSERT_MESSAGE(
"callback only invoked once", !hasResult);
322 char buffer[30] = { 0 };
324 CPPUNIT_ASSERT(!hasResult);
325 std::strcpy(buffer,
"Starting Updated");
326 bs(std::string_view(buffer, 16));
327 CPPUNIT_ASSERT(!hasResult);
328 std::strcpy(buffer,
" version: some ");
330 CPPUNIT_ASSERT(!hasResult);
331 expectedResult =
"some version number";
332 std::strcpy(buffer,
"version number\tmore chars");
334 CPPUNIT_ASSERT(hasResult);
336 std::strcpy(buffer,
"... Starting build ...");
338 CPPUNIT_ASSERT(!hasResult);
346 CPPUNIT_ASSERT_EQUAL(
"libc++utilities.so"s,
fileName(
"C:\\libs\\libc++utilities.so"));
347 CPPUNIT_ASSERT_EQUAL(
"libc++utilities.so"s,
fileName(
"C:\\libs/libc++utilities.so"));
348 CPPUNIT_ASSERT_EQUAL(
"libc++utilities.so"s,
fileName(
"/usr/lib/libc++utilities.so"));
349 CPPUNIT_ASSERT_EQUAL(
"libc++utilities.so"s,
fileName(
"libc++utilities.so"));
350 CPPUNIT_ASSERT_EQUAL(
"/usr/lib/"s,
directory(
"/usr/lib/libc++utilities.so"));
351 CPPUNIT_ASSERT_EQUAL(
string(),
directory(
"libc++utilities.so"));
352 CPPUNIT_ASSERT_EQUAL(
"C:\\libs\\"s,
directory(
"C:\\libs\\libc++utilities.so"));
353 CPPUNIT_ASSERT_EQUAL(
"C:\\libs/"s,
directory(
"C:\\libs/libc++utilities.so"));
354 string invalidPath(
"lib/c++uti*lities.so?");
356 CPPUNIT_ASSERT(invalidPath ==
"libc++utilities.so");
358 const auto input = std::string_view(
"some/path/täst");
359 const auto expected = input;
361#ifdef PLATFORM_WINDOWS
362 const auto outputAsUtf8 =
convertUtf16LEToUtf8(
reinterpret_cast<const char *
>(output.data()), output.size() * 2);
363 const auto outputView = std::string_view(outputAsUtf8.first.get(), outputAsUtf8.second);
364 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"makeNativePath()", expected, outputView);
366 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"makeNativePath()", expected, output);
377 inputFile.exceptions(ios_base::failbit | ios_base::badbit);
381 ini.
parse(inputFile);
382 const auto globalScope = ini.
data().at(0);
383 const auto scope1 = ini.
data().at(1);
384 const auto scope2 = ini.
data().at(2);
385 CPPUNIT_ASSERT(globalScope.first.empty());
386 CPPUNIT_ASSERT(globalScope.second.find(
"key0") != globalScope.second.cend());
387 CPPUNIT_ASSERT(globalScope.second.find(
"key0")->second ==
"value 0");
388 CPPUNIT_ASSERT(globalScope.second.find(
"key1") == globalScope.second.cend());
389 CPPUNIT_ASSERT(scope1.first ==
"scope 1");
390 CPPUNIT_ASSERT(scope1.second.find(
"key1") != scope1.second.cend());
391 CPPUNIT_ASSERT(scope1.second.find(
"key1")->second ==
"value 1");
392 CPPUNIT_ASSERT(scope1.second.find(
"key2") != scope1.second.cend());
393 CPPUNIT_ASSERT(scope1.second.find(
"key2")->second ==
"value=2");
394 CPPUNIT_ASSERT(scope2.first ==
"scope 2");
395 CPPUNIT_ASSERT(scope2.second.find(
"key5") == scope2.second.cend());
399 outputFile.exceptions(ios_base::failbit | ios_base::badbit);
400 outputFile.open(
workingCopyPath(
"output.ini", WorkingCopyMode::NoCopy), ios_base::out | ios_base::trunc);
401 ini.
make(outputFile);
405 outputFile.open(
workingCopyPath(
"output.ini", WorkingCopyMode::NoCopy), ios_base::in);
407 ini2.
parse(outputFile);
408 CPPUNIT_ASSERT(ini.
data() == ini2.
data());
418 inputFile.exceptions(ios_base::failbit | ios_base::badbit);
419 inputFile.open(
testFilePath(
"pacman.conf"), ios_base::in);
423 ini.
parse(inputFile);
426 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"5 scopes (taking implicit empty section at the end into account)", 5_st, ini.
sections.size());
429#if !defined(PLATFORM_WINDOWS) || defined(PLATFORM_MINGW) || defined(PLATFORM_CYGWIN)
430#define STD_REGEX_WORKS
432 "comment block before section",
"# Based on.*\n.*# GENERAL OPTIONS\n#\n"s, std::regex::extended, options->precedingCommentBlock);
434 CPPUNIT_ASSERT_EQUAL(7_st, options->fields.size());
435 CPPUNIT_ASSERT_EQUAL(
"HoldPkg"s, options->fields[0].key);
436 CPPUNIT_ASSERT_EQUAL(
"pacman glibc"s, options->fields[0].value);
437 CPPUNIT_ASSERT_MESSAGE(
"value present", options->fields[0].flags & IniFileFieldFlags::HasValue);
438#ifdef STD_REGEX_WORKS
440 "# The following paths are.*\n.*#HookDir = /etc/pacman\\.d/hooks/\n"s, std::regex::extended, options->fields[0].precedingCommentBlock);
442 CPPUNIT_ASSERT_EQUAL(
""s, options->fields[0].followingInlineComment);
443 CPPUNIT_ASSERT_EQUAL(
"Foo"s, options->fields[1].key);
444 CPPUNIT_ASSERT_EQUAL(
"bar"s, options->fields[1].value);
445 CPPUNIT_ASSERT_MESSAGE(
"value present", options->fields[1].flags & IniFileFieldFlags::HasValue);
446#ifdef STD_REGEX_WORKS
447 TESTUTILS_ASSERT_LIKE_FLAGS(
"comment block between fields",
"#XferCommand.*\n.*#CleanMethod = KeepInstalled\n"s, std::regex::extended,
448 options->fields[1].precedingCommentBlock);
450 CPPUNIT_ASSERT_EQUAL(
"# inline comment"s, options->fields[1].followingInlineComment);
451 CPPUNIT_ASSERT_EQUAL(
"CheckSpace"s, options->fields[3].key);
452 CPPUNIT_ASSERT_EQUAL(
""s, options->fields[3].value);
453 CPPUNIT_ASSERT_MESSAGE(
"no value present", !(options->fields[3].flags & IniFileFieldFlags::HasValue));
454#ifdef STD_REGEX_WORKS
455 TESTUTILS_ASSERT_LIKE_FLAGS(
"empty lines in comments preserved",
"\n# Pacman.*\n.*\n\n#NoUpgrade =\n.*#TotalDownload\n"s, std::regex::extended,
456 options->fields[3].precedingCommentBlock);
458 CPPUNIT_ASSERT_EQUAL(
""s, options->fields[3].followingInlineComment);
459 auto extraScope = ini.
findSection(options,
"extra");
460 CPPUNIT_ASSERT(extraScope != ini.
sectionEnd());
461 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"comment block which is only an empty line",
"\n"s, extraScope->precedingCommentBlock);
462 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"inline comment after scope",
"# an inline comment after a scope name"s, extraScope->followingInlineComment);
463 CPPUNIT_ASSERT_EQUAL(1_st, extraScope->fields.size());
464 CPPUNIT_ASSERT(ini.
sections.back().flags & IniFileSectionFlags::Implicit);
465#ifdef STD_REGEX_WORKS
466 TESTUTILS_ASSERT_LIKE_FLAGS(
"comment block after last field present in implicitly added last scope",
"\n# If you.*\n.*custompkgs\n"s,
467 std::regex::extended, ini.
sections.back().precedingCommentBlock);
471 const auto *
const constIniFile = &ini;
472 auto includeField = constIniFile->
findField(
"extra",
"Include");
473 CPPUNIT_ASSERT(includeField.has_value());
474 CPPUNIT_ASSERT_EQUAL(
"Include"s, includeField.value()->key);
475 CPPUNIT_ASSERT_EQUAL(
"/etc/pacman.d/mirrorlist"s, includeField.value()->value);
476 CPPUNIT_ASSERT_MESSAGE(
"field not present", !constIniFile->findField(
"extra",
"Includ").has_value());
477 CPPUNIT_ASSERT_MESSAGE(
"scope not present", !constIniFile->findField(
"extr",
"Includ").has_value());
481 std::stringstream newFile;
483 std::string originalContents;
485 inputFile.seekg(std::ios_base::beg);
488#pragma GCC diagnostic push
489#pragma GCC diagnostic ignored "-Wnull-dereference"
491 originalContents.assign((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
493#pragma GCC diagnostic pop
495 CPPUNIT_ASSERT_EQUAL(originalContents, newFile.str());
504 auto testFile = std::fstream();
505 testFile.exceptions(ios_base::failbit | ios_base::badbit);
506 testFile.open(
testFilePath(
"some_data"), ios_base::in | ios_base::binary);
507 auto outputStream = std::stringstream(ios_base::in | ios_base::out | ios_base::binary);
508 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
512 copyHelper.copy(testFile, outputStream, 50);
513 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(0), outputStream.tellg());
514 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), outputStream.tellp());
515 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellg());
516 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellp());
520 for (
auto i = 0;
i < 50; ++
i) {
521 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
532 testFile.exceptions(ios_base::failbit | ios_base::badbit);
533 testFile.open(
testFilePath(
"some_data"), ios_base::in | ios_base::binary);
534 auto outputPath =
workingCopyPath(
"copied_data", WorkingCopyMode::Cleanup);
536 outputStream.exceptions(ios_base::failbit | ios_base::badbit);
537 outputStream.open(outputPath, ios_base::out | ios_base::binary);
541 copyHelper.copy(testFile, outputStream, 50);
542 CPPUNIT_ASSERT(outputStream.is_open());
543 CPPUNIT_ASSERT(testFile.is_open());
546 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), outputStream.tellg());
547 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), outputStream.tellp());
548 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellg());
549 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellp());
552 const auto aFewMoreBytes =
"a few more bytes"sv;
553 outputStream << aFewMoreBytes;
554 outputStream.close();
555 outputStream.open(outputPath, ios_base::in | ios_base::binary);
559 for (
auto i = 0;
i < 50; ++
i) {
560 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
562 auto tail = std::string(aFewMoreBytes.size(),
'0');
563 outputStream.read(tail.data(),
static_cast<std::streamsize
>(tail.size()));
564 CPPUNIT_ASSERT_EQUAL(aFewMoreBytes, std::string_view(tail.data(), tail.size()));
567 auto percentage = 0.0;
568 const auto isAborted = [] {
return false; };
569 const auto callback = [&percentage](
double p) { percentage = p; };
571 outputStream.close();
572 outputStream.open(outputPath, ios_base::out | ios_base::trunc | ios_base::binary);
573 copyHelper.callbackCopy(testFile, outputStream, 50, isAborted, callback);
574 CPPUNIT_ASSERT_EQUAL(1.0, percentage);
577 CPPUNIT_ASSERT(outputStream.is_open());
578 CPPUNIT_ASSERT(testFile.is_open());
579 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), outputStream.tellg());
580 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), outputStream.tellp());
581 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellg());
582 CPPUNIT_ASSERT_EQUAL(
static_cast<std::fstream::pos_type
>(50), testFile.tellp());
583 outputStream << aFewMoreBytes;
584 outputStream.close();
585 outputStream.open(outputPath, ios_base::in | ios_base::binary);
587 for (
auto i = 0;
i < 50; ++
i) {
588 CPPUNIT_ASSERT_EQUAL(testFile.get(), outputStream.get());
590 tail.assign(aFewMoreBytes.size(),
'0');
591 outputStream.read(tail.data(),
static_cast<std::streamsize
>(tail.size()));
592 CPPUNIT_ASSERT_EQUAL(aFewMoreBytes, std::string_view(tail.data(), tail.size()));
602 CPPUNIT_ASSERT_EQUAL(
"# file for testing INI parser\n"
606 "key1=value 1 # comment\n"
617 CPPUNIT_ASSERT_THROW(
readFile(iniFilePath, 10), std::ios_base::failure);
620#if !defined(PLATFORM_WINDOWS) || defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
621 CPPUNIT_ASSERT_EQUAL(
"file with non-ASCII character 'ä' in its name\n"s,
readFile(
testFilePath(
"täst.txt")));
630 const string path(
workingCopyPath(
"test.ini", WorkingCopyMode::NoCopy));
632 CPPUNIT_ASSERT_EQUAL(
"some contents"s,
readFile(path));
642 ss1 << EscapeCodes::Phrases::Error <<
"some error" << EscapeCodes::Phrases::End;
643 ss1 << EscapeCodes::Phrases::Warning <<
"some warning" << EscapeCodes::Phrases::End;
644 ss1 << EscapeCodes::Phrases::Info <<
"some info" << EscapeCodes::Phrases::End;
645 ss1 << EscapeCodes::Phrases::ErrorMessage <<
"Arch-style error" << EscapeCodes::Phrases::End;
646 ss1 << EscapeCodes::Phrases::WarningMessage <<
"Arch-style warning" << EscapeCodes::Phrases::End;
647 ss1 << EscapeCodes::Phrases::PlainMessage <<
"Arch-style message" << EscapeCodes::Phrases::End;
648 ss1 << EscapeCodes::Phrases::SuccessMessage <<
"Arch-style success" << EscapeCodes::Phrases::End;
649 ss1 << EscapeCodes::Phrases::SubMessage <<
"Arch-style sub-message" << EscapeCodes::Phrases::End;
650 ss1 <<
EscapeCodes::color(EscapeCodes::Color::Blue, EscapeCodes::Color::Red, EscapeCodes::TextAttribute::Blink)
651 <<
"blue, blinking text on red background" << EscapeCodes::TextAttribute::Reset <<
'\n';
652 cout <<
"\noutput for formatting with ANSI escape codes:\n" << ss1.str() <<
"---------------------------------------------\n";
653 CPPUNIT_ASSERT_EQUAL(
"\033[1;31mError: \033[0m\033[1msome error\033[0m\n"
654 "\033[1;33mWarning: \033[0m\033[1msome warning\033[0m\n"
655 "\033[1;34mInfo: \033[0m\033[1msome info\033[0m\n"
656 "\033[1;31m==> ERROR: \033[0m\033[1mArch-style error\033[0m\n"
657 "\033[1;33m==> WARNING: \033[0m\033[1mArch-style warning\033[0m\n"
658 " \033[0m\033[1mArch-style message\033[0m\n"
659 "\033[1;32m==> \033[0m\033[1mArch-style success\033[0m\n"
660 "\033[1;32m -> \033[0m\033[1mArch-style sub-message\033[0m\n"
661 "\033[5;34;41mblue, blinking text on red background\033[0m\n"s,
666 ss2 << EscapeCodes::Phrases::Info <<
"some info" << EscapeCodes::Phrases::End;
667 CPPUNIT_ASSERT_EQUAL(
"Info: some info\n"s, ss2.str());
670#ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
674void IoTests::testNativeFileStream()
680 fileStream.exceptions(ios_base::badbit | ios_base::failbit);
681 CPPUNIT_ASSERT(!fileStream.is_open());
682 fileStream.open(txtFilePath, ios_base::in);
683 CPPUNIT_ASSERT(fileStream.is_open());
684#if defined(PLATFORM_WINDOWS) && defined(CPP_UTILITIES_USE_BOOST_IOSTREAMS)
685 CPPUNIT_ASSERT(fileStream.fileHandle() !=
nullptr);
687 CPPUNIT_ASSERT(fileStream.fileDescriptor() != -1);
689 CPPUNIT_ASSERT_EQUAL(
static_cast<char>(fileStream.get()),
'f');
690 fileStream.seekg(0, ios_base::end);
691 CPPUNIT_ASSERT_EQUAL(fileStream.tellg(),
static_cast<NativeFileStream::pos_type
>(47));
693 CPPUNIT_ASSERT(!fileStream.is_open());
695 fileStream.open(
"non existing file", ios_base::in | ios_base::out | ios_base::binary);
696 CPPUNIT_FAIL(
"expected exception");
697 }
catch (
const std::ios_base::failure &failure) {
698#ifdef PLATFORM_WINDOWS
699#ifdef CPP_UTILITIES_USE_BOOST_IOSTREAMS
711#ifndef PLATFORM_WINDOWS
712 auto readWriteFileDescriptor = open(txtFilePath.data(), O_RDWR);
713 CPPUNIT_ASSERT(readWriteFileDescriptor);
714 fileStream.open(readWriteFileDescriptor, ios_base::in | ios_base::out | ios_base::binary);
715 CPPUNIT_ASSERT(fileStream.is_open());
716 CPPUNIT_ASSERT_EQUAL(
static_cast<char>(fileStream.get()),
'f');
717 fileStream.seekg(0, ios_base::end);
718 CPPUNIT_ASSERT_EQUAL(fileStream.tellg(),
static_cast<NativeFileStream::pos_type
>(47));
721 CPPUNIT_ASSERT(!fileStream.is_open());
724 fileStream.open(-1, ios_base::in | ios_base::out | ios_base::binary);
726 CPPUNIT_FAIL(
"expected exception");
727 }
catch (
const std::ios_base::failure &failure) {
728#ifndef PLATFORM_WINDOWS
730 "expected error message",
"(basic_ios::clear|failed reading: Bad file descriptor): iostream error"s,
string(failure.what()));
739 fileStream2.exceptions(ios_base::failbit | ios_base::badbit);
740 fileStream2.open(txtFilePath, ios_base::in | ios_base::out | ios_base::app);
741 CPPUNIT_ASSERT(fileStream2.is_open());
742 fileStream2 <<
"foo";
745 CPPUNIT_ASSERT(!fileStream2.is_open());
746 CPPUNIT_ASSERT_EQUAL(
"file with non-ASCII character 'ä' in its name\nfoo"s,
readFile(txtFilePath, 50));
749 fileStream2.open(txtFilePath, ios_base::out | ios_base::trunc);
750 CPPUNIT_ASSERT(fileStream2.is_open());
751 fileStream2 <<
"bar";
753 CPPUNIT_ASSERT(!fileStream2.is_open());
754 CPPUNIT_ASSERT_EQUAL(
"bar"s,
readFile(txtFilePath, 4));
757#ifdef PLATFORM_WINDOWS
758 const auto wideTxtFilePath = NativeFileStream::makeWidePath(txtFilePath);
759 const auto appendFileHandle = _wfopen(wideTxtFilePath.get(), L
"a+");
761 const auto appendFileHandle = fopen(txtFilePath.data(),
"a");
763 CPPUNIT_ASSERT(appendFileHandle);
764 fileStream2.open(fileno(appendFileHandle), ios_base::out | ios_base::app);
765 CPPUNIT_ASSERT(fileStream2.is_open());
766 fileStream2 <<
"foo";
768 CPPUNIT_ASSERT(!fileStream2.is_open());
769 CPPUNIT_ASSERT_EQUAL(
"barfoo"s,
readFile(txtFilePath, 7));
#define CPP_UTILITIES_UNUSED(x)
Prevents warnings about unused variables.
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.
void reset(const char *buffer, std::size_t bufferSize)
Resets the reader.
std::uint8_t readBit()
Reads the one bit from the buffer advancing the current position by one bit.
void skipBits(std::size_t bitCount)
Skips the specified number of bits without reading it.
void align()
Re-establishes alignment.
std::size_t bitsAvailable()
Returns the number of bits which are still available to read.
intType readSignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (signed).
intType readUnsignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (unsigned).
intType readBits(std::uint8_t bitCount)
Reads the specified number of bits from the buffer advancing the current position by bitCount bits.
intType showBits(std::uint8_t bitCount)
Reads the specified number of bits from the buffer without advancing the current position.
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.
The IniFile class allows parsing and writing INI files.
void parse(std::istream &inputStream)
Parses all data from the specified inputStream.
ScopeList & data()
Returns the data of the file.
void make(std::ostream &outputStream)
Write the current data to the specified outputStream.
The IoTests class tests classes and functions provided by the files inside the io directory.
void testBufferSearch()
Tests the BufferSearch class.
void testBinaryReader()
Tests the most important methods of the BinaryReader.
void testAnsiEscapeCodes()
Tests formatting functions of CppUtilities::EscapeCodes namespace.
void testIniFile()
Tests IniFile.
void testBitReader()
Tests the BitReader class.
void testBinaryWriter()
Tests the most important methods of the BinaryWriter.
void testCopyWithNativeFileStream()
Tests CopyHelper in combination with NativeFileStream.
void testCopy()
Tests CopyHelper.
void testPathUtilities()
Tests fileName() and removeInvalidChars().
void testWriteFile()
Tests writeFile().
void testReadFile()
Tests readFile().
void testAdvancedIniFile()
Tests AdvancedIniFile.
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.
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.
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::testFilePath().
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPath().
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 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...
CPP_UTILITIES_EXPORT void writeFile(std::string_view path, std::string_view contents)
Writes all contents to the specified file in a single call.
CPP_UTILITIES_EXPORT void removeInvalidChars(std::string &fileName)
Removes invalid characters from the specified fileName.
CPP_UTILITIES_EXPORT std::string fileName(const std::string &path)
Returns the file name and extension of the specified path string.
NativePathStringView makeNativePath(PathStringView path)
Returns path in the platform's native encoding.
CPP_UTILITIES_EXPORT std::string directory(const std::string &path)
Returns the directory of the specified path string (including trailing slash).
The AdvancedIniFile class allows parsing and writing INI files.
void make(std::ostream &outputStream, IniFileMakeOptions options=IniFileMakeOptions::None)
Write the current data to the specified outputStream.
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.
void parse(std::istream &inputStream, IniFileParseOptions options=IniFileParseOptions::None)
Parses all data from the specified inputStream.
SectionList::iterator sectionEnd()
Returns an iterator that points one past the last section.
SectionList::iterator findSection(std::string_view sectionName)
Returns an iterator to the first section with the name sectionName.
#define TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, regexFlags, actualString)
Asserts whether the specified string matches the specified regex.
#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString)
Asserts whether the specified string matches the specified regex.