tor-browser

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

str_replace.cc (3033B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "absl/strings/str_replace.h"
     16 
     17 #include <cstddef>
     18 #include <initializer_list>
     19 #include <string>
     20 #include <utility>
     21 #include <vector>
     22 
     23 #include "absl/base/config.h"
     24 #include "absl/base/nullability.h"
     25 #include "absl/strings/str_cat.h"
     26 #include "absl/strings/string_view.h"
     27 
     28 namespace absl {
     29 ABSL_NAMESPACE_BEGIN
     30 namespace strings_internal {
     31 
     32 using FixedMapping =
     33    std::initializer_list<std::pair<absl::string_view, absl::string_view>>;
     34 
     35 // Applies the ViableSubstitutions in subs_ptr to the absl::string_view s, and
     36 // stores the result in *result_ptr. Returns the number of substitutions that
     37 // occurred.
     38 int ApplySubstitutions(
     39    absl::string_view s,
     40    absl::Nonnull<std::vector<strings_internal::ViableSubstitution>*> subs_ptr,
     41    absl::Nonnull<std::string*> result_ptr) {
     42  auto& subs = *subs_ptr;
     43  int substitutions = 0;
     44  size_t pos = 0;
     45  while (!subs.empty()) {
     46    auto& sub = subs.back();
     47    if (sub.offset >= pos) {
     48      if (pos <= s.size()) {
     49        StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement);
     50      }
     51      pos = sub.offset + sub.old.size();
     52      substitutions += 1;
     53    }
     54    sub.offset = s.find(sub.old, pos);
     55    if (sub.offset == s.npos) {
     56      subs.pop_back();
     57    } else {
     58      // Insertion sort to ensure the last ViableSubstitution continues to be
     59      // before all the others.
     60      size_t index = subs.size();
     61      while (--index && subs[index - 1].OccursBefore(subs[index])) {
     62        std::swap(subs[index], subs[index - 1]);
     63      }
     64    }
     65  }
     66  result_ptr->append(s.data() + pos, s.size() - pos);
     67  return substitutions;
     68 }
     69 
     70 }  // namespace strings_internal
     71 
     72 // We can implement this in terms of the generic StrReplaceAll, but
     73 // we must specify the template overload because C++ cannot deduce the type
     74 // of an initializer_list parameter to a function, and also if we don't specify
     75 // the type, we just call ourselves.
     76 //
     77 // Note that we implement them here, rather than in the header, so that they
     78 // aren't inlined.
     79 
     80 std::string StrReplaceAll(absl::string_view s,
     81                          strings_internal::FixedMapping replacements) {
     82  return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
     83 }
     84 
     85 int StrReplaceAll(strings_internal::FixedMapping replacements,
     86                  absl::Nonnull<std::string*> target) {
     87  return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
     88 }
     89 
     90 ABSL_NAMESPACE_END
     91 }  // namespace absl