forked from OSchip/llvm-project
Add basic_string::__resize_default_init (from P1072)
This patch adds an implementation of __resize_default_init as described in P1072R2. Additionally, it uses it in filesystem to demonstrate its intended utility. Once P1072 lands, or if it changes it's interface, I will adjust the internal libc++ implementation to match. llvm-svn: 347589
This commit is contained in:
parent
e8e8c5cf4d
commit
01a87ef88b
|
@ -956,6 +956,8 @@ public:
|
||||||
void resize(size_type __n, value_type __c);
|
void resize(size_type __n, value_type __c);
|
||||||
_LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());}
|
_LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY void __resize_default_init(size_type __n);
|
||||||
|
|
||||||
void reserve(size_type __res_arg = 0);
|
void reserve(size_type __res_arg = 0);
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
void shrink_to_fit() _NOEXCEPT {reserve();}
|
void shrink_to_fit() _NOEXCEPT {reserve();}
|
||||||
|
@ -1010,6 +1012,10 @@ public:
|
||||||
basic_string& append(const value_type* __s, size_type __n);
|
basic_string& append(const value_type* __s, size_type __n);
|
||||||
basic_string& append(const value_type* __s);
|
basic_string& append(const value_type* __s);
|
||||||
basic_string& append(size_type __n, value_type __c);
|
basic_string& append(size_type __n, value_type __c);
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
void __append_default_init(size_type __n);
|
||||||
|
|
||||||
template <class _ForwardIterator>
|
template <class _ForwardIterator>
|
||||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||||
basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator);
|
basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator);
|
||||||
|
@ -2427,6 +2433,23 @@ basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
|
inline void
|
||||||
|
basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n)
|
||||||
|
{
|
||||||
|
if (__n)
|
||||||
|
{
|
||||||
|
size_type __cap = capacity();
|
||||||
|
size_type __sz = size();
|
||||||
|
if (__cap - __sz < __n)
|
||||||
|
__grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||||
|
pointer __p = __get_pointer();
|
||||||
|
__sz += __n;
|
||||||
|
__set_size(__sz);
|
||||||
|
traits_type::assign(__p[__sz], value_type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class _CharT, class _Traits, class _Allocator>
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
void
|
void
|
||||||
basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
|
basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
|
||||||
|
@ -3082,6 +3105,17 @@ basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c)
|
||||||
__erase_to_end(__n);
|
__erase_to_end(__n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
|
inline void
|
||||||
|
basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n)
|
||||||
|
{
|
||||||
|
size_type __sz = size();
|
||||||
|
if (__n > __sz) {
|
||||||
|
__append_default_init(__n - __sz);
|
||||||
|
} else
|
||||||
|
__erase_to_end(__n);
|
||||||
|
}
|
||||||
|
|
||||||
template <class _CharT, class _Traits, class _Allocator>
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type
|
typename basic_string<_CharT, _Traits, _Allocator>::size_type
|
||||||
|
|
|
@ -67,24 +67,31 @@ static string format_string_imp(const char* msg, ...) {
|
||||||
va_copy(args_cp, args);
|
va_copy(args_cp, args);
|
||||||
GuardVAList args_copy_guard(args_cp);
|
GuardVAList args_copy_guard(args_cp);
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
|
||||||
array<char, 256> local_buff;
|
array<char, 256> local_buff;
|
||||||
size_t size = local_buff.size();
|
size_t size_with_null = local_buff.size();
|
||||||
auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp);
|
auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
|
||||||
|
|
||||||
args_copy_guard.clear();
|
args_copy_guard.clear();
|
||||||
|
|
||||||
// handle empty expansion
|
// handle empty expansion
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return string{};
|
return result;
|
||||||
if (static_cast<size_t>(ret) < size)
|
if (static_cast<size_t>(ret) < size_with_null) {
|
||||||
return string(local_buff.data());
|
result.assign(local_buff.data(), static_cast<size_t>(ret));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// we did not provide a long enough buffer on our first attempt.
|
// we did not provide a long enough buffer on our first attempt. The
|
||||||
// add 1 to size to account for null-byte in size cast to prevent overflow
|
// return value is the number of bytes (excluding the null byte) that are
|
||||||
size = static_cast<size_t>(ret) + 1;
|
// needed for formatting.
|
||||||
auto buff_ptr = unique_ptr<char[]>(new char[size]);
|
size_with_null = static_cast<size_t>(ret) + 1;
|
||||||
ret = ::vsnprintf(buff_ptr.get(), size, msg, args);
|
result.__resize_default_init(size_with_null - 1);
|
||||||
return string(buff_ptr.get());
|
ret = ::vsnprintf(&result[0], size_with_null, msg, args);
|
||||||
|
_LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* unwrap(string const& s) { return s.c_str(); }
|
const char* unwrap(string const& s) { return s.c_str(); }
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <string>
|
||||||
|
|
||||||
|
// __resize_default_init(size_type)
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
void write_c_str(char *buf, int size) {
|
||||||
|
for (int i=0; i < size; ++i) {
|
||||||
|
buf[i] = 'a';
|
||||||
|
}
|
||||||
|
buf[size] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_buffer_usage()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
unsigned buff_size = 125;
|
||||||
|
unsigned used_size = buff_size - 16;
|
||||||
|
std::string s;
|
||||||
|
s.__resize_default_init(buff_size);
|
||||||
|
write_c_str(&s[0], used_size);
|
||||||
|
assert(s.size() == buff_size);
|
||||||
|
assert(strlen(s.data()) == used_size);
|
||||||
|
s.__resize_default_init(used_size);
|
||||||
|
assert(s.size() == used_size);
|
||||||
|
assert(s.data()[used_size] == '\0');
|
||||||
|
for (unsigned i=0; i < used_size; ++i) {
|
||||||
|
assert(s[i] == 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_basic() {
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s.__resize_default_init(3);
|
||||||
|
assert(s.size() == 3);
|
||||||
|
assert(s.data()[3] == '\0');
|
||||||
|
for (int i=0; i < 3; ++i)
|
||||||
|
s[i] = 'a' + i;
|
||||||
|
s.__resize_default_init(1);
|
||||||
|
assert(s[0] == 'a');
|
||||||
|
assert(s.data()[1] == '\0');
|
||||||
|
assert(s.size() == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_basic();
|
||||||
|
test_buffer_usage();
|
||||||
|
}
|
Loading…
Reference in New Issue