216 const std::uint8_t simpleString[] = {
'A',
'B',
'C',
'D' };
217 const std::uint16_t simpleUtf16LEString[] = { 0x0041, 0x0042, 0x0043, 0x0044 };
218 const std::uint16_t simpleUtf16BEString[] = { 0x4100, 0x4200, 0x4300, 0x4400 };
220 const std::uint8_t latin1String[] = {
'A',
'B', 0xD6,
'C',
'D' };
221 const std::uint8_t utf8String[] = {
'A',
'B', 0xC3, 0x96,
'C',
'D' };
222 const std::uint16_t utf16LEString[] = { 0x0041, 0x0042, 0x00D6, 0x0043, 0x0044 };
223 const std::uint16_t utf16BEString[] = { 0x4100, 0x4200, 0xD600, 0x4300, 0x4400 };
228 "UTF-16LE to UTF-8 (simple)", simpleString, 4,
convertUtf16LEToUtf8(
reinterpret_cast<const char *
>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
231 "UTF-16BE to UTF-8 (simple)", simpleString, 4,
convertUtf16BEToUtf8(
reinterpret_cast<const char *
>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
236 assertEqual(
"UTF-8 to UFT-16LE (simple)",
reinterpret_cast<const std::uint8_t *
>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
238 assertEqual(
"UTF-8 to UFT-16LE",
reinterpret_cast<const std::uint8_t *
>(LE_STR_FOR_ENDIANNESS(utf16)), 10,
240 assertEqual(
"UTF-8 to UFT-16BE (simple)",
reinterpret_cast<const std::uint8_t *
>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
242 assertEqual(
"UTF-8 to UFT-16BE",
reinterpret_cast<const std::uint8_t *
>(BE_STR_FOR_ENDIANNESS(utf16)), 10,
253 CPPUNIT_ASSERT_EQUAL(
"0"s, numberToString<unsigned int>(0));
254 CPPUNIT_ASSERT_EQUAL(
"0"s, numberToString<signed int>(0));
255 uniform_int_distribution<std::int64_t> randomDistSigned(numeric_limits<std::int64_t>::min());
256 uniform_int_distribution<std::uint64_t> randomDistUnsigned(0);
257 const string stringMsg(
"string"), wideStringMsg(
"wide string"), bufferMsg(
"buffer");
258 for (std::uint8_t b = 1; b < 100; ++b) {
259 auto signedRandom = randomDistSigned(m_randomEngine);
260 auto unsignedRandom = randomDistUnsigned(m_randomEngine);
261 for (
const auto base : initializer_list<std::uint8_t>{ 2, 8, 10, 16 }) {
262 const auto asString = numberToString<std::uint64_t, string>(unsignedRandom, base);
263 const auto asWideString = numberToString<std::uint64_t, wstring>(unsignedRandom, base);
264 CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asString, base));
265 CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asWideString, base));
266 CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, unsignedRandom, bufferToNumber<std::uint64_t>(asString.data(), asString.size(), base));
268 for (
const auto base : initializer_list<std::uint8_t>{ 10 }) {
269 const auto asString = numberToString<std::int64_t, string>(signedRandom,
static_cast<string::value_type
>(base));
270 const auto asWideString = numberToString<std::int64_t, wstring>(signedRandom, base);
271 CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, signedRandom, stringToNumber<std::int64_t>(asString, base));
272 CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, signedRandom, stringToNumber<std::int64_t>(asWideString, base));
273 CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, signedRandom, bufferToNumber<std::int64_t>(asString.data(), asString.size(), base));
278 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(
"01"));
279 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(L
"01"s));
280 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(u
"01"s));
281 CPPUNIT_ASSERT_EQUAL(-23, stringToNumber<std::int32_t>(
" - 023"s));
282 CPPUNIT_ASSERT_EQUAL(-23, bufferToNumber<std::int32_t>(
" - 023", 6));
283 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(
"01"));
284 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(L
"01"s));
285 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(u
"01"s));
286 CPPUNIT_ASSERT_EQUAL(23u, stringToNumber<std::uint32_t>(
" 023"s));
287 CPPUNIT_ASSERT_EQUAL(23u, bufferToNumber<std::uint32_t>(
" 023", 5));
288 CPPUNIT_ASSERT_EQUAL(255u, stringToNumber<std::uint32_t>(
"fF", 16));
289 CPPUNIT_ASSERT_THROW_MESSAGE(
"character out of range", stringToNumber<std::uint32_t>(
"fF", 15),
ConversionException);
290 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid character", stringToNumber<std::uint32_t>(
"(", 15),
ConversionException);
292 CPPUNIT_ASSERT_THROW_MESSAGE(
"overflow", stringToNumber<std::uint32_t>(
"100000000", 16),
ConversionException);
293 CPPUNIT_ASSERT_THROW_MESSAGE(
"underflow", stringToNumber<std::int32_t>(
"-80000001", 16),
ConversionException);
294 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"positive limit", 0xFFFFFFFFu, stringToNumber<std::uint32_t>(
"FFFFFFFF", 16));
295 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"negative limit", -2147483647, stringToNumber<std::int32_t>(
"-2147483647", 10));
299 CPPUNIT_ASSERT_EQUAL(1.5f, stringToNumber<float>(
numberToString(1.5f)));
300 CPPUNIT_ASSERT_EQUAL(1.5, stringToNumber<double>(
numberToString(1.5)));
301 CPPUNIT_ASSERT_EQUAL(-10.25, stringToNumber<double>(
"-10.25"));
304 CPPUNIT_ASSERT_EQUAL(
"TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
307 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"empty string", vector<string>({ string() }),
splitString<vector<string>>(
string(),
","));
308 CPPUNIT_ASSERT_EQUAL_MESSAGE(
309 "empty string (simple)", vector<string_view>({ string_view() }),
splitStringSimple<vector<string_view>>(string_view(),
","));
310 vector<string> splitTestExpected({
"1",
"2,3" });
311 vector<string> splitTestActual = splitString<vector<string>>(
"1,2,3"s,
","s, EmptyPartsTreat::Keep, 2);
312 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
313 splitTestActual = splitStringSimple<vector<string>>(
"1,2,3"s,
","s, 2);
314 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
315 splitTestExpected = {
"12",
"34",
"56",
"" };
316 splitTestActual = splitString<vector<string>>(
"12,34,56,"s,
","s);
317 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
318 splitTestActual = splitStringSimple<vector<string>>(
"12,34,56,"s,
","s);
319 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
320 splitTestExpected = {
"1",
"2,3",
"4,,5" };
321 splitTestActual = splitString<vector<string>>(
"1,2,,3,4,,5"s,
","s, EmptyPartsTreat::Merge, 3);
322 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
323 string splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Keep),
" "s,
false,
"("s,
")"s);
324 CPPUNIT_ASSERT_EQUAL(
"() (a) () (ab) (ABC) (s)"s, splitJoinTest);
325 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Keep),
" "s,
true,
"("s,
")"s);
326 CPPUNIT_ASSERT_EQUAL(
"(a) (ab) (ABC) (s)"s, splitJoinTest);
327 splitJoinTest =
joinStrings(
splitStringSimple<vector<string>>(
",a,,ab,ABC,s"s,
","s),
" "s,
true,
"("s,
")"s);
328 CPPUNIT_ASSERT_EQUAL(
"(a) (ab) (ABC) (s)"s, splitJoinTest);
329 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Omit),
" "s,
false,
"("s,
")"s);
330 CPPUNIT_ASSERT_EQUAL(
"(a) (ab) (ABC) (s)"s, splitJoinTest);
331 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Merge),
" "s,
false,
"("s,
")"s);
332 CPPUNIT_ASSERT_EQUAL(
"(a,ab) (ABC) (s)"s, splitJoinTest);
335 string findReplaceTest(
"findAndReplace()");
336 findAndReplace<string>(findReplaceTest,
"And",
"Or");
337 CPPUNIT_ASSERT_EQUAL(
"findOrReplace()"s, findReplaceTest);
340 CPPUNIT_ASSERT(!
startsWith(findReplaceTest,
"findAnd"));
341 CPPUNIT_ASSERT(
startsWith(findReplaceTest,
"findOr"));
342 CPPUNIT_ASSERT(!
startsWith(findReplaceTest,
"findAnd"s));
343 CPPUNIT_ASSERT(
startsWith(findReplaceTest,
"findOr"s));
346 CPPUNIT_ASSERT(!
startsWith(
"test"s,
"tests"s));
347 CPPUNIT_ASSERT(!
startsWith(
"test"s,
"tests"));
350 CPPUNIT_ASSERT(!
endsWith(findReplaceTest,
"AndReplace()"));
351 CPPUNIT_ASSERT(
endsWith(findReplaceTest,
"OrReplace()"));
352 CPPUNIT_ASSERT(!
endsWith(findReplaceTest,
"AndReplace()"s));
353 CPPUNIT_ASSERT(
endsWith(findReplaceTest,
"OrReplace()"s));
354 CPPUNIT_ASSERT(
endsWith(
"test"s,
"test"s));
355 CPPUNIT_ASSERT(
endsWith(
"test"s,
"test"));
356 CPPUNIT_ASSERT(!
endsWith(
"test"s,
" test"s));
357 CPPUNIT_ASSERT(!
endsWith(
"test"s,
" test"));
360 CPPUNIT_ASSERT(containsSubstrings<string>(
"this string contains foo and bar", {
"foo",
"bar" }));
361 CPPUNIT_ASSERT(!containsSubstrings<string>(
"this string contains foo and bar", {
"bar",
"foo" }));
364 string truncateTest(
"foo bar ");
366 CPPUNIT_ASSERT_EQUAL(
"foo"s, truncateTest);
369 std::uniform_int_distribution<int> randomDistChar;
370 std::uint8_t originalBase64Data[4047];
371 for (std::uint8_t &c : originalBase64Data) {
372 c =
static_cast<std::uint8_t
>(randomDistChar(m_randomEngine) & 0xFF);
374 auto encodedBase64Data =
encodeBase64(originalBase64Data,
sizeof(originalBase64Data));
375 auto decodedBase64Data =
decodeBase64(encodedBase64Data.data(),
static_cast<std::uint32_t
>(encodedBase64Data.size()));
376 CPPUNIT_ASSERT(decodedBase64Data.second ==
sizeof(originalBase64Data));
377 for (
unsigned int i = 0;
i <
sizeof(originalBase64Data); ++
i) {
378 CPPUNIT_ASSERT(decodedBase64Data.first[
i] == originalBase64Data[
i]);
381 encodedBase64Data =
encodeBase64(originalBase64Data,
sizeof(originalBase64Data) - 1);
382 CPPUNIT_ASSERT_EQUAL(
'=', encodedBase64Data.at(encodedBase64Data.size() - 1));
383 CPPUNIT_ASSERT_NO_THROW(
decodeBase64(encodedBase64Data.data(),
static_cast<std::uint32_t
>(encodedBase64Data.size())));
384 encodedBase64Data =
encodeBase64(originalBase64Data,
sizeof(originalBase64Data) - 2);
385 CPPUNIT_ASSERT_EQUAL(
'=', encodedBase64Data.at(encodedBase64Data.size() - 1));
386 CPPUNIT_ASSERT_EQUAL(
'=', encodedBase64Data.at(encodedBase64Data.size() - 2));
387 CPPUNIT_ASSERT_NO_THROW(
decodeBase64(encodedBase64Data.data(),
static_cast<std::uint32_t
>(encodedBase64Data.size())));
394 CPPUNIT_ASSERT_EQUAL(
"2.50 KiB (2560 byte)"s,
dataSizeToString((2048ull + 512ull),
true));
395 CPPUNIT_ASSERT_EQUAL(
"2.50 MiB"s,
dataSizeToString((2048ull + 512ull) * 1024ull));
396 CPPUNIT_ASSERT_EQUAL(
"2.50 GiB"s,
dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull));
397 CPPUNIT_ASSERT_EQUAL(
"2.50 TiB"s,
dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull * 1024ull));
400 CPPUNIT_ASSERT_EQUAL(
"128 Mbit/s"s,
bitrateToString(128.0 * 1e3,
false));
401 CPPUNIT_ASSERT_EQUAL(
"128 Gbit/s"s,
bitrateToString(128.0 * 1e6,
false));
436 static_assert(Helper::IsStringType<std::string, std::string>::value);
437 static_assert(!Helper::IsStringType<std::string, std::wstring>::value);
438 static_assert(Helper::IsStringType<std::wstring, std::wstring>::value);
439 static_assert(Helper::IsStringViewType<std::string, std::string_view>::value);
440 static_assert(!Helper::IsStringViewType<std::wstring, std::string_view>::value);
441 static_assert(Helper::IsStringViewType<std::wstring, std::wstring_view>::value);
442 static_assert(Helper::IsConvertibleToConstStringRef<std::string, ConvertibleToString>::value);
443#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
444 static_assert(!Helper::IsConvertibleToConstStringRef<std::filesystem::path::string_type, std::filesystem::path>::value,
445 "conversion via native() preferred");
448 !Helper::IsConvertibleToConstStringRef<std::string, std::string>::value,
"yes, in this context this should not be considered convertible");
449 static_assert(!Helper::IsConvertibleToConstStringRef<std::wstring, ConvertibleToString>::value);
450#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
451 static_assert(Helper::IsConvertibleToConstStringRefViaNative<std::filesystem::path::string_type, std::filesystem::path>::value);
453 static_assert(!Helper::IsConvertibleToConstStringRefViaNative<std::string, std::string>::value);
456 const tuple<const char *, string, int, const char *> tuple(
"string1",
"string2", 1234,
"string3");
457 CPPUNIT_ASSERT_EQUAL(
"string1string21234string3"s,
tupleToString(tuple));
458 CPPUNIT_ASSERT_EQUAL(
"foobarfoo2bar2"s,
tupleToString(
"foo"s %
"bar" %
"foo2"s %
"bar2"));
459 CPPUNIT_ASSERT_EQUAL(
"v2.3.0"s,
argsToString(
"v2.", 3,
'.', 0));
460 CPPUNIT_ASSERT_EQUAL(
"v2.3.0"s,
argsToString(
'v', make_tuple(2,
'.', 3,
'.', 0)));
461#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
462 if constexpr (std::is_same_v<std::filesystem::path::value_type, std::string::value_type>) {
463 CPPUNIT_ASSERT_EQUAL(
"path: foo"s,
argsToString(
"path: ", std::filesystem::path(
"foo")));
468 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"result can be passed to any function taking a std::string"s,
"123456789"s,
"12" %
string(
"34") %
'5' % 67 +
"89");
469 constexpr double velocityExample = 27.0;
470 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"real-word example"s,
"velocity: 27 km/h (7.5 m/s)"s,
472 CPPUNIT_ASSERT_EQUAL_MESSAGE(
473 "regular + operator still works (no problems with ambiguity)"s,
"regular + still works"s,
"regular"s +
" + still works");
474 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"using string_view",
"foobar123"s,
"foo"sv %
"bar"sv + 123);
477 StringThatDoesNotLikeToBeCopiedOrMoved str(
" happen ");
478 const StringThatDoesNotLikeToBeCopiedOrMoved str2(
"for this");
479 CPPUNIT_ASSERT_EQUAL(
"no copy/move should happen for this!"s,
480 argsToString(StringThatDoesNotLikeToBeCopiedOrMoved(
"no copy/move should"), str, str2, StringThatDoesNotLikeToBeCopiedOrMoved(
"!")));