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);
|
||||
_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);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
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);
|
||||
basic_string& append(size_type __n, value_type __c);
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __append_default_init(size_type __n);
|
||||
|
||||
template <class _ForwardIterator>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
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);
|
||||
GuardVAList args_copy_guard(args_cp);
|
||||
|
||||
std::string result;
|
||||
|
||||
array<char, 256> local_buff;
|
||||
size_t size = local_buff.size();
|
||||
auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp);
|
||||
size_t size_with_null = local_buff.size();
|
||||
auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
|
||||
|
||||
args_copy_guard.clear();
|
||||
|
||||
// handle empty expansion
|
||||
if (ret == 0)
|
||||
return string{};
|
||||
if (static_cast<size_t>(ret) < size)
|
||||
return string(local_buff.data());
|
||||
return result;
|
||||
if (static_cast<size_t>(ret) < size_with_null) {
|
||||
result.assign(local_buff.data(), static_cast<size_t>(ret));
|
||||
return result;
|
||||
}
|
||||
|
||||
// we did not provide a long enough buffer on our first attempt.
|
||||
// add 1 to size to account for null-byte in size cast to prevent overflow
|
||||
size = static_cast<size_t>(ret) + 1;
|
||||
auto buff_ptr = unique_ptr<char[]>(new char[size]);
|
||||
ret = ::vsnprintf(buff_ptr.get(), size, msg, args);
|
||||
return string(buff_ptr.get());
|
||||
// we did not provide a long enough buffer on our first attempt. The
|
||||
// return value is the number of bytes (excluding the null byte) that are
|
||||
// needed for formatting.
|
||||
size_with_null = static_cast<size_t>(ret) + 1;
|
||||
result.__resize_default_init(size_with_null - 1);
|
||||
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(); }
|
||||
|
|
|
@ -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