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_BTREE_NAVIGATOR_H_
0016 #define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
0017
0018 #include <cassert>
0019 #include <iostream>
0020
0021 #include "absl/strings/internal/cord_internal.h"
0022 #include "absl/strings/internal/cord_rep_btree.h"
0023
0024 namespace absl {
0025 ABSL_NAMESPACE_BEGIN
0026 namespace cord_internal {
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 class CordRepBtreeNavigator {
0047 public:
0048
0049
0050
0051 struct Position {
0052 CordRep* edge;
0053 size_t offset;
0054 };
0055
0056
0057
0058
0059
0060
0061 struct ReadResult {
0062 CordRep* tree;
0063 size_t n;
0064 };
0065
0066
0067 explicit operator bool() const;
0068
0069
0070 CordRepBtree* btree() const;
0071
0072
0073
0074 CordRep* Current() const;
0075
0076
0077 CordRep* InitFirst(CordRepBtree* tree);
0078
0079
0080 CordRep* InitLast(CordRepBtree* tree);
0081
0082
0083
0084
0085
0086
0087 Position InitOffset(CordRepBtree* tree, size_t offset);
0088
0089
0090
0091
0092 CordRep* Next();
0093
0094
0095
0096
0097 CordRep* Previous();
0098
0099
0100
0101
0102
0103 Position Seek(size_t offset);
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 ReadResult Read(size_t edge_offset, size_t n);
0114
0115
0116
0117
0118
0119 Position Skip(size_t n);
0120
0121
0122 void Reset();
0123
0124 private:
0125
0126
0127
0128 CordRep* NextUp();
0129
0130
0131
0132
0133
0134 CordRep* PreviousUp();
0135
0136
0137 template <CordRepBtree::EdgeType edge_type>
0138 CordRep* Init(CordRepBtree* tree);
0139
0140
0141 int height_ = -1;
0142
0143
0144
0145
0146 uint8_t index_[CordRepBtree::kMaxDepth];
0147 CordRepBtree* node_[CordRepBtree::kMaxDepth];
0148 };
0149
0150
0151 inline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }
0152
0153 inline CordRepBtree* CordRepBtreeNavigator::btree() const {
0154 return height_ >= 0 ? node_[height_] : nullptr;
0155 }
0156
0157 inline CordRep* CordRepBtreeNavigator::Current() const {
0158 assert(height_ >= 0);
0159 return node_[0]->Edge(index_[0]);
0160 }
0161
0162 inline void CordRepBtreeNavigator::Reset() { height_ = -1; }
0163
0164 inline CordRep* CordRepBtreeNavigator::InitFirst(CordRepBtree* tree) {
0165 return Init<CordRepBtree::kFront>(tree);
0166 }
0167
0168 inline CordRep* CordRepBtreeNavigator::InitLast(CordRepBtree* tree) {
0169 return Init<CordRepBtree::kBack>(tree);
0170 }
0171
0172 template <CordRepBtree::EdgeType edge_type>
0173 inline CordRep* CordRepBtreeNavigator::Init(CordRepBtree* tree) {
0174 assert(tree != nullptr);
0175 assert(tree->size() > 0);
0176 assert(tree->height() <= CordRepBtree::kMaxHeight);
0177 int height = height_ = tree->height();
0178 size_t index = tree->index(edge_type);
0179 node_[height] = tree;
0180 index_[height] = static_cast<uint8_t>(index);
0181 while (--height >= 0) {
0182 tree = tree->Edge(index)->btree();
0183 node_[height] = tree;
0184 index = tree->index(edge_type);
0185 index_[height] = static_cast<uint8_t>(index);
0186 }
0187 return node_[0]->Edge(index);
0188 }
0189
0190 inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::Seek(
0191 size_t offset) {
0192 assert(btree() != nullptr);
0193 int height = height_;
0194 CordRepBtree* edge = node_[height];
0195 if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};
0196 CordRepBtree::Position index = edge->IndexOf(offset);
0197 index_[height] = static_cast<uint8_t>(index.index);
0198 while (--height >= 0) {
0199 edge = edge->Edge(index.index)->btree();
0200 node_[height] = edge;
0201 index = edge->IndexOf(index.n);
0202 index_[height] = static_cast<uint8_t>(index.index);
0203 }
0204 return {edge->Edge(index.index), index.n};
0205 }
0206
0207 inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::InitOffset(
0208 CordRepBtree* tree, size_t offset) {
0209 assert(tree != nullptr);
0210 assert(tree->height() <= CordRepBtree::kMaxHeight);
0211 if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};
0212 height_ = tree->height();
0213 node_[height_] = tree;
0214 return Seek(offset);
0215 }
0216
0217 inline CordRep* CordRepBtreeNavigator::Next() {
0218 CordRepBtree* edge = node_[0];
0219 return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);
0220 }
0221
0222 inline CordRep* CordRepBtreeNavigator::Previous() {
0223 CordRepBtree* edge = node_[0];
0224 return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);
0225 }
0226
0227 inline CordRep* CordRepBtreeNavigator::NextUp() {
0228 assert(index_[0] == node_[0]->back());
0229 CordRepBtree* edge;
0230 size_t index;
0231 int height = 0;
0232 do {
0233 if (++height > height_) return nullptr;
0234 edge = node_[height];
0235 index = index_[height] + 1;
0236 } while (index == edge->end());
0237 index_[height] = static_cast<uint8_t>(index);
0238 do {
0239 node_[--height] = edge = edge->Edge(index)->btree();
0240 index_[height] = static_cast<uint8_t>(index = edge->begin());
0241 } while (height > 0);
0242 return edge->Edge(index);
0243 }
0244
0245 inline CordRep* CordRepBtreeNavigator::PreviousUp() {
0246 assert(index_[0] == node_[0]->begin());
0247 CordRepBtree* edge;
0248 size_t index;
0249 int height = 0;
0250 do {
0251 if (++height > height_) return nullptr;
0252 edge = node_[height];
0253 index = index_[height];
0254 } while (index == edge->begin());
0255 index_[height] = static_cast<uint8_t>(--index);
0256 do {
0257 node_[--height] = edge = edge->Edge(index)->btree();
0258 index_[height] = static_cast<uint8_t>(index = edge->back());
0259 } while (height > 0);
0260 return edge->Edge(index);
0261 }
0262
0263 }
0264 ABSL_NAMESPACE_END
0265 }
0266
0267 #endif