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
25template <class S>
26constexpr 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
45template <class S>
46constexpr 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
64template <class String>
65constexpr 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
80void 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
93int 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

source code of libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp