tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

resize_uninitialized.h (4426B)


      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  static void Resize(string_type* s, size_t new_size) {
     48    s->__resize_default_init(new_size);
     49  }
     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 inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
     68  ResizeUninitializedTraits<string_type>::Resize(s, new_size);
     69 }
     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  static void Append(string_type* s, size_t n) {
     97    s->__append_default_init(n);
     98  }
     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_