Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:25

0001 // Copyright 2021 The Abseil Authors
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //     https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
0016 #define ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
0017 
0018 #include <cassert>
0019 #include <memory>
0020 #include <random>
0021 #include <string>
0022 #include <vector>
0023 
0024 #include "absl/base/config.h"
0025 #include "absl/base/internal/raw_logging.h"
0026 #include "absl/strings/internal/cord_internal.h"
0027 #include "absl/strings/internal/cord_rep_btree.h"
0028 #include "absl/strings/internal/cord_rep_flat.h"
0029 #include "absl/strings/string_view.h"
0030 
0031 namespace absl {
0032 ABSL_NAMESPACE_BEGIN
0033 namespace cordrep_testing {
0034 
0035 inline cord_internal::CordRepSubstring* MakeSubstring(
0036     size_t start, size_t len, cord_internal::CordRep* rep) {
0037   auto* sub = new cord_internal::CordRepSubstring;
0038   sub->tag = cord_internal::SUBSTRING;
0039   sub->start = start;
0040   sub->length = len <= 0 ? rep->length - start + len : len;
0041   sub->child = rep;
0042   return sub;
0043 }
0044 
0045 inline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) {
0046   assert(value.length() <= cord_internal::kMaxFlatLength);
0047   auto* flat = cord_internal::CordRepFlat::New(value.length());
0048   flat->length = value.length();
0049   memcpy(flat->Data(), value.data(), value.length());
0050   return flat;
0051 }
0052 
0053 // Creates an external node for testing
0054 inline cord_internal::CordRepExternal* MakeExternal(absl::string_view s) {
0055   struct Rep : public cord_internal::CordRepExternal {
0056     std::string s;
0057     explicit Rep(absl::string_view sv) : s(sv) {
0058       this->tag = cord_internal::EXTERNAL;
0059       this->base = s.data();
0060       this->length = s.length();
0061       this->releaser_invoker = [](cord_internal::CordRepExternal* self) {
0062         delete static_cast<Rep*>(self);
0063       };
0064     }
0065   };
0066   return new Rep(s);
0067 }
0068 
0069 inline std::string CreateRandomString(size_t n) {
0070   absl::string_view data =
0071       "abcdefghijklmnopqrstuvwxyz"
0072       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
0073       "0123456789~!@#$%^&*()_+=-<>?:\"{}[]|";
0074   std::minstd_rand rnd;
0075   std::uniform_int_distribution<size_t> dist(0, data.size() - 1);
0076   std::string s(n, ' ');
0077   for (size_t i = 0; i < n; ++i) {
0078     s[i] = data[dist(rnd)];
0079   }
0080   return s;
0081 }
0082 
0083 // Creates an array of flats from the provided string, chopping
0084 // the provided string up into flats of size `chunk_size` characters
0085 // resulting in roughly `data.size() / chunk_size` total flats.
0086 inline std::vector<cord_internal::CordRep*> CreateFlatsFromString(
0087     absl::string_view data, size_t chunk_size) {
0088   assert(chunk_size > 0);
0089   std::vector<cord_internal::CordRep*> flats;
0090   for (absl::string_view s = data; !s.empty(); s.remove_prefix(chunk_size)) {
0091     flats.push_back(MakeFlat(s.substr(0, chunk_size)));
0092   }
0093   return flats;
0094 }
0095 
0096 inline cord_internal::CordRepBtree* CordRepBtreeFromFlats(
0097     absl::Span<cord_internal::CordRep* const> flats) {
0098   assert(!flats.empty());
0099   auto* node = cord_internal::CordRepBtree::Create(flats[0]);
0100   for (size_t i = 1; i < flats.size(); ++i) {
0101     node = cord_internal::CordRepBtree::Append(node, flats[i]);
0102   }
0103   return node;
0104 }
0105 
0106 template <typename Fn>
0107 inline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) {
0108   fn(rep);
0109   while (rep->tag == cord_internal::SUBSTRING) {
0110     rep = rep->substring()->child;
0111     fn(rep);
0112   }
0113   if (rep->tag == cord_internal::BTREE) {
0114     for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
0115       CordVisitReps(edge, fn);
0116     }
0117   }
0118 }
0119 
0120 template <typename Predicate>
0121 inline std::vector<cord_internal::CordRep*> CordCollectRepsIf(
0122     Predicate&& predicate, cord_internal::CordRep* rep) {
0123   std::vector<cord_internal::CordRep*> reps;
0124   CordVisitReps(rep, [&reps, &predicate](cord_internal::CordRep* rep) {
0125     if (predicate(rep)) reps.push_back(rep);
0126   });
0127   return reps;
0128 }
0129 
0130 inline std::vector<cord_internal::CordRep*> CordCollectReps(
0131     cord_internal::CordRep* rep) {
0132   std::vector<cord_internal::CordRep*> reps;
0133   auto fn = [&reps](cord_internal::CordRep* rep) { reps.push_back(rep); };
0134   CordVisitReps(rep, fn);
0135   return reps;
0136 }
0137 
0138 inline void CordToString(cord_internal::CordRep* rep, std::string& s) {
0139   size_t offset = 0;
0140   size_t length = rep->length;
0141   while (rep->tag == cord_internal::SUBSTRING) {
0142     offset += rep->substring()->start;
0143     rep = rep->substring()->child;
0144   }
0145   if (rep->tag == cord_internal::BTREE) {
0146     for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
0147       CordToString(edge, s);
0148     }
0149   } else if (rep->tag >= cord_internal::FLAT) {
0150     s.append(rep->flat()->Data() + offset, length);
0151   } else if (rep->tag == cord_internal::EXTERNAL) {
0152     s.append(rep->external()->base + offset, length);
0153   } else {
0154     ABSL_RAW_LOG(FATAL, "Unsupported tag %d", rep->tag);
0155   }
0156 }
0157 
0158 inline std::string CordToString(cord_internal::CordRep* rep) {
0159   std::string s;
0160   s.reserve(rep->length);
0161   CordToString(rep, s);
0162   return s;
0163 }
0164 
0165 // RAII Helper class to automatically unref reps on destruction.
0166 class AutoUnref {
0167  public:
0168   ~AutoUnref() {
0169     for (CordRep* rep : unrefs_) CordRep::Unref(rep);
0170   }
0171 
0172   // Adds `rep` to the list of reps to be unreffed at destruction.
0173   template <typename CordRepType>
0174   CordRepType* Add(CordRepType* rep) {
0175     unrefs_.push_back(rep);
0176     return rep;
0177   }
0178 
0179   // Increments the reference count of `rep` by one, and adds it to
0180   // the list of reps to be unreffed at destruction.
0181   template <typename CordRepType>
0182   CordRepType* Ref(CordRepType* rep) {
0183     unrefs_.push_back(CordRep::Ref(rep));
0184     return rep;
0185   }
0186 
0187   // Increments the reference count of `rep` by one if `condition` is true,
0188   // and adds it to the list of reps to be unreffed at destruction.
0189   template <typename CordRepType>
0190   CordRepType* RefIf(bool condition, CordRepType* rep) {
0191     if (condition) unrefs_.push_back(CordRep::Ref(rep));
0192     return rep;
0193   }
0194 
0195  private:
0196   using CordRep = absl::cord_internal::CordRep;
0197 
0198   std::vector<CordRep*> unrefs_;
0199 };
0200 
0201 }  // namespace cordrep_testing
0202 ABSL_NAMESPACE_END
0203 }  // namespace absl
0204 
0205 #endif  // ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_