//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // FIXME: This takes over an hour to compile, disable for now. // UNSUPPORTED: LIBCXX-AMDGPU-FIXME // UNSUPPORTED: LIBCXX-NVPTX-FIXME // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=10000000 // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=70000000 // template R> // constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23 #include #include #include "../../../../containers/sequences/insert_range_sequence_containers.h" #include "test_macros.h" template concept HasReplaceWithRange = requires(std::string& c, Range&& range) { c.replace_with_range(c.end(), c.end(), std::forward(range)); }; constexpr bool test_constraints_replace_with_range() { // Input range with the same value type. static_assert(HasReplaceWithRange>); // Input range with a convertible value type. static_assert(HasReplaceWithRange>); // Input range with a non-convertible value type. static_assert(!HasReplaceWithRange>); // Not an input range. static_assert(!HasReplaceWithRange); static_assert(!HasReplaceWithRange); static_assert(!HasReplaceWithRange); return true; } using StrBuffer = Buffer; struct TestCaseReplacement { StrBuffer initial; std::size_t from = 0; std::size_t to = 0; StrBuffer input; StrBuffer expected; }; // Permutation matrix: // - initial string: empty / one-element / n elements; // - cut starts from: beginning / middle / end; // - cut size: empty / one-element / several elements / until the end; // - input range: empty / one-element / middle-sized / longer than SSO / longer than the current string capacity. // Empty string. constexpr TestCaseReplacement EmptyString_End_EmptyCut_EmptyRange{ .initial = "", .from = 0, .to = 0, .input = "", .expected = ""}; constexpr TestCaseReplacement EmptyString_End_EmptyCut_OneElementRange{ .initial = "", .from = 0, .to = 0, .input = "a", .expected = "a"}; constexpr TestCaseReplacement EmptyString_End_EmptyCut_MidRange{ .initial = "", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiou"}; constexpr TestCaseReplacement EmptyString_End_EmptyCut_LongRange{ .initial = "", .from = 0, .to = 0, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789"}; // One-element string. constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_EmptyRange{ .initial = "B", .from = 0, .to = 0, .input = "", .expected = "B"}; constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_OneElementRange{ .initial = "B", .from = 0, .to = 0, .input = "a", .expected = "aB"}; constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_MidRange{ .initial = "B", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiouB"}; constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_LongRange{ .initial = "B", .from = 0, .to = 0, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789B"}; constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_EmptyRange{ .initial = "B", .from = 0, .to = 1, .input = "", .expected = ""}; constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_OneElementRange{ .initial = "B", .from = 0, .to = 1, .input = "a", .expected = "a"}; constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_MidRange{ .initial = "B", .from = 0, .to = 1, .input = "aeiou", .expected = "aeiou"}; constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_LongRange{ .initial = "B", .from = 0, .to = 1, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789"}; constexpr TestCaseReplacement OneElementString_End_EmptyCut_EmptyRange{ .initial = "B", .from = 1, .to = 1, .input = "", .expected = "B"}; constexpr TestCaseReplacement OneElementString_End_EmptyCut_OneElementRange{ .initial = "B", .from = 1, .to = 1, .input = "a", .expected = "Ba"}; constexpr TestCaseReplacement OneElementString_End_EmptyCut_MidRange{ .initial = "B", .from = 1, .to = 1, .input = "aeiou", .expected = "Baeiou"}; constexpr TestCaseReplacement OneElementString_End_EmptyCut_LongRange{ .initial = "B", .from = 1, .to = 1, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "Babcdefghijklmnopqrstuvwxyz0123456789"}; // Short string (using SSO). // Replace at the beginning. constexpr TestCaseReplacement ShortString_Begin_EmptyCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "", .expected = "_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_EmptyCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "a", .expected = "a_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_EmptyCut_MidRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiou_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_EmptyCut_LongRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_OneElementCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "", .expected = "BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_OneElementCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "a", .expected = "aBCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_OneElementCut_MidRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "aeiou", .expected = "aeiouBCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_OneElementCut_LongRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "", .expected = "DFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "a", .expected = "aDFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_MidRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "aeiou", .expected = "aeiouDFGHJ_"}; // Note: this test case switches from SSO to non-SSO. constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_LongRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789DFGHJ_"}; constexpr TestCaseReplacement ShortString_Begin_CutToEnd_EmptyRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "", .expected = ""}; constexpr TestCaseReplacement ShortString_Begin_CutToEnd_OneElementRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "a", .expected = "a"}; constexpr TestCaseReplacement ShortString_Begin_CutToEnd_MidRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "aeiou", .expected = "aeiou"}; // Note: this test case switches from SSO to non-SSO. constexpr TestCaseReplacement ShortString_Begin_CutToEnd_LongRange{ .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789"}; // Replace in the middle. constexpr TestCaseReplacement ShortString_Mid_EmptyCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "", .expected = "_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_EmptyCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "a", .expected = "_BCDaFGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_EmptyCut_MidRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "aeiou", .expected = "_BCDaeiouFGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_EmptyCut_LongRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789FGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_OneElementCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "", .expected = "_BCDGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_OneElementCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "a", .expected = "_BCDaGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_OneElementCut_MidRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "aeiou", .expected = "_BCDaeiouGHJ_"}; constexpr TestCaseReplacement ShortString_Mid_OneElementCut_LongRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789GHJ_"}; constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "", .expected = "_BCDJ_"}; constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "a", .expected = "_BCDaJ_"}; constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_MidRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "aeiou", .expected = "_BCDaeiouJ_"}; constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_LongRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789J_"}; constexpr TestCaseReplacement ShortString_Mid_CutToEnd_EmptyRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "", .expected = "_BCD"}; constexpr TestCaseReplacement ShortString_Mid_CutToEnd_OneElementRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "a", .expected = "_BCDa"}; constexpr TestCaseReplacement ShortString_Mid_CutToEnd_MidRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "aeiou", .expected = "_BCDaeiou"}; constexpr TestCaseReplacement ShortString_Mid_CutToEnd_LongRange{ .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789"}; // Replace at the end. constexpr TestCaseReplacement ShortString_End_EmptyCut_EmptyRange{ .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "", .expected = "_BCDFGHJ_"}; constexpr TestCaseReplacement ShortString_End_EmptyCut_OneElementRange{ .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "a", .expected = "_BCDFGHJ_a"}; constexpr TestCaseReplacement ShortString_End_EmptyCut_MidRange{ .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "aeiou", .expected = "_BCDFGHJ_aeiou"}; constexpr TestCaseReplacement ShortString_End_EmptyCut_LongRange{ .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_BCDFGHJ_abcdefghijklmnopqrstuvwxyz0123456789"}; // Long string (no SSO). // Replace at the beginning. constexpr TestCaseReplacement LongString_Begin_EmptyCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 0, .input = "", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_EmptyCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 0, .input = "a", .expected = "a_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_EmptyCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiou_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_EmptyCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 0, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_EmptyCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 0, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_OneElementCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 1, .input = "", .expected = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_OneElementCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 1, .input = "a", .expected = "aABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_OneElementCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 1, .input = "aeiou", .expected = "aeiouABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_OneElementCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 1, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_OneElementCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 1, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_MidSizedCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 3, .input = "", .expected = "CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_MidSizedCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 3, .input = "a", .expected = "aCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_MidSizedCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 3, .input = "aeiou", .expected = "aeiouCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_MidSizedCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 3, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_MidSizedCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 3, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Begin_CutToEnd_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "", .expected = ""}; constexpr TestCaseReplacement LongString_Begin_CutToEnd_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "a", .expected = "a"}; constexpr TestCaseReplacement LongString_Begin_CutToEnd_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "aeiou", .expected = "aeiou"}; constexpr TestCaseReplacement LongString_Begin_CutToEnd_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789"}; constexpr TestCaseReplacement LongString_Begin_CutToEnd_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789"}; // Replace in the middle. constexpr TestCaseReplacement LongString_Mid_EmptyCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 18, .input = "", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_EmptyCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 18, .input = "a", .expected = "_ABCDEFGHIJKLMNOPQaRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_EmptyCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 18, .input = "aeiou", .expected = "_ABCDEFGHIJKLMNOPQaeiouRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_EmptyCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 18, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789RSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_EmptyCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 18, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQ" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "RSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_OneElementCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 19, .input = "", .expected = "_ABCDEFGHIJKLMNOPQSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_OneElementCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 19, .input = "a", .expected = "_ABCDEFGHIJKLMNOPQaSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_OneElementCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 19, .input = "aeiou", .expected = "_ABCDEFGHIJKLMNOPQaeiouSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_OneElementCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 19, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789STUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_OneElementCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 19, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQ" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "STUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_MidSizedCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 21, .input = "", .expected = "_ABCDEFGHIJKLMNOPQUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_MidSizedCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 21, .input = "a", .expected = "_ABCDEFGHIJKLMNOPQaUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_MidSizedCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 21, .input = "aeiou", .expected = "_ABCDEFGHIJKLMNOPQaeiouUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_MidSizedCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 21, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789UVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_MidSizedCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 21, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQ" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789" "UVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_Mid_CutToEnd_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 38, .input = "", .expected = "_ABCDEFGHIJKLMNOPQ"}; constexpr TestCaseReplacement LongString_Mid_CutToEnd_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 38, .input = "a", .expected = "_ABCDEFGHIJKLMNOPQa"}; constexpr TestCaseReplacement LongString_Mid_CutToEnd_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 38, .input = "aeiou", .expected = "_ABCDEFGHIJKLMNOPQaeiou"}; constexpr TestCaseReplacement LongString_Mid_CutToEnd_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789"}; constexpr TestCaseReplacement LongString_Mid_CutToEnd_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 18, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQ" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789"}; // Replace at the end. constexpr TestCaseReplacement LongString_End_EmptyCut_EmptyRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 38, .to = 38, .input = "", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"}; constexpr TestCaseReplacement LongString_End_EmptyCut_OneElementRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 38, .to = 38, .input = "a", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_a"}; constexpr TestCaseReplacement LongString_End_EmptyCut_MidRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 38, .to = 38, .input = "aeiou", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_aeiou"}; constexpr TestCaseReplacement LongString_End_EmptyCut_LongRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 38, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_abcdefghijklmnopqrstuvwxyz0123456789"}; constexpr TestCaseReplacement LongString_End_EmptyCut_LongerThanCapacityRange{ .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 38, .to = 38, .input = "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789", .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789_" "abcdefghijklmnopqrstuvwxyz0123456789"}; template constexpr void test_string_replace_with_range() { auto test = [&](const TestCaseReplacement& test_case) { using Container = std::basic_string, Alloc>; auto get_pos = [](auto& c, auto index) { return std::ranges::next(c.begin(), index); }; Container c(test_case.initial.begin(), test_case.initial.end()); auto in = wrap_input(test_case.input); auto from = get_pos(c, test_case.from); auto to = get_pos(c, test_case.to); Container& result = c.replace_with_range(from, to, in); assert(&result == &c); LIBCPP_ASSERT(c.__invariants()); return std::ranges::equal(c, test_case.expected); }; { // Empty string. // empty_str.replace_with_range(end, end, empty_range) assert(test(EmptyString_End_EmptyCut_EmptyRange)); // empty_str.replace_with_range(end, end, one_element_range) assert(test(EmptyString_End_EmptyCut_OneElementRange)); // empty_str.replace_with_range(end, end, mid_range) assert(test(EmptyString_End_EmptyCut_MidRange)); // empty_str.replace_with_range(end, end, long_range) assert(test(EmptyString_End_EmptyCut_LongRange)); } { // One-element string. // one_element_str.replace_with_range(begin, begin, empty_range) assert(test(OneElementString_Begin_EmptyCut_EmptyRange)); // one_element_str.replace_with_range(begin, begin, one_element_range) assert(test(OneElementString_Begin_EmptyCut_OneElementRange)); // one_element_str.replace_with_range(begin, begin, mid_range) assert(test(OneElementString_Begin_EmptyCut_MidRange)); // one_element_str.replace_with_range(begin, begin, long_range) assert(test(OneElementString_Begin_EmptyCut_LongRange)); // one_element_str.replace_with_range(begin, begin + 1, empty_range) assert(test(OneElementString_Begin_OneElementCut_EmptyRange)); // one_element_str.replace_with_range(begin, begin + 1, one_element_range) assert(test(OneElementString_Begin_OneElementCut_OneElementRange)); // one_element_str.replace_with_range(begin, begin + 1, mid_range) assert(test(OneElementString_Begin_OneElementCut_MidRange)); // one_element_str.replace_with_range(begin, begin + 1, long_range) assert(test(OneElementString_Begin_OneElementCut_LongRange)); // one_element_str.replace_with_range(end, end, empty_range) assert(test(OneElementString_End_EmptyCut_EmptyRange)); // one_element_str.replace_with_range(end, end, one_element_range) assert(test(OneElementString_End_EmptyCut_OneElementRange)); // one_element_str.replace_with_range(end, end, mid_range) assert(test(OneElementString_End_EmptyCut_MidRange)); // one_element_str.replace_with_range(end, end, long_range) assert(test(OneElementString_End_EmptyCut_LongRange)); } { // Short string. // Replace at the beginning. // short_str.replace_with_range(begin, begin, empty_range) assert(test(ShortString_Begin_EmptyCut_EmptyRange)); // short_str.replace_with_range(begin, begin, one_element_range) assert(test(ShortString_Begin_EmptyCut_OneElementRange)); // short_str.replace_with_range(begin, begin, mid_range) assert(test(ShortString_Begin_EmptyCut_MidRange)); // short_str.replace_with_range(begin, begin, long_range) assert(test(ShortString_Begin_EmptyCut_LongRange)); // short_str.replace_with_range(begin, begin + 1, empty_range) assert(test(ShortString_Begin_OneElementCut_EmptyRange)); // short_str.replace_with_range(begin, begin + 1, one_element_range) assert(test(ShortString_Begin_OneElementCut_OneElementRange)); // short_str.replace_with_range(begin, begin + 1, mid_range) assert(test(ShortString_Begin_OneElementCut_MidRange)); // short_str.replace_with_range(begin, begin + 1, long_range) assert(test(ShortString_Begin_OneElementCut_LongRange)); // short_str.replace_with_range(begin, begin + 3, empty_range) assert(test(ShortString_Begin_MidSizedCut_EmptyRange)); // short_str.replace_with_range(begin, begin + 3, one_element_range) assert(test(ShortString_Begin_MidSizedCut_OneElementRange)); // short_str.replace_with_range(begin, begin + 3, mid_range) assert(test(ShortString_Begin_MidSizedCut_MidRange)); // short_str.replace_with_range(begin, begin + 3, long_range) assert(test(ShortString_Begin_MidSizedCut_LongRange)); // short_str.replace_with_range(begin, end, empty_range) assert(test(ShortString_Begin_CutToEnd_EmptyRange)); // short_str.replace_with_range(begin, end, one_element_range) assert(test(ShortString_Begin_CutToEnd_OneElementRange)); // short_str.replace_with_range(begin, end, mid_range) assert(test(ShortString_Begin_CutToEnd_MidRange)); // short_str.replace_with_range(begin, end, long_range) assert(test(ShortString_Begin_CutToEnd_LongRange)); // Replace in the middle. // short_str.replace_with_range(mid, mid, empty_range) assert(test(ShortString_Mid_EmptyCut_EmptyRange)); // short_str.replace_with_range(mid, mid, one_element_range) assert(test(ShortString_Mid_EmptyCut_OneElementRange)); // short_str.replace_with_range(mid, mid, mid_range) assert(test(ShortString_Mid_EmptyCut_MidRange)); // short_str.replace_with_range(mid, mid, long_range) assert(test(ShortString_Mid_EmptyCut_LongRange)); // short_str.replace_with_range(mid, mid + 1, empty_range) assert(test(ShortString_Mid_OneElementCut_EmptyRange)); // short_str.replace_with_range(mid, mid + 1, one_element_range) assert(test(ShortString_Mid_OneElementCut_OneElementRange)); // short_str.replace_with_range(mid, mid + 1, mid_range) assert(test(ShortString_Mid_OneElementCut_MidRange)); // short_str.replace_with_range(mid, mid + 1, long_range) assert(test(ShortString_Mid_OneElementCut_LongRange)); // short_str.replace_with_range(mid, mid + 3, empty_range) assert(test(ShortString_Mid_MidSizedCut_EmptyRange)); // short_str.replace_with_range(mid, mid + 3, one_element_range) assert(test(ShortString_Mid_MidSizedCut_OneElementRange)); // short_str.replace_with_range(mid, mid + 3, mid_range) assert(test(ShortString_Mid_MidSizedCut_MidRange)); // short_str.replace_with_range(mid, mid + 3, long_range) assert(test(ShortString_Mid_MidSizedCut_LongRange)); // short_str.replace_with_range(mid, end, empty_range) assert(test(ShortString_Mid_CutToEnd_EmptyRange)); // short_str.replace_with_range(mid, end, one_element_range) assert(test(ShortString_Mid_CutToEnd_OneElementRange)); // short_str.replace_with_range(mid, end, mid_range) assert(test(ShortString_Mid_CutToEnd_MidRange)); // short_str.replace_with_range(mid, end, long_range) assert(test(ShortString_Mid_CutToEnd_LongRange)); // Replace at the end. // short_str.replace_with_range(end, end, empty_range) assert(test(ShortString_End_EmptyCut_EmptyRange)); // short_str.replace_with_range(end, end, one_element_range) assert(test(ShortString_End_EmptyCut_OneElementRange)); // short_str.replace_with_range(end, end, mid_range) assert(test(ShortString_End_EmptyCut_MidRange)); // short_str.replace_with_range(end, end, long_range) assert(test(ShortString_End_EmptyCut_LongRange)); } { // Long string. // Replace at the beginning. // long_str.replace_with_range(begin, begin, empty_range) assert(test(LongString_Begin_EmptyCut_EmptyRange)); // long_str.replace_with_range(begin, begin, one_element_range) assert(test(LongString_Begin_EmptyCut_OneElementRange)); // long_str.replace_with_range(begin, begin, mid_range) assert(test(LongString_Begin_EmptyCut_MidRange)); // long_str.replace_with_range(begin, begin, long_range) assert(test(LongString_Begin_EmptyCut_LongRange)); // long_str.replace_with_range(begin, begin, longer_than_capacity_range) assert(test(LongString_Begin_EmptyCut_LongerThanCapacityRange)); // long_str.replace_with_range(begin, begin + 1, empty_range) assert(test(LongString_Begin_OneElementCut_EmptyRange)); // long_str.replace_with_range(begin, begin + 1, one_element_range) assert(test(LongString_Begin_OneElementCut_OneElementRange)); // long_str.replace_with_range(begin, begin + 1, mid_range) assert(test(LongString_Begin_OneElementCut_MidRange)); // long_str.replace_with_range(begin, begin + 1, long_range) assert(test(LongString_Begin_OneElementCut_LongRange)); // long_str.replace_with_range(begin, begin + 1, longer_than_capacity_range) assert(test(LongString_Begin_OneElementCut_LongerThanCapacityRange)); // long_str.replace_with_range(begin, begin + 3, empty_range) assert(test(LongString_Begin_MidSizedCut_EmptyRange)); // long_str.replace_with_range(begin, begin + 3, one_element_range) assert(test(LongString_Begin_MidSizedCut_OneElementRange)); // long_str.replace_with_range(begin, begin + 3, mid_range) assert(test(LongString_Begin_MidSizedCut_MidRange)); // long_str.replace_with_range(begin, begin + 3, long_range) assert(test(LongString_Begin_MidSizedCut_LongRange)); // long_str.replace_with_range(begin, begin + 3, longer_than_capacity_range) assert(test(LongString_Begin_MidSizedCut_LongerThanCapacityRange)); // long_str.replace_with_range(begin, end, empty_range) assert(test(LongString_Begin_CutToEnd_EmptyRange)); // long_str.replace_with_range(begin, end, one_element_range) assert(test(LongString_Begin_CutToEnd_OneElementRange)); // long_str.replace_with_range(begin, end, mid_range) assert(test(LongString_Begin_CutToEnd_MidRange)); // long_str.replace_with_range(begin, end, long_range) assert(test(LongString_Begin_CutToEnd_LongRange)); // long_str.replace_with_range(begin, end, longer_than_capacity_range) assert(test(LongString_Begin_CutToEnd_LongerThanCapacityRange)); // Replace in the middle. // long_str.replace_with_range(mid, mid, empty_range) assert(test(LongString_Mid_EmptyCut_EmptyRange)); // long_str.replace_with_range(mid, mid, one_element_range) assert(test(LongString_Mid_EmptyCut_OneElementRange)); // long_str.replace_with_range(mid, mid, mid_range) assert(test(LongString_Mid_EmptyCut_MidRange)); // long_str.replace_with_range(mid, mid, long_range) assert(test(LongString_Mid_EmptyCut_LongRange)); // long_str.replace_with_range(mid, mid, longer_than_capacity_range) assert(test(LongString_Mid_EmptyCut_LongerThanCapacityRange)); // long_str.replace_with_range(mid, mid + 1, empty_range) assert(test(LongString_Mid_OneElementCut_EmptyRange)); // long_str.replace_with_range(mid, mid + 1, one_element_range) assert(test(LongString_Mid_OneElementCut_OneElementRange)); // long_str.replace_with_range(mid, mid + 1, mid_range) assert(test(LongString_Mid_OneElementCut_MidRange)); // long_str.replace_with_range(mid, mid + 1, long_range) assert(test(LongString_Mid_OneElementCut_LongRange)); // long_str.replace_with_range(mid, mid + 1, longer_than_capacity_range) assert(test(LongString_Mid_OneElementCut_LongerThanCapacityRange)); // long_str.replace_with_range(mid, mid + 3, empty_range) assert(test(LongString_Mid_MidSizedCut_EmptyRange)); // long_str.replace_with_range(mid, mid + 3, one_element_range) assert(test(LongString_Mid_MidSizedCut_OneElementRange)); // long_str.replace_with_range(mid, mid + 3, mid_range) assert(test(LongString_Mid_MidSizedCut_MidRange)); // long_str.replace_with_range(mid, mid + 3, long_range) assert(test(LongString_Mid_MidSizedCut_LongRange)); // long_str.replace_with_range(mid, mid + 3, longer_than_capacity_range) assert(test(LongString_Mid_MidSizedCut_LongerThanCapacityRange)); // long_str.replace_with_range(mid, end, empty_range) assert(test(LongString_Mid_CutToEnd_EmptyRange)); // long_str.replace_with_range(mid, end, one_element_range) assert(test(LongString_Mid_CutToEnd_OneElementRange)); // long_str.replace_with_range(mid, end, mid_range) assert(test(LongString_Mid_CutToEnd_MidRange)); // long_str.replace_with_range(mid, end, long_range) assert(test(LongString_Mid_CutToEnd_LongRange)); // long_str.replace_with_range(mid, end, longer_than_capacity_range) assert(test(LongString_Mid_CutToEnd_LongerThanCapacityRange)); // Replace at the end. // long_str.replace_with_range(end, end, empty_range) assert(test(LongString_End_EmptyCut_EmptyRange)); // long_str.replace_with_range(end, end, one_element_range) assert(test(LongString_End_EmptyCut_OneElementRange)); // long_str.replace_with_range(end, end, mid_range) assert(test(LongString_End_EmptyCut_MidRange)); // long_str.replace_with_range(end, end, long_range) assert(test(LongString_End_EmptyCut_LongRange)); // long_str.replace_with_range(end, end, longer_than_capacity_range) assert(test(LongString_End_EmptyCut_LongerThanCapacityRange)); } } constexpr void test_string_replace_with_range_rvalue_range() { // Make sure that the input range can be passed by both an lvalue and an rvalue reference and regardless of constness. { // Lvalue. std::string in = "abc"; std::string c = "123"; c.replace_with_range(c.begin(), c.end(), in); } { // Const lvalue. const std::string in = "abc"; std::string c = "123"; c.replace_with_range(c.begin(), c.end(), in); } { // Rvalue. std::string in = "abc"; std::string c = "123"; c.replace_with_range(c.begin(), c.end(), std::move(in)); } { // Const rvalue. const std::string in = "abc"; std::string c = "123"; c.replace_with_range(c.begin(), c.end(), std::move(in)); } } constexpr bool test_constexpr() { for_all_iterators_and_allocators_constexpr([]() { test_string_replace_with_range(); }); test_string_replace_with_range_rvalue_range(); return true; } // Tested cases: // - different kinds of replacements (varying the size of the initial string, the cut point and the cut size, and the // size of the input range); // - an exception is thrown when allocating new elements. int main(int, char**) { static_assert(test_constraints_replace_with_range()); for_all_iterators_and_allocators([]() { test_string_replace_with_range(); }); test_string_replace_with_range_rvalue_range(); static_assert(test_constexpr()); // Note: `test_string_replace_with_range_exception_safety_throwing_copy` doesn't apply because copying chars cannot // throw. { #if !defined(TEST_HAS_NO_EXCEPTIONS) // Note: the input string must be long enough to prevent SSO, otherwise the allocator won't be used. std::string in(64, 'a'); try { ThrowingAllocator alloc; globalMemCounter.reset(); std::basic_string, ThrowingAllocator> c(alloc); c.replace_with_range(c.end(), c.end(), in); assert(false); // The function call above should throw. } catch (int) { assert(globalMemCounter.new_called == globalMemCounter.delete_called); } #endif } return 0; }