misc.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "simple/support/misc.hpp"
  2. #include <cassert>
  3. #include <string>
  4. using namespace simple::support;
  5. template <typename T>
  6. constexpr auto tos (T v) { using std::to_string; return to_string(v); }
  7. void StringToNumber()
  8. {
  9. assert( 123 == ston<int>("123") );
  10. assert( -0xabc == ston<int>("-0xabc") );
  11. assert( -0123 == ston<int>("-0123") );
  12. assert( 123.123f == ston<float>(tos(123.123f)) );
  13. assert( -123.123 == ston<double>(tos(-123.123)) );
  14. assert( 123.123l == ston<long double>(tos(123.123l)) );
  15. assert( 123 == ston<int>("123xyz") );
  16. assert( 23 == ston<int>("123xyz", 1) );
  17. std::size_t i = 0;
  18. assert( 123 == ston<int>("123xyz", &i) );
  19. assert( 3 == i );
  20. i = 1;
  21. assert( 23 == ston<int>("123xyz", &i) );
  22. assert( 3 == i );
  23. try {
  24. ston<int>("abc123");
  25. assert( ((void)"ston did not throw an invalid argument exception", false) );
  26. } catch(const std::invalid_argument & e) { }
  27. try {
  28. ston<signed char>(std::to_string(std::numeric_limits<signed char>::max()) + '0');
  29. assert( ((void)"ston did not throw an out of range exception", false) );
  30. } catch(const std::out_of_range & e) { }
  31. try {
  32. ston<unsigned char>(std::to_string(std::numeric_limits<unsigned char>::max()) + '0');
  33. assert( ((void)"ston did not throw an out of range exception", false) );
  34. } catch(const std::out_of_range & e) { }
  35. }
  36. void StringToNumericRange()
  37. {
  38. assert( (range<int>{12,34} == storn<int>("12-34")) );
  39. assert( (range<int>{12,24} == storn<int>("12:12")) );
  40. assert( (range<int>{-0xcd,-0xab} == storn<int>("-0xcd,-0xab")) );
  41. assert( (range<float>{12.12f,34.34f} == storn<float>(tos(12.12f) + '-' + tos(34.34f))) );
  42. assert( (range<double>{-12.12,12.12} == storn<double>(tos(-12.12) + ':' + tos(24.24))) );
  43. assert( (range<int>{12,34} == storn<int>("12-34.xyz")) );
  44. assert( (range<int>{2,34} == storn<int>("12-34.xyz", 1)) );
  45. std::size_t i = 0;
  46. assert( (range<int>{12,34} == storn<int>("12-34.xyz", &i)) );
  47. assert( 5 == i );
  48. i = 1;
  49. assert( (range<int>{2,34} == storn<int>("12-34.xyz", &i)) );
  50. assert( 5 == i );
  51. try {
  52. storn<int>("1232");
  53. assert( ((void)"storn did not throw an invalid argument exception", false) );
  54. } catch(const std::invalid_argument & e) { }
  55. try {
  56. storn<int>("12: ");
  57. assert( ((void)"storn did not throw an invalid argument exception", false) );
  58. } catch(const std::invalid_argument & e) { }
  59. try {
  60. storn<int>("12 : 32");
  61. assert( ((void)"storn did not throw an invalid argument exception", false) );
  62. } catch(const std::invalid_argument & e) { }
  63. }
  64. void NumericRangeToString()
  65. {
  66. assert( "12-34" == tos(range<int>{12,34}) );
  67. assert( "12~34" == to_string(range<int>{12,34}, '~') );
  68. assert( "12:34" == to_string(range<int>{12,46}, ':') );
  69. assert( tos(-12.34) + '-' + tos(12.34) == tos(range<double>{-12.34,12.34}) );
  70. }
  71. void SimplifiedToNumber()
  72. {
  73. assert( 123 == *to_<int>("123") );
  74. assert( -0xabc == *to_<int>("-0xabc") );
  75. assert( -0123 == *to_<int>("-0123") );
  76. assert( 123.123f == *to_<float>(tos(123.123f)) );
  77. assert( -123.123 == *to_<double>(tos(-123.123)) );
  78. assert( 123.123l == *to_<long double>(tos(123.123l)) );
  79. assert( 123 == *to_<int>("123xyz") );
  80. assert(std::nullopt == to_<int>("abc123"));
  81. assert(std::nullopt ==
  82. to_<signed char>(std::to_string(std::numeric_limits<signed char>::max()) + '0'));
  83. assert(std::nullopt ==
  84. to_<unsigned char>(std::to_string(std::numeric_limits<unsigned char>::max()) + '0'));
  85. }
  86. void RangeReference()
  87. {
  88. using std::begin;
  89. using std::end;
  90. const std::string prefix = "Permaprefix";
  91. std::string stuff{prefix};
  92. range temporef{begin(stuff), end(stuff)};
  93. assert( std::equal(begin(temporef), end(temporef),
  94. begin(prefix), end(prefix)) );
  95. offset_range permaref{
  96. stuff,
  97. make_range(stuff) - begin(stuff)
  98. };
  99. assert( std::equal(begin(permaref), end(permaref),
  100. begin(prefix), end(prefix)) );
  101. stuff += " now this a really really long long paragraph of text, that should by all means cause reallocation and stuff, so the iterators in temporef range will be invalidated, while permaref that uses indices will remain valid and usable... though it doesn't really matter if it actually relocates since there is no way to check any of this, you'll just have to believe me and trust me and never ever let me go...";
  102. // can't do this anymore
  103. // assert( std::equal(begin(temporef), end(temporef),
  104. // begin(prefix), end(prefix)) );
  105. // asan might not catch this, because of small string optimization, and since you are allowed to reinterpret anything as char* it might not even be UB dependent on the implementation, but then the assertion will fail at least
  106. // otherwise the assertion might not fail, if the old/freed memory happens to remain untouched by either the system or the allocator
  107. // so asan and assert together can kind of catch this I guess
  108. // TODO: __gnu_debug::string (but not std::string under _GLIBCXX_DEBUG, it's an obscure exception) does catch this reliably, so that's a thing to consider for unit testing purposes in general
  109. // all ok here
  110. assert( std::equal(begin(permaref), end(permaref),
  111. begin(prefix), end(prefix)) );
  112. }
  113. void Deref()
  114. {
  115. static_assert(can_deref_v<char*>);
  116. static_assert(can_deref_v<char**>);
  117. static_assert(not can_deref_v<char>);
  118. char a = 10;
  119. auto aa = &a;
  120. auto aaa = &aa;
  121. assert( deref(aaa) == 10 );
  122. assert( deref(aa) == 10 );
  123. assert( deref(a) == 10 );
  124. }
  125. int main()
  126. {
  127. StringToNumber();
  128. StringToNumericRange();
  129. NumericRangeToString();
  130. SimplifiedToNumber();
  131. RangeReference();
  132. Deref();
  133. return 0;
  134. }