Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement P1072R10 basic_string::resize_and_overwrite #2258

Merged
merged 4 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -3952,16 +3952,35 @@ public:
);
}

_CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Elem _Ch = _Elem()) {
_CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _New_size, const _Elem _Ch = _Elem()) {
// determine new length, padding with _Ch elements as needed
const size_type _Old_size = size();
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
if (_Newsize <= _Old_size) {
_Eos(_Newsize);
if (_New_size <= _Old_size) {
_Eos(_New_size);
} else {
append(_Newsize - _Old_size, _Ch);
append(_New_size - _Old_size, _Ch);
}
}

#if _HAS_CXX23
template <class _Operation>
constexpr void resize_and_overwrite(_CRT_GUARDOVERFLOW const size_type _New_size, _Operation _Op) {
if (_Mypair._Myval2._Myres < _New_size) {
_Reallocate_grow_by(_New_size - _Mypair._Myval2._Mysize,
[](_Elem* const _New_ptr, const _Elem* const _Old_ptr, const size_type _Old_size) {
_Traits::copy(_New_ptr, _Old_ptr, _Old_size + 1);
});
}

AdamBucior marked this conversation as resolved.
Show resolved Hide resolved
const auto _Result_size = _STD move(_Op)(_Mypair._Myval2._Myptr(), _New_size);
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Result_size >= 0, "the returned size can't be smaller than 0");
_STL_VERIFY(_Result_size <= _New_size, "the returned size can't be greater than the passed size");
#endif // _CONTAINER_DEBUG_LEVEL > 0
_Eos(_Result_size);
}
#endif // _HAS_CXX23

_NODISCARD _CONSTEXPR20 size_type capacity() const noexcept {
return _Mypair._Myval2._Myres;
}
Expand Down Expand Up @@ -4595,8 +4614,8 @@ private:
_Mypair._Myval2._Myres = _BUF_SIZE - 1;
}

_CONSTEXPR20 void _Eos(const size_type _Newsize) { // set new length and null terminator
_Traits::assign(_Mypair._Myval2._Myptr()[_Mypair._Myval2._Mysize = _Newsize], _Elem());
_CONSTEXPR20 void _Eos(const size_type _New_size) { // set new length and null terminator
_Traits::assign(_Mypair._Myval2._Myptr()[_Mypair._Myval2._Mysize = _New_size], _Elem());
}

_CONSTEXPR20 void _Tidy_init() noexcept { // initialize basic_string data members
Expand Down
10 changes: 6 additions & 4 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@
// P0448R4 <spanstream>
// P0943R6 Supporting C Atomics In C++
// P1048R1 is_scoped_enum
// P1072R10 basic_string::resize_and_overwrite
// P1132R7 out_ptr(), inout_ptr()
// P1147R1 Printing volatile Pointers
// P1272R4 byteswap()
Expand Down Expand Up @@ -1376,10 +1377,11 @@
#define __cpp_lib_ranges_starts_ends_with 202106L
#endif // __cpp_lib_concepts

#define __cpp_lib_spanstream 202106L
#define __cpp_lib_stdatomic_h 202011L
#define __cpp_lib_string_contains 202011L
#define __cpp_lib_to_underlying 202102L
#define __cpp_lib_spanstream 202106L
#define __cpp_lib_stdatomic_h 202011L
#define __cpp_lib_string_contains 202011L
#define __cpp_lib_string_resize_and_overwrite 202110L
#define __cpp_lib_to_underlying 202102L
#endif // _HAS_CXX23

#define __cpp_lib_experimental_erase_if 201411L
Expand Down
102 changes: 102 additions & 0 deletions tests/std/tests/P0980R1_constexpr_strings/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,108 @@ constexpr bool test_interface() {
assert(equalRanges(resized, "Helaaa"sv));
}

#if _HAS_CXX23
AdamBucior marked this conversation as resolved.
Show resolved Hide resolved
{ // resize_and_overwrite
AdamBucior marked this conversation as resolved.
Show resolved Hide resolved
constexpr basic_string_view hello_fluffy_kittens = get_view_input<CharType>();
constexpr basic_string_view hello = hello_fluffy_kittens.substr(0, 5);
constexpr basic_string_view dog = get_dog<CharType>();
constexpr basic_string_view kitten = get_cat<CharType>();

str s;
AdamBucior marked this conversation as resolved.
Show resolved Hide resolved
s.resize_and_overwrite(5, [=](CharType* p, size_t n) {
assert(n == 5);
hello.copy(p, 5);
return 5u;
});

assert(s == hello);
assert(s.size() == 5);
assert(s.capacity() >= 5);
assert(s[5] == 0);

s.resize_and_overwrite(8, [=](CharType* p, size_t n) {
assert(n == 8);
assert(equal(hello.begin(), hello.end(), p, p + 5));
dog.copy(p, 3);
return 3u;
});

assert(s == dog);
assert(s.size() == 3);
assert(s.capacity() >= 3);
assert(s[3] == 0);

s.resize_and_overwrite(6, [=](CharType* p, size_t n) {
assert(n == 6);
assert(equal(dog.begin(), dog.end(), p, p + 3));
kitten.copy(p, 6);
return 6u;
});

assert(s == kitten);
assert(s.size() == 6);
assert(s.capacity() >= 6);
assert(s[6] == 0);

s.resize_and_overwrite(0, [=](CharType*, size_t n) {
assert(n == 0);
return 0u;
});

assert(s.size() == 0);
assert(s[0] == 0);

s = dog;

s.resize_and_overwrite(6, [=](CharType* p, size_t n) {
assert(n == 6);
assert(equal(dog.begin(), dog.end(), p, p + 3));
return 0u;
});

assert(s.size() == 0);
assert(s[0] == 0);

s = kitten;

s.resize_and_overwrite(3, [=](CharType* p, size_t n) {
assert(n == 3);
assert(equal(kitten.begin(), kitten.begin() + 3, p, p + 3));
dog.copy(p, 3);
return 3u;
});

assert(s == dog);
assert(s.size() == 3);
assert(s.capacity() >= 3);
assert(s[3] == 0);

s.resize_and_overwrite(20, [=](CharType* p, size_t n) {
assert(n == 20);
assert(equal(dog.begin(), dog.end(), p, p + 3));
hello_fluffy_kittens.copy(p, 20);
return 20u;
});

assert(s == hello_fluffy_kittens);
assert(s.size() == 20);
assert(s.capacity() >= 20);
assert(s[20] == 0);

s.resize_and_overwrite(3, [=](CharType* p, size_t n) {
assert(n == 3);
assert(equal(hello_fluffy_kittens.begin(), hello_fluffy_kittens.begin() + 3, p, p + 3));
dog.copy(p, 3);
return 3u;
});

assert(s == dog);
assert(s.size() == 3);
assert(s.capacity() >= 3);
assert(s[3] == 0);
}
#endif // _HAS_CXX23

{ // swap
constexpr basic_string_view<CharType> expected_first = get_dog<CharType>();
constexpr basic_string_view<CharType> expected_second = get_cat<CharType>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,20 @@ STATIC_ASSERT(__cpp_lib_string_contains == 202011L);
#endif
#endif

#if _HAS_CXX23
#ifndef __cpp_lib_string_resize_and_overwrite
#error __cpp_lib_string_resize_and_overwrite is not defined
#elif __cpp_lib_string_resize_and_overwrite != 202110L
AdamBucior marked this conversation as resolved.
Show resolved Hide resolved
#error __cpp_lib_string_resize_and_overwrite is not 202110L
#else
STATIC_ASSERT(__cpp_lib_string_resize_and_overwrite == 202110L);
#endif
#else
#ifdef __cpp_lib_string_resize_and_overwrite
#error __cpp_lib_string_resize_and_overwrite is defined
#endif
#endif

#ifndef __cpp_lib_string_udls
#error __cpp_lib_string_udls is not defined
#elif __cpp_lib_string_udls != 201304L
Expand Down