20 #include <hilti/rt/any.h> 21 #include <hilti/rt/exception.h> 22 #include <hilti/rt/intrusive-ptr.h> 23 #include <hilti/rt/logging.h> 24 #include <hilti/rt/result.h> 25 #include <hilti/rt/safe-int.h> 26 #include <hilti/rt/types/bytes.h> 27 #include <hilti/rt/types/time.h> 28 #include <hilti/rt/types/vector.h> 29 #include <hilti/rt/util.h> 37 class SafeConstIterator;
44 namespace detail::adl {
56 using Offset = integer::safe<uint64_t>;
59 using Size = integer::safe<uint64_t>;
62 enum class Direction : int64_t { Forward, Backward };
90 static const int SmallBufferSize = 32;
91 using Array = std::pair<Size, std::array<Byte, SmallBufferSize>>;
92 using Vector = std::vector<Byte>;
94 Chunk(
const Offset& o, std::array<Byte, SmallBufferSize> d,
const Size& n)
95 : _offset(o), _data(std::make_pair(n, d)) {}
96 Chunk(
const Offset& o, Vector&& d) : _offset(o), _data(std::move(d)) {}
98 Chunk(
const Offset& o,
const std::string& s);
101 Chunk(Offset o, std::array<Byte, N> d) : Chunk(_fromArray(o, std::move(d))) {}
102 Chunk(
const Offset& o,
const char* d,
const Size& n) : Chunk(_fromArray(o, d, n)) {}
105 Chunk(
const Offset& o,
size_t len) : _offset(o), _data(
Gap{len}) {}
107 Chunk(
const Chunk& other) : _offset(other._offset), _data(other._data) {}
108 Chunk(Chunk&& other) noexcept
109 : _offset(other._offset), _data(std::move(other._data)), _next(std::move(other._next)) {}
111 Chunk& operator=(
const Chunk& other) =
delete;
113 Chunk& operator=(Chunk&& other) noexcept {
114 _offset = other._offset;
115 _data = std::move(other._data);
116 _next = std::move(other._next);
117 _chain = other._chain;
123 Offset offset()
const {
return _offset; }
124 Offset endOffset()
const {
return _offset + size(); }
125 bool isGap()
const {
return std::holds_alternative<Gap>(_data); }
126 bool inRange(
const Offset& offset)
const {
return offset >= _offset && offset < endOffset(); }
128 const Byte* data()
const {
129 if (
auto a = std::get_if<Array>(&_data) )
130 return a->second.data();
131 else if (
auto a = std::get_if<Vector>(&_data) ) {
134 else if ( std::holds_alternative<Gap>(_data) )
135 throw MissingData(
"data is missing");
140 const Byte* data(
const Offset& offset)
const {
141 assert(inRange(offset));
142 return data() + (offset - _offset).Ref();
145 const Byte* endData()
const {
146 if (
auto a = std::get_if<Array>(&_data) )
147 return a->second.data() + a->first.Ref();
148 else if (
auto a = std::get_if<Vector>(&_data) ) {
149 return a->data() + a->size();
151 else if ( std::holds_alternative<Gap>(_data) )
152 throw MissingData(
"data is missing");
158 if (
auto a = std::get_if<Array>(&_data) )
160 else if (
auto a = std::get_if<Vector>(&_data) )
162 else if (
auto a = std::get_if<Gap>(&_data) )
168 bool isLast()
const {
return ! _next; }
169 const Chunk* next()
const {
return _next.get(); }
172 const Chunk* i =
this;
173 while ( i && i->_next )
180 while ( i && i->_next )
185 void debugPrint(std::ostream& out)
const;
192 void trim(
const Offset& o);
195 void setOffset(Offset o) {
205 void setChain(
const Chain* chain) {
213 Chunk* next() {
return _next.get(); }
217 void setNext(std::unique_ptr<Chunk> next) {
220 Offset offset = endOffset();
221 _next = std::move(next);
223 auto c = _next.get();
232 void clearNext() { _next =
nullptr; }
235 inline Chunk _fromArray(
const Offset& o,
const char* d,
const Size& n) {
236 auto ud =
reinterpret_cast<const Byte*
>(d);
238 if ( n <= Chunk::SmallBufferSize ) {
239 std::array<Byte, Chunk::SmallBufferSize> x{};
240 std::copy(ud, ud + n.Ref(), x.data());
241 return Chunk(o, x, n);
244 return Chunk(o, Chunk::Vector(ud, ud + n.Ref()));
248 std::variant<Array, Vector, Gap> _data;
249 const Chain* _chain =
nullptr;
251 std::unique_ptr<Chunk> _next =
nullptr;
264 using Size = stream::Size;
269 Chain(std::unique_ptr<Chunk> head) : _head(
std::move(head)), _tail(_head->last()) { _head->setChain(
this); }
273 Chain& operator=(
const Chain& other) =
delete;
274 Chain& operator=(
const Chain&& other) =
delete;
276 const Chunk* head()
const {
return _head.get(); }
277 const Chunk* tail()
const {
return _tail; }
278 Size size()
const {
return (endOffset() - offset()).Ref(); }
279 bool isFrozen()
const {
return _state == State::Frozen; }
280 bool isValid()
const {
return _state != State::Invalid; }
281 bool inRange(
const Offset& o)
const {
return o >= offset() && o < endOffset(); }
283 Offset offset()
const {
return _head_offset; }
284 Offset endOffset()
const {
return _tail ? _tail->endOffset() : _head_offset; }
291 const Chunk* findChunk(
const Offset& offset,
const Chunk* hint_prev =
nullptr)
const;
292 Chunk* findChunk(
const Offset& offset,
Chunk* hint_prev =
nullptr);
296 const Byte* data(
const Offset& offset,
Chunk* hint_prev =
nullptr)
const;
308 void append(std::unique_ptr<Chunk> chunk);
309 void append(
Chain&& other);
311 void trim(
const Offset& offset);
318 _state = State::Invalid;
326 _state = State::Mutable;
334 _state = State::Frozen;
338 _state = State::Mutable;
342 int numberOfChunks()
const;
345 void _ensureValid()
const {
347 throw InvalidIterator(
"stream object no longer available");
350 void _ensureMutable()
const {
352 throw Frozen(
"stream object can no longer be modified");
362 State _state = State::Mutable;
365 std::unique_ptr<Chunk> _head =
nullptr;
371 Offset _head_offset = 0;
375 Chunk* _tail =
nullptr;
395 using Byte = stream::Byte;
399 using Offset = stream::Offset;
400 using Size = stream::Size;
410 Offset
offset()
const {
return _offset; }
413 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
457 auto operator+(
const integer::safe<uint64_t>& i)
const {
464 auto operator-(
const integer::safe<uint64_t>& i)
const {
476 _ensureSameChain(other);
477 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
486 _ensureSameChain(other);
487 return (_offset == other._offset) || (isEnd() && other.
isEnd());
496 _ensureSameChain(other);
497 return ! (*
this == other);
502 _ensureSameChain(other);
503 return offset() < other.
offset();
508 _ensureSameChain(other);
509 return offset() <= other.
offset();
514 _ensureSameChain(other);
515 return offset() > other.
offset();
520 _ensureSameChain(other);
521 return offset() >= other.
offset();
525 explicit operator bool()
const {
return ! isUnset(); }
527 std::ostream& operator<<(std::ostream& out)
const {
543 return ! _chain->isValid();
550 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
562 return _offset >= _chain->endOffset();
569 void debugPrint(std::ostream& out)
const;
578 const Chunk* chunk()
const {
return _chain && _chain->isValid() && _chain->inRange(_offset) ? _chunk :
nullptr; }
579 const Chain* chain()
const {
return _chain.get(); }
583 : _chain(std::move(chain)), _offset(offset), _chunk(chunk) {
587 void _ensureValidChain()
const {
591 if ( ! _chain->isValid() )
592 throw InvalidIterator(
"stream object no longer available");
596 if ( ! (_chain && other._chain) )
601 throw InvalidIterator(
"stream object no longer available");
603 if ( _chain != other._chain )
604 throw InvalidIterator(
"incompatible iterators");
607 void _increment(
const integer::safe<uint64_t>& n) {
609 throw InvalidIterator(
"unbound stream iterator");
616 if ( ! (_chain && _chain->isValid()) )
619 _chunk = _chain->findChunk(_offset, chunk());
623 void _decrement(
const integer::safe<uint64_t>& n) {
625 throw InvalidIterator(
"unbound stream iterator");
628 throw InvalidIterator(
"attempt to move before beginning of stream");
635 if ( _chunk && _offset > _chunk->offset() )
638 if ( ! (_chain && _chain->isValid()) )
641 _chunk = _chain->findChunk(_offset, _chunk);
645 Byte _dereference()
const {
647 throw InvalidIterator(
"unbound stream iterator");
651 if ( ! _chain->inRange(_offset) )
652 throw InvalidIterator(
"stream iterator outside of valid range");
654 auto c = _chain->findChunk(_offset, chunk());
658 throw MissingData(
"data is missing");
660 return *c->data(_offset);
684 const Chunk* _chunk =
nullptr;
706 using Byte = stream::Byte;
710 using Offset = stream::Offset;
711 using Size = stream::Size;
720 Offset
offset()
const {
return _offset; }
723 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
761 auto operator+(
const integer::safe<uint64_t>& i)
const {
768 auto operator-(
const integer::safe<uint64_t>& i)
const {
780 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
789 return (_offset == other._offset) || (isEnd() && other.
isEnd());
812 explicit operator bool()
const {
return ! isUnset(); }
814 std::ostream& operator<<(std::ostream& out)
const {
830 return ! _chain->isValid();
837 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
844 return _offset >= _chain->endOffset();
851 void debugPrint(std::ostream& out)
const;
858 const Chunk* chunk()
const {
return _chunk; }
859 const Chain* chain()
const {
return _chain; }
863 : _chain(chain.get()), _offset(offset), _chunk(chunk) {
868 : _chain(chain), _offset(offset), _chunk(chunk) {
872 void _increment(
const integer::safe<uint64_t>& n) {
875 if ( _chunk && _offset < _chunk->endOffset() )
878 _chunk = _chain->findChunk(_offset, _chunk);
881 void _decrement(
const integer::safe<uint64_t>& n) {
884 if ( _chunk && _offset > _chunk->offset() )
887 _chunk = _chain->findChunk(_offset, _chunk);
890 Byte _dereference()
const {
899 auto* byte = _chunk->data(_offset);
902 throw MissingData(
"data is missing");
910 const Chain* _chain =
nullptr;
920 const Chunk* _chunk =
nullptr;
924 : _chain(i.chain()), _offset(i.
offset()), _chunk(i.chain() ? i.chain()->findChunk(_offset, i.chunk()) : nullptr) {}
961 if ( i.chain() != this )
962 throw InvalidIterator(
"incompatible iterator");
965 throw InvalidIterator(
"stream object no longer available");
975 : _chain(detail::
ConstChainPtr(intrusive_ptr::NewRef(), i._chain)), _offset(i._offset), _chunk(i._chunk) {}
986 using Byte = stream::Byte;
990 using Offset = stream::Offset;
991 using Size = stream::Size;
1004 if ( ! _end->_chain )
1005 _end = _begin.chain()->end();
1007 _ensureSameChain(*_end);
1021 Offset
offset()
const {
return _begin.offset(); }
1029 return _end->offset();
1031 return std::nullopt;
1074 _ensureSameChain(n);
1096 std::tuple<bool, SafeConstIterator>
find(
const View& v)
const {
1114 _ensureSameChain(n);
1141 std::tuple<bool, SafeConstIterator>
find(
const Bytes& v, Direction d = Direction::Forward)
const {
1143 auto i = (d == Direction::Forward ? unsafeBegin() : unsafeEnd());
1144 auto x = find(v, std::move(i), d);
1160 Direction d = Direction::Forward)
const {
1162 _ensureSameChain(n);
1179 Direction d = Direction::Forward)
const {
1180 if ( d == Direction::Forward )
1181 return _findForward(v, std::move(n));
1183 return _findBackward(v, std::move(n));
1193 _ensureSameChain(i);
1194 return View(std::move(i), _end);
1207 View advanceToNextData()
const;
1216 _ensureSameChain(from);
1217 _ensureSameChain(to);
1218 return View(std::move(from), std::move(to));
1228 _ensureSameChain(to);
1229 return View(begin(), std::move(to));
1238 View sub(
const Offset& from,
const Offset& to)
const {
return View(begin() + from, begin() + to); }
1246 View sub(
const Offset& to)
const {
return View(begin(), begin() + to); }
1257 _ensureSameChain(nbegin);
1260 return View(nbegin);
1262 if ( nbegin.
offset() > _end->offset() )
1263 return View(*_end, *_end);
1265 return View(nbegin, *_end);
1288 auto p = unsafeBegin();
1289 for (
int i = 0; i < n; ++i )
1301 void copyRaw(Byte* dst)
const;
1307 std::string dataForPrint()
const;
1320 assert(_begin.chain());
1321 return _end ? *_end : _begin.chain()->end();
1337 std::optional<Block> firstBlock()
const;
1342 std::optional<Block> nextBlock(std::optional<Block> current)
const;
1353 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1355 bool operator!=(
const View& other)
const {
return ! (*
this == other); }
1364 : _begin(
std::move(begin)), _end(
std::move(end)) {
1366 _ensureSameChain(*_end);
1370 if ( _begin.chain() != other.chain() )
1371 throw InvalidIterator(
"incompatible iterator");
1374 void _ensureValid()
const {
1381 if ( _end && ! _end->isValid() )
1382 throw InvalidIterator(
"view has invalid end");
1392 std::optional<SafeConstIterator> _end;
1410 using Byte = stream::Byte;
1414 using Offset = stream::Offset;
1416 using Size = stream::Size;
1446 Stream(
const char* d,
const Size& n);
1470 Stream(
Stream&& other) noexcept : _chain(std::move(other._chain)) { other._chain = make_intrusive<Chain>(); }
1477 if ( &other ==
this )
1480 _chain->invalidate();
1481 _chain = std::move(other._chain);
1482 other._chain = make_intrusive<Chain>();
1491 if ( &other ==
this )
1494 _chain->invalidate();
1495 _chain = other._chain->deepCopy();
1502 _chain->invalidate();
1506 Size
size()
const {
return _chain->size(); }
1509 bool isEmpty()
const {
return _chain->size() == 0; }
1515 void append(
const Bytes& data);
1521 void append(
Bytes&& data);
1527 void append(std::unique_ptr<const Byte*> data);
1533 void append(
const char* data,
size_t len);
1581 View view(
bool expanding =
true)
const {
return expanding ?
View(begin()) : View(begin(), end()); }
1586 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1607 Stream(
Chunk&& ch) : _chain(make_intrusive<Chain>(std::make_unique<Chunk>(std::move(ch)))) {}
1613 inline std::string detail::to_string_for_print<stream::View>(
const stream::View& x) {
1614 return escapeBytes(x.dataForPrint(),
true);
1618 inline std::string detail::to_string_for_print<Stream>(
const Stream& x) {
1619 return to_string_for_print(x.view());
1622 inline std::ostream& operator<<(std::ostream& out,
const Stream& x) {
return out << to_string_for_print(x); }
1624 namespace detail::adl {
View sub(const Offset &to) const
Definition: stream.h:1246
Chain(std::unique_ptr< Chunk > head)
Definition: stream.h:269
std::tuple< bool, SafeConstIterator > find(const Bytes &v, Direction d=Direction::Forward) const
Definition: stream.h:1141
std::string to_string(T &&x)
Definition: extension-points.h:26
std::string to_string_for_print(const T &x)
Definition: extension-points.h:45
Definition: exception.h:199
View sub(SafeConstIterator to) const
Definition: stream.h:1227
void trim(const SafeConstIterator &i)
Definition: stream.h:1543
View(SafeConstIterator begin)
Definition: stream.h:1015
bool operator>=(const UnsafeConstIterator &other) const
Definition: stream.h:809
auto operator*() const
Definition: stream.h:758
const detail::Chunk * _block
Definition: stream.h:1331
bool isUnset() const
Definition: stream.h:820
detail::UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1310
SafeConstIterator end() const
Definition: stream.h:1558
Stream(const char *d)
Definition: stream.h:1440
std::tuple< bool, UnsafeConstIterator > find(const Bytes &v, UnsafeConstIterator n, Direction d=Direction::Forward) const
Definition: stream.h:1178
bool operator>(const SafeConstIterator &other) const
Definition: stream.h:513
bool operator<=(const UnsafeConstIterator &other) const
Definition: stream.h:803
Definition: intrusive-ptr.h:25
std::optional< Offset > endOffset() const
Definition: stream.h:1027
View limit(const Offset &incr) const
Definition: stream.h:1273
SafeConstIterator at(const Offset &offset) const
Definition: stream.h:1249
Stream & operator=(const Stream &other)
Definition: stream.h:1490
Offset offset() const
Definition: stream.h:1021
void internalError(const std::string &msg) __attribute__((noreturn))
Definition: logging.cc:16
uint64_t offset
Definition: stream.h:1328
Definition: optional.h:79
UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1561
const Byte * start
Definition: stream.h:1326
auto operator+(const integer::safe< uint64_t > &i) const
Definition: stream.h:761
Definition: intrusive-ptr.h:28
auto operator-(const integer::safe< uint64_t > &i) const
Definition: stream.h:768
integer::safe< int64_t > operator-(const SafeConstIterator &other) const
Definition: stream.h:475
Definition: stream.h:1325
SafeConstIterator at(const Offset &offset) const
Definition: stream.h:1570
auto operator--(int)
Definition: stream.h:745
bool operator==(const UnsafeConstIterator &other) const
Definition: stream.h:788
SafeConstIterator begin() const
Definition: stream.h:1555
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.cc:380
bool isEmpty() const
Definition: stream.h:1042
Stream & operator=(Stream &&other) noexcept
Definition: stream.h:1476
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:42
bool is_first
Definition: stream.h:1329
auto & operator+=(const integer::safe< uint64_t > &i)
Definition: stream.h:429
bool isEmpty() const
Definition: stream.h:1509
bool operator<=(const SafeConstIterator &other) const
Definition: stream.h:507
auto & operator--()
Definition: stream.h:739
bool operator<(const SafeConstIterator &other) const
Definition: stream.h:501
bool operator!=(const SafeConstIterator &other) const
Definition: stream.h:495
auto operator++(int)
Definition: stream.h:732
SafeConstIterator find(Byte b, const SafeConstIterator &n) const
Definition: stream.h:1072
auto & operator--()
Definition: stream.h:435
bool isEnd() const
Definition: stream.h:840
auto operator--(int)
Definition: stream.h:441
View advance(const integer::safe< uint64_t > &i) const
Definition: stream.h:1202
detail::UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1313
bool isValid() const
Definition: stream.h:837
UnsafeConstIterator()=default
void unfreeze()
Definition: stream.h:1549
bool isExpired() const
Definition: stream.h:826
int numberOfChunks() const
Definition: stream.h:1594
Offset offset() const
Definition: stream.h:720
View advance(SafeConstIterator i) const
Definition: stream.h:1192
Stream(const stream::View &d)
Definition: stream.h:1451
bool isFrozen() const
Definition: stream.h:723
SafeConstIterator()=default
bool isExpired() const
Definition: stream.h:539
auto & operator-=(const integer::safe< uint64_t > &i)
Definition: stream.h:448
std::tuple< bool, SafeConstIterator > find(const View &v) const
Definition: stream.h:1096
Offset endOffset() const
Definition: stream.h:1573
bool isValid() const
Definition: stream.h:550
bool operator!=(const UnsafeConstIterator &other) const
Definition: stream.h:797
View sub(const Offset &from, const Offset &to) const
Definition: stream.h:1238
bool isUnset() const
Definition: stream.h:533
View sub(SafeConstIterator from, SafeConstIterator to) const
Definition: stream.h:1215
Stream(const Stream &other)
Definition: stream.h:1464
Stream(std::vector< std::array< Byte, N >> d)
Definition: stream.h:1458
Stream(std::vector< Byte > d)
Definition: stream.h:1428
bool is_last
Definition: stream.h:1330
Definition: stream.h:1408
auto operator-(const integer::safe< uint64_t > &i) const
Definition: stream.h:464
Definition: intrusive-ptr.h:69
Stream()
Definition: stream.h:1422
Stream(Stream &&other) noexcept
Definition: stream.h:1470
auto operator++(int)
Definition: stream.h:422
auto & operator-=(const integer::safe< uint64_t > &i)
Definition: stream.h:752
void debugPrint(std::ostream &out) const
Definition: stream.cc:592
Size size() const
Definition: stream.h:1506
bool isOpenEnded() const
Definition: stream.h:1052
bool isFrozen() const
Definition: stream.h:1552
bool isFrozen() const
Definition: stream.h:1045
bool operator==(const SafeConstIterator &other) const
Definition: stream.h:485
View extract(Byte *dst, uint64_t n) const
Definition: stream.h:1282
std::tuple< bool, SafeConstIterator > find(const View &v, const SafeConstIterator &n) const
Definition: stream.h:1112
auto operator*() const
Definition: stream.h:454
bool operator>=(const SafeConstIterator &other) const
Definition: stream.h:519
bool isEnd() const
Definition: stream.h:557
~Stream()
Definition: stream.h:1500
View(SafeConstIterator begin, SafeConstIterator end)
Definition: stream.h:1001
UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1564
SafeConstIterator end() const
Definition: stream.h:1319
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:143
const SafeConstIterator & begin() const
Definition: stream.h:1316
auto operator+(const integer::safe< uint64_t > &i) const
Definition: stream.h:457
bool isFrozen() const
Definition: stream.h:413
SafeConstIterator find(Byte b) const
Definition: stream.h:1060
bool operator>(const UnsafeConstIterator &other) const
Definition: stream.h:806
void freeze()
Definition: stream.h:1546
bool operator<(const UnsafeConstIterator &other) const
Definition: stream.h:800
auto & operator++()
Definition: stream.h:726
View trim(const SafeConstIterator &nbegin) const
Definition: stream.h:1256
integer::safe< int64_t > operator-(const UnsafeConstIterator &other) const
Definition: stream.h:779
auto & operator++()
Definition: stream.h:416
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
std::tuple< bool, SafeConstIterator > find(const Bytes &v, const SafeConstIterator &n, Direction d=Direction::Forward) const
Definition: stream.h:1159
Offset offset() const
Definition: stream.h:410
View view(bool expanding=true) const
Definition: stream.h:1581
uint64_t size
Definition: stream.h:1327