[libcxx] r347589 - Add basic_string::__resize_default_init (from P1072)
Eric Fiselier
eric at efcs.ca
Mon Nov 26 12:15:38 PST 2018
Author: ericwf
Date: Mon Nov 26 12:15:38 2018
New Revision: 347589
URL: http://llvm.org/viewvc/llvm-project?rev=347589&view=rev
Log:
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.
Added:
libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
Modified:
libcxx/trunk/include/string
libcxx/trunk/src/filesystem/filesystem_common.h
Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=347589&r1=347588&r2=347589&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Mon Nov 26 12:15:38 2018
@@ -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);
@@ -2428,6 +2434,23 @@ basic_string<_CharT, _Traits, _Allocator
}
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
__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
Modified: libcxx/trunk/src/filesystem/filesystem_common.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/filesystem/filesystem_common.h?rev=347589&r1=347588&r2=347589&view=diff
==============================================================================
--- libcxx/trunk/src/filesystem/filesystem_common.h (original)
+++ libcxx/trunk/src/filesystem/filesystem_common.h Mon Nov 26 12:15:38 2018
@@ -67,24 +67,31 @@ static string format_string_imp(const ch
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());
-
- // 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());
+ 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. 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(); }
Added: libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp?rev=347589&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp Mon Nov 26 12:15:38 2018
@@ -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();
+}
More information about the libcxx-commits
mailing list