1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10 
11 // <string>
12 
13 // template<class Operation>
14 // void resize_and_overwrite(size_type n, Operation op)
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <string>
19 
20 #include "make_string.h"
21 #include "test_macros.h"
22 
23 template <class S>
test_appending(size_t k,size_t N,size_t new_capacity)24 constexpr void test_appending(size_t k, size_t N, size_t new_capacity) {
25   assert(N > k);
26   assert(new_capacity >= N);
27   auto s = S(k, 'a');
28   s.resize_and_overwrite(new_capacity, [&](auto* p, auto n) {
29     assert(n == new_capacity);
30     LIBCPP_ASSERT(s.size() == new_capacity);
31     LIBCPP_ASSERT(s.begin().base() == p);
32     assert(std::all_of(p, p + k, [](const auto ch) { return ch == 'a'; }));
33     std::fill(p + k, p + n, 'b');
34     p[n] = 'c'; // will be overwritten
35     return N;
36   });
37   const S expected = S(k, 'a') + S(N - k, 'b');
38   assert(s == expected);
39   assert(s.c_str()[N] == '\0');
40 }
41 
42 template <class S>
test_truncating(size_t o,size_t N)43 constexpr void test_truncating(size_t o, size_t N) {
44   assert(N < o);
45   auto s = S(o, 'a');
46   s.resize_and_overwrite(N, [&](auto* p, auto n) {
47     assert(n == N);
48     LIBCPP_ASSERT(s.size() == n);
49     LIBCPP_ASSERT(s.begin().base() == p);
50     assert(std::all_of(p, p + n, [](auto ch) { return ch == 'a'; }));
51     p[n - 1] = 'b';
52     p[n] = 'c'; // will be overwritten
53     return n;
54   });
55   const S expected = S(N - 1, 'a') + S(1, 'b');
56   assert(s == expected);
57   assert(s.c_str()[N] == '\0');
58 }
59 
60 template <class CharT>
test()61 constexpr bool test() {
62   using S = std::basic_string<CharT>;
63   test_appending<S>(10, 15, 15);
64   test_appending<S>(10, 15, 20);
65   test_appending<S>(10, 40, 40);
66   test_appending<S>(10, 40, 50);
67   test_appending<S>(30, 35, 35);
68   test_appending<S>(30, 35, 45);
69   test_appending<S>(10, 15, 30);
70   test_truncating<S>(15, 10);
71   test_truncating<S>(40, 35);
72   test_truncating<S>(40, 10);
73 
74   return true;
75 }
76 
test_value_categories()77 void test_value_categories() {
78   std::string s;
79   s.resize_and_overwrite(10, [](char*&&, size_t&&) { return 0; });
80   s.resize_and_overwrite(10, [](char* const&, const size_t&) { return 0; });
81   struct RefQualified {
82     int operator()(char*, size_t) && { return 0; }
83   };
84   s.resize_and_overwrite(10, RefQualified{});
85 }
86 
main(int,char **)87 int main(int, char**) {
88   test<char>();
89   test<char8_t>();
90   test<char16_t>();
91   test<char32_t>();
92 
93   static_assert(test<char>());
94   static_assert(test<char8_t>());
95   static_assert(test<char16_t>());
96   static_assert(test<char32_t>());
97 
98 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
99   test<wchar_t>();
100   static_assert(test<wchar_t>());
101 #endif
102   return 0;
103 }
104