starts_with.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Range v3 library
  2. //
  3. // Copyright 2019 Christopher Di Bella
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. #include <range/v3/algorithm/starts_with.hpp>
  12. #include "../simple_test.hpp"
  13. #include "../test_iterators.hpp"
  14. #include <forward_list>
  15. #include <range/v3/range/conversion.hpp>
  16. #include <range/v3/view/iota.hpp>
  17. #include <range/v3/view/slice.hpp>
  18. #include <range/v3/view/take_exactly.hpp>
  19. #include <range/v3/view/istream.hpp>
  20. #include <sstream>
  21. #include <vector>
  22. void test_defaults()
  23. {
  24. using namespace ranges;
  25. { // checks starts_with works for input ranges
  26. constexpr auto full_latin_alphabet = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
  27. auto const partial_latin_alphabet = "a b c d";
  28. {
  29. auto long_stream = std::istringstream{full_latin_alphabet};
  30. auto short_stream = std::istringstream{partial_latin_alphabet};
  31. auto r1 = istream<char>(long_stream);
  32. auto r2 = istream<char>(short_stream);
  33. CHECK(starts_with(begin(r1), end(r1), begin(r2), end(r2)));
  34. }
  35. {
  36. auto long_stream = std::istringstream{full_latin_alphabet};
  37. auto short_stream = std::istringstream{partial_latin_alphabet};
  38. auto r1 = istream<char>(long_stream);
  39. auto r2 = istream<char>(short_stream);
  40. CHECK(!starts_with(begin(r2), end(r2), begin(r1), end(r1)));
  41. }
  42. {
  43. auto long_stream = std::istringstream{full_latin_alphabet};
  44. auto short_stream = std::istringstream{partial_latin_alphabet};
  45. CHECK(starts_with(istream<char>(long_stream), istream<char>(short_stream)));
  46. }
  47. {
  48. auto long_stream = std::istringstream{full_latin_alphabet};
  49. auto short_stream = std::istringstream{partial_latin_alphabet};
  50. CHECK(!starts_with(istream<char>(short_stream), istream<char>(long_stream)));
  51. }
  52. }
  53. { // checks starts_with works for random-access ranges
  54. #ifdef RANGES_WORKAROUND_MSVC_779708
  55. auto const long_range = views::iota(0, 100) | to<std::vector>();
  56. auto const short_range = views::iota(0, 10) | to<std::vector>();
  57. #else // ^^^ workaround / no workaround vvv
  58. auto const long_range = views::iota(0, 100) | to<std::vector>;
  59. auto const short_range = views::iota(0, 10) | to<std::vector>;
  60. #endif // RANGES_WORKAROUND_MSVC_779708
  61. CHECK(starts_with(begin(long_range), end(long_range), begin(short_range), end(short_range)));
  62. CHECK(starts_with(long_range, short_range));
  63. CHECK(!starts_with(begin(short_range), end(short_range), begin(long_range), end(long_range)));
  64. CHECK(!starts_with(short_range, long_range));
  65. }
  66. { // checks starts_with works for random-access ranges with arbitrary sentinels
  67. auto const long_range = views::iota(0);
  68. auto const short_range = views::iota(0) | views::take_exactly(100);
  69. CHECK(starts_with(begin(long_range), end(long_range), begin(short_range), end(short_range)));
  70. CHECK(starts_with(long_range, short_range));
  71. CHECK(!starts_with(begin(short_range), end(short_range), begin(long_range), end(long_range)));
  72. CHECK(!starts_with(short_range, long_range));
  73. }
  74. { // checks starts_with identifies a subrange
  75. auto const range = views::iota(0) | views::slice(50, 100);
  76. auto const offset = views::iota(50, 100);
  77. CHECK(starts_with(begin(range), end(range), begin(offset), end(offset)));
  78. CHECK(starts_with(range, offset));
  79. CHECK(starts_with(begin(offset), end(offset), begin(range), end(range)));
  80. CHECK(starts_with(offset, range));
  81. }
  82. { // checks starts_with identifies when two ranges don't have the same start sequence
  83. auto const first = views::iota(0, 1'000);
  84. auto const second = views::iota(10, 1'000);
  85. CHECK(!starts_with(begin(first), end(first), begin(second), end(second)));
  86. CHECK(!starts_with(first, second));
  87. CHECK(!starts_with(begin(second), end(second), begin(first), end(first)));
  88. CHECK(!starts_with(second, first));
  89. }
  90. }
  91. void test_comparison()
  92. {
  93. using namespace ranges;
  94. auto const long_range = views::iota(0, 100);
  95. auto const short_range = views::iota(1, 51);
  96. CHECK(starts_with(begin(long_range), end(long_range), begin(short_range), end(short_range),
  97. less{}));
  98. CHECK(starts_with(long_range, short_range, less{}));
  99. CHECK(!starts_with(begin(long_range), end(long_range), begin(short_range), end(short_range),
  100. greater{}));
  101. CHECK(!starts_with(long_range, short_range, greater{}));
  102. }
  103. int main()
  104. {
  105. ::test_defaults();
  106. ::test_comparison();
  107. return ::test_result();
  108. }