xref: /llvm-project/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp (revision bcf9fb9802baad73e2f2acf142519e0dcfd3cc7f)
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 <memory>
19 #include <string>
20 
21 #include "make_string.h"
22 #include "test_macros.h"
23 #include "asan_testing.h"
24 
25 template <class S>
26 constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
27   assert(N > k);
28   assert(new_capacity >= N);
29   auto s = S(k, 'a');
30   s.resize_and_overwrite(new_capacity, [&](auto* p, auto n) {
31     assert(n == new_capacity);
32     LIBCPP_ASSERT(s.size() == new_capacity);
33     LIBCPP_ASSERT(std::to_address(s.begin()) == p);
34     assert(std::all_of(p, p + k, [](const auto ch) { return ch == 'a'; }));
35     std::fill(p + k, p + n, 'b');
36     p[n] = 'c'; // will be overwritten
37     return N;
38   });
39   const S expected = S(k, 'a') + S(N - k, 'b');
40   assert(s == expected);
41   assert(s.c_str()[N] == '\0');
42   LIBCPP_ASSERT(is_string_asan_correct(s));
43 }
44 
45 template <class S>
46 constexpr void test_truncating(std::size_t o, size_t N) {
47   assert(N < o);
48   auto s = S(o, 'a');
49   s.resize_and_overwrite(N, [&](auto* p, auto n) {
50     assert(n == N);
51     LIBCPP_ASSERT(s.size() == n);
52     LIBCPP_ASSERT(std::to_address(s.begin()) == p);
53     assert(std::all_of(p, p + n, [](auto ch) { return ch == 'a'; }));
54     p[n - 1] = 'b';
55     p[n]     = 'c'; // will be overwritten
56     return n;
57   });
58   const S expected = S(N - 1, 'a') + S(1, 'b');
59   assert(s == expected);
60   assert(s.c_str()[N] == '\0');
61   LIBCPP_ASSERT(is_string_asan_correct(s));
62 }
63 
64 template <class String>
65 constexpr bool test() {
66   test_appending<String>(10, 15, 15);
67   test_appending<String>(10, 15, 20);
68   test_appending<String>(10, 40, 40);
69   test_appending<String>(10, 40, 50);
70   test_appending<String>(30, 35, 35);
71   test_appending<String>(30, 35, 45);
72   test_appending<String>(10, 15, 30);
73   test_truncating<String>(15, 10);
74   test_truncating<String>(40, 35);
75   test_truncating<String>(40, 10);
76 
77   return true;
78 }
79 
80 void test_value_categories() {
81   std::string s;
82   s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; });
83   LIBCPP_ASSERT(is_string_asan_correct(s));
84   s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; });
85   LIBCPP_ASSERT(is_string_asan_correct(s));
86   struct RefQualified {
87     int operator()(char*, std::size_t) && { return 0; }
88   };
89   s.resize_and_overwrite(10, RefQualified{});
90   LIBCPP_ASSERT(is_string_asan_correct(s));
91 }
92 
93 int main(int, char**) {
94   test<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>();
95   test<std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>>();
96   test<std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t>>>();
97   test<std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>>>();
98 
99   static_assert(test<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>());
100   static_assert(test<std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>>());
101   static_assert(test<std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t>>>());
102   static_assert(test<std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>>>());
103 
104 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
105   test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106   static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107 #endif
108   return 0;
109 }
110