Skip to content

Commit

Permalink
Implement P1072R10 basic_string::resize_and_overwrite (#2258)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamBucior authored Nov 13, 2021
1 parent 254fca2 commit 2de0fa5
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 10 deletions.
31 changes: 25 additions & 6 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -3946,16 +3946,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();
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);
});
}

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 @@ -4589,8 +4608,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
{ // resize_and_overwrite
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;
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
#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

0 comments on commit 2de0fa5

Please sign in to comment.