File indexing completed on 2025-01-18 09:27:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
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
0084
0085
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
0166 class AutoUnref {
0167 public:
0168 ~AutoUnref() {
0169 for (CordRep* rep : unrefs_) CordRep::Unref(rep);
0170 }
0171
0172
0173 template <typename CordRepType>
0174 CordRepType* Add(CordRepType* rep) {
0175 unrefs_.push_back(rep);
0176 return rep;
0177 }
0178
0179
0180
0181 template <typename CordRepType>
0182 CordRepType* Ref(CordRepType* rep) {
0183 unrefs_.push_back(CordRep::Ref(rep));
0184 return rep;
0185 }
0186
0187
0188
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 }
0202 ABSL_NAMESPACE_END
0203 }
0204
0205 #endif