/proc/self/cwd/external/com_google_absl/absl/strings/internal/resize_uninitialized.h
Line | Count | Source |
1 | | // |
2 | | // Copyright 2017 The Abseil Authors. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | // |
16 | | |
17 | | #ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ |
18 | | #define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ |
19 | | |
20 | | #include <algorithm> |
21 | | #include <string> |
22 | | #include <type_traits> |
23 | | #include <utility> |
24 | | |
25 | | #include "absl/base/port.h" |
26 | | #include "absl/meta/type_traits.h" // for void_t |
27 | | |
28 | | namespace absl { |
29 | | ABSL_NAMESPACE_BEGIN |
30 | | namespace strings_internal { |
31 | | |
32 | | // In this type trait, we look for a __resize_default_init member function, and |
33 | | // we use it if available, otherwise, we use resize. We provide HasMember to |
34 | | // indicate whether __resize_default_init is present. |
35 | | template <typename string_type, typename = void> |
36 | | struct ResizeUninitializedTraits { |
37 | | using HasMember = std::false_type; |
38 | | static void Resize(string_type* s, size_t new_size) { s->resize(new_size); } |
39 | | }; |
40 | | |
41 | | // __resize_default_init is provided by libc++ >= 8.0 |
42 | | template <typename string_type> |
43 | | struct ResizeUninitializedTraits< |
44 | | string_type, absl::void_t<decltype(std::declval<string_type&>() |
45 | | .__resize_default_init(237))> > { |
46 | | using HasMember = std::true_type; |
47 | 2.48k | static void Resize(string_type* s, size_t new_size) { |
48 | 2.48k | s->__resize_default_init(new_size); |
49 | 2.48k | } |
50 | | }; |
51 | | |
52 | | // Returns true if the std::string implementation supports a resize where |
53 | | // the new characters added to the std::string are left untouched. |
54 | | // |
55 | | // (A better name might be "STLStringSupportsUninitializedResize", alluding to |
56 | | // the previous function.) |
57 | | template <typename string_type> |
58 | | inline constexpr bool STLStringSupportsNontrashingResize(string_type*) { |
59 | | return ResizeUninitializedTraits<string_type>::HasMember::value; |
60 | | } |
61 | | |
62 | | // Like str->resize(new_size), except any new characters added to "*str" as a |
63 | | // result of resizing may be left uninitialized, rather than being filled with |
64 | | // '0' bytes. Typically used when code is then going to overwrite the backing |
65 | | // store of the std::string with known data. |
66 | | template <typename string_type, typename = void> |
67 | 2.48k | inline void STLStringResizeUninitialized(string_type* s, size_t new_size) { |
68 | 2.48k | ResizeUninitializedTraits<string_type>::Resize(s, new_size); |
69 | 2.48k | } |
70 | | |
71 | | // Used to ensure exponential growth so that the amortized complexity of |
72 | | // increasing the string size by a small amount is O(1), in contrast to |
73 | | // O(str->size()) in the case of precise growth. |
74 | | template <typename string_type> |
75 | | void STLStringReserveAmortized(string_type* s, size_t new_size) { |
76 | | const size_t cap = s->capacity(); |
77 | | if (new_size > cap) { |
78 | | // Make sure to always grow by at least a factor of 2x. |
79 | | s->reserve((std::max)(new_size, 2 * cap)); |
80 | | } |
81 | | } |
82 | | |
83 | | // In this type trait, we look for an __append_default_init member function, and |
84 | | // we use it if available, otherwise, we use append. |
85 | | template <typename string_type, typename = void> |
86 | | struct AppendUninitializedTraits { |
87 | | static void Append(string_type* s, size_t n) { |
88 | | s->append(n, typename string_type::value_type()); |
89 | | } |
90 | | }; |
91 | | |
92 | | template <typename string_type> |
93 | | struct AppendUninitializedTraits< |
94 | | string_type, absl::void_t<decltype(std::declval<string_type&>() |
95 | | .__append_default_init(237))> > { |
96 | 1.24k | static void Append(string_type* s, size_t n) { |
97 | 1.24k | s->__append_default_init(n); |
98 | 1.24k | } |
99 | | }; |
100 | | |
101 | | // Like STLStringResizeUninitialized(str, new_size), except guaranteed to use |
102 | | // exponential growth so that the amortized complexity of increasing the string |
103 | | // size by a small amount is O(1), in contrast to O(str->size()) in the case of |
104 | | // precise growth. |
105 | | template <typename string_type> |
106 | | void STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) { |
107 | | const size_t size = s->size(); |
108 | | if (new_size > size) { |
109 | | AppendUninitializedTraits<string_type>::Append(s, new_size - size); |
110 | | } else { |
111 | | s->erase(new_size); |
112 | | } |
113 | | } |
114 | | |
115 | | } // namespace strings_internal |
116 | | ABSL_NAMESPACE_END |
117 | | } // namespace absl |
118 | | |
119 | | #endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ |