C++ Utilities  5.10.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
conversiontests.cpp
Go to the documentation of this file.
1 #include "../conversion/binaryconversion.h"
2 #include "../conversion/stringbuilder.h"
3 #include "../conversion/stringconversion.h"
4 #include "../tests/testutils.h"
5 
6 using namespace CppUtilities;
7 
8 #include <cppunit/TestFixture.h>
9 #include <cppunit/extensions/HelperMacros.h>
10 
11 #include <functional>
12 #include <initializer_list>
13 #include <random>
14 #include <sstream>
15 
16 #ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
17 #include <filesystem>
18 #endif
19 
20 using namespace std;
21 
22 using namespace CPPUNIT_NS;
23 
24 // compile-time checks for binary conversion
25 static_assert(toSynchsafeInt(255) == 383, "toSynchsafeInt()");
26 static_assert(toNormalInt(383) == 255, "toNormalInt()");
27 static_assert(swapOrder(static_cast<std::uint16_t>(0xABCD)) == 0xCDAB, "swapOrder(uint16)");
28 static_assert(swapOrder(static_cast<std::uint32_t>(0xABCDEF12)) == 0x12EFCDAB, "swapOrder(uint32)");
29 static_assert(swapOrder(static_cast<std::uint64_t>(0xABCDEF1234567890)) == 0x9078563412EFCDAB, "swapOrder(uint64)");
30 
34 class ConversionTests : public TestFixture {
35  CPPUNIT_TEST_SUITE(ConversionTests);
36  CPPUNIT_TEST(testConversionException);
37  CPPUNIT_TEST(testEndianness);
38  CPPUNIT_TEST(testBinaryConversions);
39  CPPUNIT_TEST(testSwapOrderFunctions);
40  CPPUNIT_TEST(testStringEncodingConversions);
41  CPPUNIT_TEST(testStringConversions);
42  CPPUNIT_TEST(testStringBuilder);
43  CPPUNIT_TEST_SUITE_END();
44 
45 public:
47 
48  void setUp()
49  {
50  }
51  void tearDown()
52  {
53  }
54 
55  void testConversionException();
56  void testEndianness();
57  void testBinaryConversions();
58  void testSwapOrderFunctions();
59  void testStringEncodingConversions();
60  void testStringConversions();
61  void testStringBuilder();
62 
63 private:
64  template <typename intType>
65  void testConversion(const char *message, function<void(intType, char *)> vice, function<intType(const char *)> verca, intType min, intType max);
66 
67  char m_buff[8];
68  random_device m_randomDevice;
69  mt19937 m_randomEngine;
70 };
71 
73 
75  : m_randomDevice()
76  , m_randomEngine(m_randomDevice())
77 {
78 }
79 
81 {
82  CPPUNIT_ASSERT(!strcmp("unable to convert", ConversionException().what()));
83 }
84 
89 {
90  union {
91  uint32_t integer;
92  char characters[4];
93  } test = { 0x01020304 };
94 #if defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
95  // test whether macro definitions are consistent
96  CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true);
97  CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == false);
98  // test whether byte order assumption is correct
99  CPPUNIT_ASSERT_MESSAGE("Byte order assumption (big-endian) is wrong", test.characters[0] == 0x01);
100 #elif defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
101  // test whether macro definitions are consistent
102  CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == false);
103  CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true);
104  // test whether byte order assumption is correct
105  CPPUNIT_ASSERT_MESSAGE("Byte order assumption (little-endian) is wrong", test.characters[0] == 0x04);
106 #else
107  CPPUNIT_FAIL("There is not valid byte order assumption");
108 #endif
109 }
110 
111 template <typename intType>
112 void ConversionTests::testConversion(
113  const char *message, function<void(intType, char *)> vice, function<intType(const char *)> versa, intType min, intType max)
114 {
115  const intType random = uniform_int_distribution<intType>(min, max)(m_randomEngine);
116  stringstream msg;
117  msg << message << '(' << hex << '0' << 'x' << random << ')';
118  vice(random, m_buff);
119  CPPUNIT_ASSERT_MESSAGE(msg.str(), versa(m_buff) == random);
120 }
121 
122 #define TEST_TYPE(endianness, function) decltype(endianness::function(m_buff))
123 
124 #define TEST_CONVERSION(function, endianness) \
125  testConversion<TEST_TYPE(endianness, function)>("testing " #function, \
126  static_cast<void (*)(TEST_TYPE(endianness, function), char *)>(&endianness::getBytes), endianness::function, \
127  numeric_limits<TEST_TYPE(endianness, function)>::min(), numeric_limits<TEST_TYPE(endianness, function)>::max())
128 
129 #define TEST_BE_CONVERSION(function) TEST_CONVERSION(function, BE)
130 
131 #define TEST_LE_CONVERSION(function) TEST_CONVERSION(function, LE)
132 
133 #define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max) \
134  testConversion<TEST_TYPE(endianness, versa)>( \
135  "testing " #versa, static_cast<void (*)(TEST_TYPE(endianness, versa), char *)>(&endianness::vice), endianness::versa, min, max)
136 
144 {
145  // test to...() / getBytes() with random numbers
146  for (auto b = 1; b < 100; ++b) {
147  TEST_BE_CONVERSION(toUInt16);
148  TEST_BE_CONVERSION(toUInt32);
149  TEST_BE_CONVERSION(toUInt64);
150  TEST_LE_CONVERSION(toUInt16);
151  TEST_LE_CONVERSION(toUInt32);
152  TEST_LE_CONVERSION(toUInt64);
153  TEST_BE_CONVERSION(toInt16);
154  TEST_BE_CONVERSION(toInt32);
155  TEST_BE_CONVERSION(toInt64);
156  TEST_LE_CONVERSION(toInt16);
157  TEST_LE_CONVERSION(toInt32);
158  TEST_LE_CONVERSION(toInt64);
159  TEST_CUSTOM_CONVERSION(getBytes24, toUInt24, BE, 0, 0xFFFFFF);
160  TEST_CUSTOM_CONVERSION(getBytes24, toUInt24, LE, 0, 0xFFFFFF);
161  }
162 }
163 
168 {
169  CPPUNIT_ASSERT(swapOrder(static_cast<std::uint16_t>(0x7825)) == 0x2578);
170  CPPUNIT_ASSERT(swapOrder(static_cast<std::uint32_t>(0x12345678)) == 0x78563412);
171  CPPUNIT_ASSERT(swapOrder(static_cast<std::uint64_t>(0x1122334455667788)) == 0x8877665544332211);
172 }
173 
177 void assertEqual(const char *message, const std::uint8_t *expectedValues, size_t expectedSize, const StringData &actualValues)
178 {
179  // check whether number of elements matches
180  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expectedSize, actualValues.second);
181  // check whether contents match
182  auto *end = expectedValues + expectedSize;
183  auto *i = reinterpret_cast<std::uint8_t *>(actualValues.first.get());
184  for (; expectedValues != end; ++expectedValues, ++i) {
185  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, asHexNumber(*expectedValues), asHexNumber(*i));
186  }
187 }
188 
189 #if CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true
190 #define LE_STR_FOR_ENDIANNESS(name) name##LE##String
191 #define BE_STR_FOR_ENDIANNESS(name) name##BE##String
192 #elif CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true
193 #define LE_STR_FOR_ENDIANNESS(name) name##BE##String
194 #define BE_STR_FOR_ENDIANNESS(name) name##LE##String
195 #endif
196 
211 {
212  // define test string "ABCD" for the different encodings
213  const std::uint8_t simpleString[] = { 'A', 'B', 'C', 'D' };
214  const std::uint16_t simpleUtf16LEString[] = { 0x0041, 0x0042, 0x0043, 0x0044 };
215  const std::uint16_t simpleUtf16BEString[] = { 0x4100, 0x4200, 0x4300, 0x4400 };
216  // define test string "ABĂ–CD" for the different encodings
217  const std::uint8_t latin1String[] = { 'A', 'B', 0xD6, 'C', 'D' };
218  const std::uint8_t utf8String[] = { 'A', 'B', 0xC3, 0x96, 'C', 'D' };
219  const std::uint16_t utf16LEString[] = { 0x0041, 0x0042, 0x00D6, 0x0043, 0x0044 };
220  const std::uint16_t utf16BEString[] = { 0x4100, 0x4200, 0xD600, 0x4300, 0x4400 };
221  // test conversion to UTF-8
222  assertEqual("Latin-1 to UTF-8 (simple)", simpleString, 4, convertLatin1ToUtf8(reinterpret_cast<const char *>(simpleString), 4));
223  assertEqual("Latin-1 to UTF-8", utf8String, 6, convertLatin1ToUtf8(reinterpret_cast<const char *>(latin1String), 5));
224  assertEqual(
225  "UTF-16LE to UTF-8 (simple)", simpleString, 4, convertUtf16LEToUtf8(reinterpret_cast<const char *>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
226  assertEqual("UTF-16LE to UTF-8", utf8String, 6, convertUtf16LEToUtf8(reinterpret_cast<const char *>(LE_STR_FOR_ENDIANNESS(utf16)), 10));
227  assertEqual(
228  "UTF-16BE to UTF-8 (simple)", simpleString, 4, convertUtf16BEToUtf8(reinterpret_cast<const char *>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
229  assertEqual("UTF-16BE to UTF-8", utf8String, 6, convertUtf16BEToUtf8(reinterpret_cast<const char *>(BE_STR_FOR_ENDIANNESS(utf16)), 10));
230  // test conversion from UTF-8
231  assertEqual("UTF-8 to Latin-1 (simple)", simpleString, 4, convertUtf8ToLatin1(reinterpret_cast<const char *>(simpleString), 4));
232  assertEqual("UTF-8 to Latin-1", latin1String, 5, convertUtf8ToLatin1(reinterpret_cast<const char *>(utf8String), 6));
233  assertEqual("UTF-8 to UFT-16LE (simple)", reinterpret_cast<const std::uint8_t *>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
234  convertUtf8ToUtf16LE(reinterpret_cast<const char *>(simpleString), 4));
235  assertEqual("UTF-8 to UFT-16LE", reinterpret_cast<const std::uint8_t *>(LE_STR_FOR_ENDIANNESS(utf16)), 10,
236  convertUtf8ToUtf16LE(reinterpret_cast<const char *>(utf8String), 6));
237  assertEqual("UTF-8 to UFT-16BE (simple)", reinterpret_cast<const std::uint8_t *>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
238  convertUtf8ToUtf16BE(reinterpret_cast<const char *>(simpleString), 4));
239  assertEqual("UTF-8 to UFT-16BE", reinterpret_cast<const std::uint8_t *>(BE_STR_FOR_ENDIANNESS(utf16)), 10,
240  convertUtf8ToUtf16BE(reinterpret_cast<const char *>(utf8String), 6));
241  CPPUNIT_ASSERT_THROW(convertString("invalid charset", "UTF-8", "foo", 3, 1.0f), ConversionException);
242 }
243 
248 {
249  // stringToNumber() / numberToString() with zero and random numbers
250  CPPUNIT_ASSERT_EQUAL("0"s, numberToString<unsigned int>(0));
251  CPPUNIT_ASSERT_EQUAL("0"s, numberToString<signed int>(0));
252  uniform_int_distribution<std::int64_t> randomDistSigned(numeric_limits<std::int64_t>::min());
253  uniform_int_distribution<std::uint64_t> randomDistUnsigned(0);
254  const string stringMsg("string"), wideStringMsg("wide string"), bufferMsg("buffer");
255  for (std::uint8_t b = 1; b < 100; ++b) {
256  auto signedRandom = randomDistSigned(m_randomEngine);
257  auto unsignedRandom = randomDistUnsigned(m_randomEngine);
258  for (const auto base : initializer_list<std::uint8_t>{ 2, 8, 10, 16 }) {
259  const auto asString = numberToString<std::uint64_t, string>(unsignedRandom, static_cast<string::value_type>(base));
260  const auto asWideString = numberToString<std::uint64_t, wstring>(unsignedRandom, base);
261  CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asString, static_cast<string::value_type>(base)));
262  CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asWideString, base));
263  CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, unsignedRandom, bufferToNumber<std::uint64_t>(asString.data(), asString.size(), base));
264  }
265  for (const auto base : initializer_list<std::uint8_t>{ 10 }) {
266  const auto asString = numberToString<std::int64_t, string>(signedRandom, static_cast<string::value_type>(base));
267  const auto asWideString = numberToString<std::int64_t, wstring>(signedRandom, base);
268  CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, signedRandom, stringToNumber<std::int64_t>(asString, static_cast<string::value_type>(base)));
269  CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, signedRandom, stringToNumber<std::int64_t>(asWideString, base));
270  CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, signedRandom, bufferToNumber<std::int64_t>(asString.data(), asString.size(), base));
271  }
272  }
273 
274  // stringToNumber() with spaces at the beginning, leading zeroes, different types and other corner cases
275  CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>("01"));
276  CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(L"01"s));
277  CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(u"01"s));
278  CPPUNIT_ASSERT_EQUAL(-23, stringToNumber<std::int32_t>(" - 023"s));
279  CPPUNIT_ASSERT_EQUAL(-23, bufferToNumber<std::int32_t>(" - 023", 6));
280  CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>("01"));
281  CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(L"01"s));
282  CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(u"01"s));
283  CPPUNIT_ASSERT_EQUAL(23u, stringToNumber<std::uint32_t>(" 023"s));
284  CPPUNIT_ASSERT_EQUAL(23u, bufferToNumber<std::uint32_t>(" 023", 5));
285  CPPUNIT_ASSERT_EQUAL(255u, stringToNumber<std::uint32_t>("fF", 16));
286  CPPUNIT_ASSERT_THROW(stringToNumber<std::uint32_t>("fF", 15), ConversionException);
287  CPPUNIT_ASSERT_THROW(stringToNumber<std::uint32_t>("(", 15), ConversionException);
288 
289  // interpretIntegerAsString()
290  CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
291 
292  // splitString() / joinStrings()
293  vector<string> splitTestExpected({ "1", "2,3" });
294  vector<string> splitTestActual = splitString<vector<string>>("1,2,3"s, ","s, EmptyPartsTreat::Keep, 2);
295  CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
296  splitTestActual = splitStringSimple<vector<string>>("1,2,3"s, ","s, 2);
297  CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
298  splitTestExpected = { "1", "2,3", "4,,5" };
299  splitTestActual = splitString<vector<string>>("1,2,,3,4,,5"s, ","s, EmptyPartsTreat::Merge, 3);
300  CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
301  string splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Keep), " "s, false, "("s, ")"s);
302  CPPUNIT_ASSERT_EQUAL("() (a) () (ab) (ABC) (s)"s, splitJoinTest);
303  splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Keep), " "s, true, "("s, ")"s);
304  CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
305  splitJoinTest = joinStrings(splitStringSimple<vector<string>>(",a,,ab,ABC,s"s, ","s), " "s, true, "("s, ")"s);
306  CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
307  splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Omit), " "s, false, "("s, ")"s);
308  CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
309  splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Merge), " "s, false, "("s, ")"s);
310  CPPUNIT_ASSERT_EQUAL("(a,ab) (ABC) (s)"s, splitJoinTest);
311 
312  // findAndReplace()
313  string findReplaceTest("findAndReplace()");
314  findAndReplace<string>(findReplaceTest, "And", "Or");
315  CPPUNIT_ASSERT_EQUAL("findOrReplace()"s, findReplaceTest);
316 
317  // startsWith()
318  CPPUNIT_ASSERT(!startsWith(findReplaceTest, "findAnd"));
319  CPPUNIT_ASSERT(startsWith(findReplaceTest, "findOr"));
320  CPPUNIT_ASSERT(!startsWith(findReplaceTest, "findAnd"s));
321  CPPUNIT_ASSERT(startsWith(findReplaceTest, "findOr"s));
322  CPPUNIT_ASSERT(startsWith("test"s, "test"s));
323  CPPUNIT_ASSERT(startsWith("test"s, "test"));
324  CPPUNIT_ASSERT(!startsWith("test"s, "tests"s));
325  CPPUNIT_ASSERT(!startsWith("test"s, "tests"));
326 
327  // endsWith()
328  CPPUNIT_ASSERT(!endsWith(findReplaceTest, "AndReplace()"));
329  CPPUNIT_ASSERT(endsWith(findReplaceTest, "OrReplace()"));
330  CPPUNIT_ASSERT(!endsWith(findReplaceTest, "AndReplace()"s));
331  CPPUNIT_ASSERT(endsWith(findReplaceTest, "OrReplace()"s));
332  CPPUNIT_ASSERT(endsWith("test"s, "test"s));
333  CPPUNIT_ASSERT(endsWith("test"s, "test"));
334  CPPUNIT_ASSERT(!endsWith("test"s, " test"s));
335  CPPUNIT_ASSERT(!endsWith("test"s, " test"));
336 
337  // containsSubstrings()
338  CPPUNIT_ASSERT(containsSubstrings<string>("this string contains foo and bar", { "foo", "bar" }));
339  CPPUNIT_ASSERT(!containsSubstrings<string>("this string contains foo and bar", { "bar", "foo" }));
340 
341  // truncateString()
342  string truncateTest("foo bar ");
343  truncateString(truncateTest, ' ');
344  CPPUNIT_ASSERT_EQUAL("foo"s, truncateTest);
345 
346  // encodeBase64() / decodeBase64() with random data
347  uniform_int_distribution<std::uint8_t> randomDistChar;
348  std::uint8_t originalBase64Data[4047];
349  for (std::uint8_t &c : originalBase64Data) {
350  c = randomDistChar(m_randomEngine);
351  }
352  auto encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data));
353  auto decodedBase64Data = decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size()));
354  CPPUNIT_ASSERT(decodedBase64Data.second == sizeof(originalBase64Data));
355  for (unsigned int i = 0; i < sizeof(originalBase64Data); ++i) {
356  CPPUNIT_ASSERT(decodedBase64Data.first[i] == originalBase64Data[i]);
357  }
358  // test padding
359  encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data) - 1);
360  CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 1));
361  CPPUNIT_ASSERT_NO_THROW(decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size())));
362  encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data) - 2);
363  CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 1));
364  CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 2));
365  CPPUNIT_ASSERT_NO_THROW(decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size())));
366  // test check for invalid size
367  CPPUNIT_ASSERT_THROW(decodeBase64(encodedBase64Data.data(), 3), ConversionException);
368 
369  // dataSizeToString(), bitrateToString()
370  CPPUNIT_ASSERT_EQUAL("512 bytes"s, dataSizeToString(512ull));
371  CPPUNIT_ASSERT_EQUAL("2.50 KiB"s, dataSizeToString((2048ull + 512ull)));
372  CPPUNIT_ASSERT_EQUAL("2.50 KiB (2560 byte)"s, dataSizeToString((2048ull + 512ull), true));
373  CPPUNIT_ASSERT_EQUAL("2.50 MiB"s, dataSizeToString((2048ull + 512ull) * 1024ull));
374  CPPUNIT_ASSERT_EQUAL("2.50 GiB"s, dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull));
375  CPPUNIT_ASSERT_EQUAL("2.50 TiB"s, dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull * 1024ull));
376  CPPUNIT_ASSERT_EQUAL("128 bit/s"s, bitrateToString(0.128, false));
377  CPPUNIT_ASSERT_EQUAL("128 kbit/s"s, bitrateToString(128.0, false));
378  CPPUNIT_ASSERT_EQUAL("128 Mbit/s"s, bitrateToString(128.0 * 1e3, false));
379  CPPUNIT_ASSERT_EQUAL("128 Gbit/s"s, bitrateToString(128.0 * 1e6, false));
380  CPPUNIT_ASSERT_EQUAL("16 byte/s"s, bitrateToString(0.128, true));
381  CPPUNIT_ASSERT_EQUAL("16 KiB/s"s, bitrateToString(128.0, true));
382  CPPUNIT_ASSERT_EQUAL("16 MiB/s"s, bitrateToString(128.0 * 1e3, true));
383  CPPUNIT_ASSERT_EQUAL("16 GiB/s"s, bitrateToString(128.0 * 1e6, true));
384 }
385 
387 
388 struct ConvertibleToString {
389  operator std::string() const;
390 };
391 
392 struct StringThatDoesNotLikeToBeCopiedOrMoved : public std::string {
393  explicit StringThatDoesNotLikeToBeCopiedOrMoved(const char *value)
394  : std::string(value)
395  {
396  }
397  [[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(const StringThatDoesNotLikeToBeCopiedOrMoved &other)
398  : std::string(other)
399  {
400  CPPUNIT_FAIL("attempt to copy string: " + other);
401  }
402  [[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(StringThatDoesNotLikeToBeCopiedOrMoved &&other)
403  : std::string(std::move(other))
404  {
405  CPPUNIT_FAIL("attempt to move string: " + other);
406  }
407 };
408 
410 
412 {
413  // check whether type traits work as expected
414  static_assert(Helper::IsStringType<std::string, std::string>::value);
415  static_assert(!Helper::IsStringType<std::string, std::wstring>::value);
416  static_assert(Helper::IsStringType<std::wstring, std::wstring>::value);
417  static_assert(Helper::IsStringViewType<std::string, std::string_view>::value);
418  static_assert(!Helper::IsStringViewType<std::wstring, std::string_view>::value);
419  static_assert(Helper::IsStringViewType<std::wstring, std::wstring_view>::value);
420  static_assert(Helper::IsConvertibleToConstStringRef<std::string, ConvertibleToString>::value);
421 #ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
422  static_assert(!Helper::IsConvertibleToConstStringRef<std::filesystem::path::string_type, std::filesystem::path>::value,
423  "conversion via native() preferred");
424 #endif
425  static_assert(
426  !Helper::IsConvertibleToConstStringRef<std::string, std::string>::value, "yes, in this context this should not be considered convertible");
427  static_assert(!Helper::IsConvertibleToConstStringRef<std::wstring, ConvertibleToString>::value);
428 #ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
429  static_assert(Helper::IsConvertibleToConstStringRefViaNative<std::filesystem::path::string_type, std::filesystem::path>::value);
430 #endif
431  static_assert(!Helper::IsConvertibleToConstStringRefViaNative<std::string, std::string>::value);
432 
433  // conversion of string-tuple to string (the actual string builder)
434  const tuple<const char *, string, int, const char *> tuple("string1", "string2", 1234, "string3");
435  CPPUNIT_ASSERT_EQUAL("string1string21234string3"s, tupleToString(tuple));
436  CPPUNIT_ASSERT_EQUAL("foobarfoo2bar2"s, tupleToString("foo"s % "bar" % "foo2"s % "bar2"));
437  CPPUNIT_ASSERT_EQUAL("v2.3.0"s, argsToString("v2.", 3, '.', 0));
438  CPPUNIT_ASSERT_EQUAL("v2.3.0"s, argsToString('v', make_tuple(2, '.', 3, '.', 0)));
439 #ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
440  if constexpr (std::is_same_v<std::filesystem::path::value_type, std::string::value_type>) {
441  CPPUNIT_ASSERT_EQUAL("path: foo"s, argsToString("path: ", std::filesystem::path("foo")));
442  }
443 #endif
444 
445  // construction of string-tuple and final conversion to string works
446  CPPUNIT_ASSERT_EQUAL_MESSAGE("result can be passed to any function taking a std::string"s, "123456789"s, "12" % string("34") % '5' % 67 + "89");
447  constexpr double velocityExample = 27.0;
448  CPPUNIT_ASSERT_EQUAL_MESSAGE("real-word example"s, "velocity: 27 km/h (7.5 m/s)"s,
449  "velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)");
450  CPPUNIT_ASSERT_EQUAL_MESSAGE(
451  "regular + operator still works (no problems with ambiguity)"s, "regular + still works"s, "regular"s + " + still works");
452  CPPUNIT_ASSERT_EQUAL_MESSAGE("using string_view", "foobar123"s, "foo"sv % "bar"sv + 123);
453 
454  // check that for the internal tuple construction no copies are made
455  StringThatDoesNotLikeToBeCopiedOrMoved str(" happen ");
456  const StringThatDoesNotLikeToBeCopiedOrMoved str2("for this");
457  CPPUNIT_ASSERT_EQUAL("no copy/move should happen for this!"s,
458  argsToString(StringThatDoesNotLikeToBeCopiedOrMoved("no copy/move should"), str, str2, StringThatDoesNotLikeToBeCopiedOrMoved("!")));
459 }
CppUtilities::convertLatin1ToUtf8
CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified Latin-1 string to UTF-8.
Definition: stringconversion.cpp:179
CppUtilities::convertUtf16BEToUtf8
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
Definition: stringconversion.cpp:170
CppUtilities::truncateString
CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar='\0')
Truncates all characters after the first occurrence of the specified terminationChar and the terminat...
Definition: stringconversion.cpp:257
assertEqual
void assertEqual(const char *message, const std::uint8_t *expectedValues, size_t expectedSize, const StringData &actualValues)
Internally used for string encoding tests to check results.
Definition: conversiontests.cpp:177
ConversionTests
The ConversionTests class tests classes and functions provided by the files inside the conversion dir...
Definition: conversiontests.cpp:34
TEST_LE_CONVERSION
#define TEST_LE_CONVERSION(function)
Definition: conversiontests.cpp:131
CppUtilities::startsWith
bool startsWith(const StringType &str, const StringType &phrase)
Returns whether str starts with phrase.
Definition: stringconversion.h:213
ConversionTests::testBinaryConversions
void testBinaryConversions()
Tests most important binary conversions.
Definition: conversiontests.cpp:143
CppUtilities::splitStringSimple
Container splitStringSimple(const typename Container::value_type &string, const typename Container::value_type &delimiter, int maxParts=-1)
Splits the given string (which might also be a string view) at the specified delimiter.
Definition: stringconversion.h:185
ConversionTests::testEndianness
void testEndianness()
Tests whether macros for endianness are correct.
Definition: conversiontests.cpp:88
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(ConversionTests)
ConversionTests::tearDown
void tearDown()
Definition: conversiontests.cpp:51
TEST_CUSTOM_CONVERSION
#define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max)
Definition: conversiontests.cpp:133
CppUtilities::convertString
CPP_UTILITIES_EXPORT StringData convertString(const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor=1.0f)
Converts the specified string from one character set to another.
Definition: stringconversion.cpp:134
ConversionTests::testStringConversions
void testStringConversions()
Tests miscellaneous string conversions.
Definition: conversiontests.cpp:247
CppUtilities::convertUtf8ToUtf16BE
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (big-endian).
Definition: stringconversion.cpp:161
ConversionTests::ConversionTests
ConversionTests()
Definition: conversiontests.cpp:74
CppUtilities::bitrateToString
CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits=false)
Converts the specified bitrate in kbit/s to its equivalent std::string representation.
Definition: stringconversion.cpp:302
CppUtilities::toNormalInt
constexpr CPP_UTILITIES_EXPORT std::uint32_t toNormalInt(std::uint32_t synchsafeInt)
Returns a normal 32-bit integer converted from a 32-bit synchsafe integer.
Definition: binaryconversion.h:145
CppUtilities::joinStrings
ReturnType joinStrings(const Container &strings, const typename Container::value_type &delimiter=typename Container::value_type(), bool omitEmpty=false, const typename Container::value_type &leftClosure=typename Container::value_type(), const typename Container::value_type &rightClosure=typename Container::value_type())
Joins the given strings using the specified delimiter.
Definition: stringconversion.h:76
CppUtilities::max
constexpr T max(T first, T second)
Returns the greatest of the given items.
Definition: math.h:100
ConversionTests::testConversionException
void testConversionException()
Definition: conversiontests.cpp:80
CppUtilities::decodeBase64
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< std::uint8_t[]>, std::uint32_t > decodeBase64(const char *encodedStr, const std::uint32_t strSize)
Decodes the specified Base64 encoded string.
Definition: stringconversion.cpp:381
CppUtilities::toSynchsafeInt
constexpr CPP_UTILITIES_EXPORT std::uint32_t toSynchsafeInt(std::uint32_t normalInt)
Returns a 32-bit synchsafe integer converted from a normal 32-bit integer.
Definition: binaryconversion.h:135
CppUtilities
Contains all utilities provides by the c++utilities library.
Definition: argumentparser.h:17
i
constexpr int i
Definition: traitstests.cpp:106
TEST_BE_CONVERSION
#define TEST_BE_CONVERSION(function)
Definition: conversiontests.cpp:129
CppUtilities::asHexNumber
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:232
CppUtilities::tupleToString
StringType tupleToString(const std::tuple< Args... > &tuple)
Concatenates all strings hold by the specified tuple.
Definition: stringbuilder.h:250
CppUtilities::convertUtf16LEToUtf8
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
Definition: stringconversion.cpp:152
CppUtilities::dataSizeToString
CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte=false)
Converts the specified data size in byte to its equivalent std::string representation.
Definition: stringconversion.cpp:270
CppUtilities::argsToString
StringType argsToString(Args &&...args)
Definition: stringbuilder.h:258
ConversionTests::testSwapOrderFunctions
void testSwapOrderFunctions()
Tests swap order functions.
Definition: conversiontests.cpp:167
CppUtilities::ConversionException
The ConversionException class is thrown by the various conversion functions of this library when a co...
Definition: conversionexception.h:11
CppUtilities::min
constexpr T min(T first, T second)
Returns the smallest of the given items.
Definition: math.h:88
CppUtilities::convertUtf8ToLatin1
CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to Latin-1.
Definition: stringconversion.cpp:188
CppUtilities::StringData
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
Definition: stringconversion.h:40
CppUtilities::endsWith
bool endsWith(const StringType &str, const StringType &phrase)
Returns whether str ends with phrase.
Definition: stringconversion.h:250
ConversionTests::setUp
void setUp()
Definition: conversiontests.cpp:48
CppUtilities::swapOrder
constexpr CPP_UTILITIES_EXPORT std::uint16_t swapOrder(std::uint16_t value)
Swaps the byte order of the specified 16-bit unsigned integer.
Definition: binaryconversion.h:154
CppUtilities::splitString
Container splitString(const typename Container::value_type &string, const typename Container::value_type &delimiter, EmptyPartsTreat emptyPartsRole=EmptyPartsTreat::Keep, int maxParts=-1)
Splits the given string at the specified delimiter.
Definition: stringconversion.h:138
LE_STR_FOR_ENDIANNESS
#define LE_STR_FOR_ENDIANNESS(name)
Selects right string for little-endian checks.
ConversionTests::testStringEncodingConversions
void testStringEncodingConversions()
Tests string encoding conversions.
Definition: conversiontests.cpp:210
BE_STR_FOR_ENDIANNESS
#define BE_STR_FOR_ENDIANNESS(name)
Selects right string for big-endian checks.
ConversionTests::testStringBuilder
void testStringBuilder()
Definition: conversiontests.cpp:411
CppUtilities::numberToString
StringType numberToString(IntegralType number, typename StringType::value_type base=10)
Converts the given number to its equivalent string representation using the specified base.
Definition: stringconversion.h:371
CppUtilities::convertUtf8ToUtf16LE
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (little-endian).
Definition: stringconversion.cpp:143
CppUtilities::encodeBase64
CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize)
Encodes the specified data to Base64.
Definition: stringconversion.cpp:341