cord_rep_btree_navigator.h
Go to the documentation of this file.
1 // Copyright 2021 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 #ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
16 #define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
17 
18 #include <cassert>
19 #include <iostream>
20 
21 #include "absl/strings/internal/cord_internal.h"
23 
24 namespace absl {
26 namespace cord_internal {
27 
28 // CordRepBtreeNavigator is a bi-directional navigator allowing callers to
29 // navigate all the (leaf) data edges in a CordRepBtree instance.
30 //
31 // A CordRepBtreeNavigator instance is by default empty. Callers initialize a
32 // navigator instance by calling one of `InitFirst()`, `InitLast()` or
33 // `InitOffset()`, which establishes a current position. Callers can then
34 // navigate using the `Next`, `Previous`, `Skip` and `Seek` methods.
35 //
36 // The navigator instance does not take or adopt a reference on the provided
37 // `tree` on any of the initialization calls. Callers are responsible for
38 // guaranteeing the lifecycle of the provided tree. A navigator instance can
39 // be reset to the empty state by calling `Reset`.
40 //
41 // A navigator only keeps positional state on the 'current data edge', it does
42 // explicitly not keep any 'offset' state. The class does accept and return
43 // offsets in the `Read()`, `Skip()` and 'Seek()` methods as these would
44 // otherwise put a big burden on callers. Callers are expected to maintain
45 // (returned) offset info if they require such granular state.
47  public:
48  // The logical position as returned by the Seek() and Skip() functions.
49  // Returns the current leaf edge for the desired seek or skip position and
50  // the offset of that position inside that edge.
51  struct Position {
53  size_t offset;
54  };
55 
56  // The read result as returned by the Read() function.
57  // `tree` contains the resulting tree which is identical to the result
58  // of calling CordRepBtree::SubTree(...) on the tree being navigated.
59  // `n` contains the number of bytes used from the last navigated to
60  // edge of the tree.
61  struct ReadResult {
63  size_t n;
64  };
65 
66  // Returns true if this instance is not empty.
67  explicit operator bool() const;
68 
69  // Returns the tree for this instance or nullptr if empty.
70  CordRepBtree* btree() const;
71 
72  // Returns the data edge of the current position.
73  // Requires this instance to not be empty.
74  CordRep* Current() const;
75 
76  // Resets this navigator to `tree`, returning the first data edge in the tree.
78 
79  // Resets this navigator to `tree`, returning the last data edge in the tree.
81 
82  // Resets this navigator to `tree` returning the data edge at position
83  // `offset` and the relative offset of `offset` into that data edge.
84  // Returns `Position.edge = nullptr` if the provided offset is greater
85  // than or equal to the length of the tree, in which case the state of
86  // the navigator instance remains unchanged.
87  Position InitOffset(CordRepBtree* tree, size_t offset);
88 
89  // Navigates to the next data edge.
90  // Returns the next data edge or nullptr if there is no next data edge, in
91  // which case the current position remains unchanged.
92  CordRep* Next();
93 
94  // Navigates to the previous data edge.
95  // Returns the previous data edge or nullptr if there is no previous data
96  // edge, in which case the current position remains unchanged.
97  CordRep* Previous();
98 
99  // Navigates to the data edge at position `offset`. Returns the navigated to
100  // data edge in `Position.edge` and the relative offset of `offset` into that
101  // data edge in `Position.offset`. Returns `Position.edge = nullptr` if the
102  // provide offset is greater than or equal to the tree's length.
103  Position Seek(size_t offset);
104 
105  // Reads `n` bytes of data starting at offset `edge_offset` of the current
106  // data edge, and returns the result in `ReadResult.tree`. `ReadResult.n`
107  // contains the 'bytes used` from the last / current data edge in the tree.
108  // This allows users that mix regular navigation (using string views) and
109  // 'read into cord' navigation to keep track of the current state, and which
110  // bytes have been consumed from a navigator.
111  // This function returns `ReadResult.tree = nullptr` if the requested length
112  // exceeds the length of the tree starting at the current data edge.
113  ReadResult Read(size_t edge_offset, size_t n);
114 
115  // Skips `n` bytes forward from the current data edge, returning the navigated
116  // to data edge in `Position.edge` and `Position.offset` containing the offset
117  // inside that data edge. Note that the state of the navigator is left
118  // unchanged if `n` is smaller than the length of the current data edge.
119  Position Skip(size_t n);
120 
121  // Resets this instance to the default / empty state.
122  void Reset();
123 
124  private:
125  // Slow path for Next() if Next() reached the end of a leaf node. Backtracks
126  // up the stack until it finds a node that has a 'next' position available,
127  // and then does a 'front dive' towards the next leaf node.
128  CordRep* NextUp();
129 
130  // Slow path for Previous() if Previous() reached the beginning of a leaf
131  // node. Backtracks up the stack until it finds a node that has a 'previous'
132  // position available, and then does a 'back dive' towards the previous leaf
133  // node.
134  CordRep* PreviousUp();
135 
136  // Generic implementation of InitFirst() and InitLast().
137  template <CordRepBtree::EdgeType edge_type>
138  CordRep* Init(CordRepBtree* tree);
139 
140  // `height_` contains the height of the current tree, or -1 if empty.
141  int height_ = -1;
142 
143  // `index_` and `node_` contain the navigation state as the 'path' to the
144  // current data edge which is at `node_[0]->Edge(index_[0])`. The contents
145  // of these are undefined until the instance is initialized (`height_ >= 0`).
148 };
149 
150 // Returns true if this instance is not empty.
151 inline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }
152 
154  return height_ >= 0 ? node_[height_] : nullptr;
155 }
156 
158  assert(height_ >= 0);
159  return node_[0]->Edge(index_[0]);
160 }
161 
162 inline void CordRepBtreeNavigator::Reset() { height_ = -1; }
163 
165  return Init<CordRepBtree::kFront>(tree);
166 }
167 
169  return Init<CordRepBtree::kBack>(tree);
170 }
171 
172 template <CordRepBtree::EdgeType edge_type>
174  assert(tree != nullptr);
175  assert(tree->size() > 0);
176  assert(tree->height() <= CordRepBtree::kMaxHeight);
177  int height = height_ = tree->height();
178  size_t index = tree->index(edge_type);
179  node_[height] = tree;
180  index_[height] = static_cast<uint8_t>(index);
181  while (--height >= 0) {
182  tree = tree->Edge(index)->btree();
183  node_[height] = tree;
184  index = tree->index(edge_type);
185  index_[height] = static_cast<uint8_t>(index);
186  }
187  return node_[0]->Edge(index);
188 }
189 
191  size_t offset) {
192  assert(btree() != nullptr);
193  int height = height_;
194  CordRepBtree* edge = node_[height];
195  if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};
197  index_[height] = static_cast<uint8_t>(index.index);
198  while (--height >= 0) {
199  edge = edge->Edge(index.index)->btree();
200  node_[height] = edge;
201  index = edge->IndexOf(index.n);
202  index_[height] = static_cast<uint8_t>(index.index);
203  }
204  return {edge->Edge(index.index), index.n};
205 }
206 
208  CordRepBtree* tree, size_t offset) {
209  assert(tree != nullptr);
210  assert(tree->height() <= CordRepBtree::kMaxHeight);
211  if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};
212  height_ = tree->height();
213  node_[height_] = tree;
214  return Seek(offset);
215 }
216 
218  CordRepBtree* edge = node_[0];
219  return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);
220 }
221 
223  CordRepBtree* edge = node_[0];
224  return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);
225 }
226 
228  assert(index_[0] == node_[0]->back());
229  CordRepBtree* edge;
230  size_t index;
231  int height = 0;
232  do {
233  if (++height > height_) return nullptr;
234  edge = node_[height];
235  index = index_[height] + 1;
236  } while (index == edge->end());
237  index_[height] = static_cast<uint8_t>(index);
238  do {
239  node_[--height] = edge = edge->Edge(index)->btree();
240  index_[height] = static_cast<uint8_t>(index = edge->begin());
241  } while (height > 0);
242  return edge->Edge(index);
243 }
244 
246  assert(index_[0] == node_[0]->begin());
247  CordRepBtree* edge;
248  size_t index;
249  int height = 0;
250  do {
251  if (++height > height_) return nullptr;
252  edge = node_[height];
253  index = index_[height];
254  } while (index == edge->begin());
255  index_[height] = static_cast<uint8_t>(--index);
256  do {
257  node_[--height] = edge = edge->Edge(index)->btree();
258  index_[height] = static_cast<uint8_t>(index = edge->back());
259  } while (height > 0);
260  return edge->Edge(index);
261 }
262 
263 } // namespace cord_internal
265 } // namespace absl
266 
267 #endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
ABSL_PREDICT_FALSE
#define ABSL_PREDICT_FALSE(x)
Definition: abseil-cpp/absl/base/optimization.h:180
absl::cord_internal::CordRepBtreeNavigator::NextUp
CordRep * NextUp()
Definition: cord_rep_btree_navigator.h:227
absl::cord_internal::CordRepBtree::end
size_t end() const
Definition: cord_rep_btree.h:290
bool
bool
Definition: setup_once.h:312
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
absl::cord_internal::CordRepBtreeNavigator::node_
CordRepBtree * node_[CordRepBtree::kMaxDepth]
Definition: cord_rep_btree_navigator.h:147
absl::cord_internal::CordRepBtree::IndexOf
Position IndexOf(size_t offset) const
Definition: cord_rep_btree.h:788
absl::cord_internal::CordRepBtreeNavigator::Position::edge
CordRep * edge
Definition: cord_rep_btree_navigator.h:52
absl::cord_internal::CordRepBtreeNavigator::Position::offset
size_t offset
Definition: cord_rep_btree_navigator.h:53
absl::cord_internal::CordRepBtreeNavigator::Seek
Position Seek(size_t offset)
Definition: cord_rep_btree_navigator.h:190
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
absl::cord_internal::CordRepBtree::kMaxHeight
static constexpr int kMaxHeight
Definition: cord_rep_btree.h:99
absl::cord_internal::CordRep
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:209
absl::cord_internal::CordRepBtreeNavigator::Init
CordRep * Init(CordRepBtree *tree)
Definition: cord_rep_btree_navigator.h:173
absl::cord_internal::CordRepBtreeNavigator::ReadResult::n
size_t n
Definition: cord_rep_btree_navigator.h:63
absl::cord_internal::CordRepBtreeNavigator::Current
CordRep * Current() const
Definition: cord_rep_btree_navigator.h:157
absl::cord_internal::CordRepBtreeNavigator
Definition: cord_rep_btree_navigator.h:46
absl::cord_internal::CordRepBtree::kMaxDepth
static constexpr int kMaxDepth
Definition: cord_rep_btree.h:98
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::cord_internal::CordRepBtreeNavigator::ReadResult::tree
CordRep * tree
Definition: cord_rep_btree_navigator.h:62
absl::cord_internal::CordRepBtree::size
size_t size() const
Definition: cord_rep_btree.h:301
absl::cord_internal::CordRepBtree::begin
size_t begin() const
Definition: cord_rep_btree.h:288
cord_rep_btree.h
absl::cord_internal::CordRepBtreeNavigator::Read
ReadResult Read(size_t edge_offset, size_t n)
Definition: cord_rep_btree_navigator.cc:108
absl::cord_internal::CordRepBtreeNavigator::Reset
void Reset()
Definition: cord_rep_btree_navigator.h:162
absl::cord_internal::CordRepBtree::index
size_t index(EdgeType edge) const
Definition: cord_rep_btree.h:291
absl::cord_internal::CordRep::length
size_t length
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:228
absl::cord_internal::CordRepBtreeNavigator::InitFirst
CordRep * InitFirst(CordRepBtree *tree)
Definition: cord_rep_btree_navigator.h:164
absl::cord_internal::CordRepBtreeNavigator::InitLast
CordRep * InitLast(CordRepBtree *tree)
Definition: cord_rep_btree_navigator.h:168
absl::cord_internal::CordRep::btree
CordRepBtree * btree()
Definition: cord_rep_btree.h:589
absl::cord_internal::CordRepBtree
Definition: cord_rep_btree.h:63
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
absl::cord_internal::CordRepBtreeNavigator::index_
uint8_t index_[CordRepBtree::kMaxDepth]
Definition: cord_rep_btree_navigator.h:146
absl::cord_internal::CordRepBtree::Edge
CordRep * Edge(size_t index) const
Definition: cord_rep_btree.h:606
absl::cord_internal::CordRepBtreeNavigator::Next
CordRep * Next()
Definition: cord_rep_btree_navigator.h:217
absl::cord_internal::CordRepBtree::Position
Definition: cord_rep_btree.h:150
absl::cord_internal::CordRepBtreeNavigator::btree
CordRepBtree * btree() const
Definition: cord_rep_btree_navigator.h:153
absl::cord_internal::CordRepBtree::back
size_t back() const
Definition: cord_rep_btree.h:289
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::cord_internal::CordRepBtree::height
int height() const
Definition: cord_rep_btree.h:285
absl::cord_internal::CordRepBtreeNavigator::InitOffset
Position InitOffset(CordRepBtree *tree, size_t offset)
Definition: cord_rep_btree_navigator.h:207
absl::cord_internal::CordRepBtreeNavigator::Position
Definition: cord_rep_btree_navigator.h:51
absl::cord_internal::CordRepBtreeNavigator::PreviousUp
CordRep * PreviousUp()
Definition: cord_rep_btree_navigator.h:245
absl::cord_internal::CordRepBtreeNavigator::height_
int height_
Definition: cord_rep_btree_navigator.h:141
absl::cord_internal::CordRepBtreeNavigator::Previous
CordRep * Previous()
Definition: cord_rep_btree_navigator.h:222
absl::cord_internal::CordRepBtreeNavigator::Skip
Position Skip(size_t n)
Definition: cord_rep_btree_navigator.cc:68
absl::cord_internal::CordRepBtreeNavigator::ReadResult
Definition: cord_rep_btree_navigator.h:61
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
height
int height
Definition: libuv/docs/code/tty-gravity/main.c:10


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:03