19 #include <hilti/rt/any.h> 20 #include <hilti/rt/exception.h> 21 #include <hilti/rt/intrusive-ptr.h> 22 #include <hilti/rt/logging.h> 23 #include <hilti/rt/result.h> 24 #include <hilti/rt/safe-int.h> 25 #include <hilti/rt/types/bytes.h> 26 #include <hilti/rt/types/time.h> 27 #include <hilti/rt/types/vector.h> 28 #include <hilti/rt/util.h> 36 class SafeConstIterator;
43 namespace detail::adl {
55 using Offset = integer::safe<uint64_t>;
58 using Size = integer::safe<uint64_t>;
61 enum class Direction : int64_t { Forward, Backward };
89 static const int SmallBufferSize = 32;
90 using Array = std::pair<Size, std::array<Byte, SmallBufferSize>>;
91 using Vector = std::vector<Byte>;
93 Chunk(Offset o, std::array<Byte, SmallBufferSize> d, Size n) : _offset(o), _data(std::make_pair(n, d)) {}
94 Chunk(Offset o, Vector&& d) : _offset(o), _data(std::move(d)) {}
96 Chunk(Offset o,
const std::string& s);
99 Chunk(Offset o, std::array<Byte, N> d) : Chunk(_fromArray(o, std::move(d))) {}
100 Chunk(Offset o,
const char* d, Size n) : Chunk(_fromArray(o, d, n)) {}
103 Chunk(Offset o,
size_t len) : _offset(o), _data(
Gap{len}) {}
105 Chunk(
const Chunk& other) : _offset(other._offset), _data(other._data) {}
106 Chunk(Chunk&& other) noexcept
107 : _offset(other._offset), _data(std::move(other._data)), _next(std::move(other._next)) {}
109 Chunk& operator=(
const Chunk& other) =
delete;
111 Chunk& operator=(Chunk&& other) noexcept {
112 _offset = other._offset;
113 _data = std::move(other._data);
114 _next = std::move(other._next);
115 _chain = other._chain;
121 Offset offset()
const {
return _offset; }
122 Offset endOffset()
const {
return _offset + size(); }
123 bool isGap()
const {
return std::holds_alternative<Gap>(_data); }
124 bool inRange(Offset offset)
const {
return offset >= _offset && offset < endOffset(); }
126 const Byte* data()
const {
127 if (
auto a = std::get_if<Array>(&_data) )
128 return a->second.data();
129 else if (
auto a = std::get_if<Vector>(&_data) ) {
132 else if (
auto a = std::get_if<Gap>(&_data) )
133 throw MissingData(
"data is missing");
138 const Byte* data(Offset offset)
const {
139 assert(inRange(offset));
140 return data() + (offset - _offset).Ref();
143 const Byte* endData()
const {
144 if (
auto a = std::get_if<Array>(&_data) )
145 return a->second.data() + a->first.Ref();
146 else if (
auto a = std::get_if<Vector>(&_data) ) {
147 return a->data() + a->size();
149 else if (
auto a = std::get_if<Gap>(&_data) )
150 throw MissingData(
"data is missing");
156 if (
auto a = std::get_if<Array>(&_data) )
158 else if (
auto a = std::get_if<Vector>(&_data) )
160 else if (
auto a = std::get_if<Gap>(&_data) )
166 bool isLast()
const {
return ! _next; }
167 const Chunk* next()
const {
return _next.get(); }
170 const Chunk* i =
this;
171 while ( i && i->_next )
178 while ( i && i->_next )
183 void debugPrint(std::ostream& out)
const;
193 void setOffset(Offset o) {
203 void setChain(
const Chain* chain) {
211 Chunk* next() {
return _next.get(); }
215 void setNext(std::unique_ptr<Chunk> next) {
218 Offset offset = endOffset();
219 _next = std::move(next);
221 auto c = _next.get();
230 void clearNext() { _next =
nullptr; }
233 inline Chunk _fromArray(Offset o,
const char* d, Size n) {
234 auto ud =
reinterpret_cast<const Byte*
>(d);
236 if ( n <= Chunk::SmallBufferSize ) {
237 std::array<Byte, Chunk::SmallBufferSize> x{};
238 std::copy(ud, ud + n.Ref(), x.data());
239 return Chunk(o, x, n);
242 return Chunk(o, Chunk::Vector(ud, ud + n.Ref()));
246 std::variant<Array, Vector, Gap> _data;
247 const Chain* _chain =
nullptr;
249 std::unique_ptr<Chunk> _next =
nullptr;
262 using Size = stream::Size;
267 Chain(std::unique_ptr<Chunk> head) : _head(
std::move(head)), _tail(_head->last()) { _head->setChain(
this); }
271 Chain& operator=(
const Chain& other) =
delete;
272 Chain& operator=(
const Chain&& other) =
delete;
274 const Chunk* head()
const {
return _head.get(); }
275 const Chunk* tail()
const {
return _tail; }
276 Size size()
const {
return (endOffset() - offset()).Ref(); }
277 bool isFrozen()
const {
return _state == State::Frozen; }
278 bool isValid()
const {
return _state != State::Invalid; }
279 bool inRange(Offset o)
const {
return o >= offset() && o < endOffset(); }
281 Offset offset()
const {
return _head_offset; }
282 Offset endOffset()
const {
return _tail ? _tail->endOffset() : _head_offset; }
289 const Chunk* findChunk(Offset offset,
const Chunk* hint_prev =
nullptr)
const;
290 Chunk* findChunk(Offset offset,
Chunk* hint_prev =
nullptr);
294 const Byte* data(Offset offset,
Chunk* hint_prev =
nullptr)
const;
306 void append(std::unique_ptr<Chunk> chunk);
307 void append(
Chain&& other);
309 void trim(Offset offset);
316 _state = State::Invalid;
324 _state = State::Mutable;
332 _state = State::Frozen;
336 _state = State::Mutable;
340 int numberOfChunks()
const;
343 void _ensureValid()
const {
345 throw InvalidIterator(
"stream object no longer available");
348 void _ensureMutable()
const {
350 throw Frozen(
"stream object can no longer be modified");
360 State _state = State::Mutable;
363 std::unique_ptr<Chunk> _head =
nullptr;
369 Offset _head_offset = 0;
373 Chunk* _tail =
nullptr;
393 using Byte = stream::Byte;
397 using Offset = stream::Offset;
398 using Size = stream::Size;
408 Offset
offset()
const {
return _offset; }
411 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
474 _ensureSameChain(other);
475 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
484 _ensureSameChain(other);
485 return (_offset == other._offset) || (isEnd() && other.
isEnd());
494 _ensureSameChain(other);
495 return ! (*
this == other);
500 _ensureSameChain(other);
501 return offset() < other.
offset();
506 _ensureSameChain(other);
507 return offset() <= other.
offset();
512 _ensureSameChain(other);
513 return offset() > other.
offset();
518 _ensureSameChain(other);
519 return offset() >= other.
offset();
523 explicit operator bool()
const {
return ! isUnset(); }
525 std::ostream& operator<<(std::ostream& out)
const {
541 return ! _chain->isValid();
548 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
560 return _offset >= _chain->endOffset();
567 void debugPrint(std::ostream& out)
const;
576 const Chunk* chunk()
const {
return _chain && _chain->isValid() && _chain->inRange(_offset) ? _chunk :
nullptr; }
577 const Chain* chain()
const {
return _chain.get(); }
581 : _chain(std::move(chain)), _offset(offset), _chunk(chunk) {
585 void _ensureValidChain()
const {
589 if ( ! _chain->isValid() )
590 throw InvalidIterator(
"stream object no longer available");
594 if ( ! (_chain && other._chain) )
599 throw InvalidIterator(
"stream object no longer available");
601 if ( _chain != other._chain )
602 throw InvalidIterator(
"incompatible iterators");
605 void _increment(integer::safe<uint64_t> n) {
607 throw InvalidIterator(
"unbound stream iterator");
614 if ( ! (_chain && _chain->isValid()) )
617 _chunk = _chain->findChunk(_offset, chunk());
621 void _decrement(integer::safe<uint64_t> n) {
623 throw InvalidIterator(
"unbound stream iterator");
626 throw InvalidIterator(
"attempt to move before beginning of stream");
633 if ( _chunk && _offset > _chunk->offset() )
636 if ( ! (_chain && _chain->isValid()) )
639 _chunk = _chain->findChunk(_offset, _chunk);
643 Byte _dereference()
const {
645 throw InvalidIterator(
"unbound stream iterator");
649 if ( ! _chain->inRange(_offset) )
650 throw InvalidIterator(
"stream iterator outside of valid range");
652 auto c = _chain->findChunk(_offset, chunk());
656 throw MissingData(
"data is missing");
658 return *c->data(_offset);
682 const Chunk* _chunk =
nullptr;
704 using Byte = stream::Byte;
708 using Offset = stream::Offset;
709 using Size = stream::Size;
718 Offset
offset()
const {
return _offset; }
721 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
778 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
787 return (_offset == other._offset) || (isEnd() && other.
isEnd());
810 explicit operator bool()
const {
return ! isUnset(); }
812 std::ostream& operator<<(std::ostream& out)
const {
828 return ! _chain->isValid();
835 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
842 return _offset >= _chain->endOffset();
849 void debugPrint(std::ostream& out)
const;
856 const Chunk* chunk()
const {
return _chunk; }
857 const Chain* chain()
const {
return _chain; }
861 : _chain(chain.get()), _offset(offset), _chunk(chunk) {
866 : _chain(chain), _offset(offset), _chunk(chunk) {
870 void _increment(integer::safe<uint64_t> n) {
873 if ( _chunk && _offset < _chunk->endOffset() )
876 _chunk = _chain->findChunk(_offset, _chunk);
879 void _decrement(integer::safe<uint64_t> n) {
882 if ( _chunk && _offset > _chunk->offset() )
885 _chunk = _chain->findChunk(_offset, _chunk);
888 Byte _dereference()
const {
897 auto* byte = _chunk->data(_offset);
900 throw MissingData(
"data is missing");
908 const Chain* _chain =
nullptr;
918 const Chunk* _chunk =
nullptr;
922 : _chain(i.chain()), _offset(i.
offset()), _chunk(i.chain() ? i.chain()->findChunk(_offset, i.chunk()) : nullptr) {}
932 return _extract<N - 1>(dst + 1, i + 1);
945 return _extract<N>(dst, i);
978 if ( i.chain() != this )
979 throw InvalidIterator(
"incompatible iterator");
982 throw InvalidIterator(
"stream object no longer available");
992 : _chain(detail::
ConstChainPtr(intrusive_ptr::NewRef(), i._chain)), _offset(i._offset), _chunk(i._chunk) {}
1003 using Byte = stream::Byte;
1007 using Offset = stream::Offset;
1008 using Size = stream::Size;
1021 if ( ! _end->_chain )
1022 _end = _begin.chain()->end();
1024 _ensureSameChain(*_end);
1038 Offset
offset()
const {
return _begin.offset(); }
1080 _ensureSameChain(n);
1102 std::tuple<bool, SafeConstIterator>
find(
const View& v)
const {
1120 _ensureSameChain(n);
1147 std::tuple<bool, SafeConstIterator>
find(
const Bytes& v, Direction d = Direction::Forward)
const {
1149 auto i = (d == Direction::Forward ? unsafeBegin() : unsafeEnd());
1150 auto x = find(v, std::move(i), d);
1166 Direction d = Direction::Forward)
const {
1168 _ensureSameChain(n);
1185 Direction d = Direction::Forward)
const {
1186 if ( d == Direction::Forward )
1187 return _findForward(v, std::move(n));
1189 return _findBackward(v, std::move(n));
1199 _ensureSameChain(i);
1200 return View(std::move(i), _end);
1213 View advanceToNextData()
const;
1222 _ensureSameChain(from);
1223 _ensureSameChain(to);
1224 return View(std::move(from), std::move(to));
1234 _ensureSameChain(to);
1235 return View(begin(), std::move(to));
1244 View sub(Offset from, Offset to)
const {
return View(begin() + from, begin() + to); }
1263 _ensureSameChain(nbegin);
1266 return View(nbegin);
1268 if ( nbegin.
offset() > _end->offset() )
1269 return View(*_end, *_end);
1271 return View(nbegin, *_end);
1300 void copyRaw(Byte* dst)
const;
1306 std::string dataForPrint()
const;
1319 assert(_begin.chain());
1320 return _end ? *_end : _begin.chain()->end();
1336 std::optional<Block> firstBlock()
const;
1341 std::optional<Block> nextBlock(std::optional<Block> current)
const;
1352 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1354 bool operator!=(
const View& other)
const {
return ! (*
this == other); }
1363 : _begin(
std::move(begin)), _end(
std::move(end)) {
1365 _ensureSameChain(*_end);
1369 if ( _begin.chain() != other.chain() )
1370 throw InvalidIterator(
"incompatible iterator");
1373 void _ensureValid()
const {
1380 if ( _end && ! _end->isValid() )
1381 throw InvalidIterator(
"view has invalid end");
1391 std::optional<SafeConstIterator> _end;
1409 using Byte = stream::Byte;
1413 using Offset = stream::Offset;
1415 using Size = stream::Size;
1445 Stream(
const char* d, Size n);
1469 Stream(
Stream&& other) noexcept : _chain(std::move(other._chain)) { other._chain = make_intrusive<Chain>(); }
1476 if ( &other ==
this )
1479 _chain->invalidate();
1480 _chain = std::move(other._chain);
1481 other._chain = make_intrusive<Chain>();
1490 if ( &other ==
this )
1493 _chain->invalidate();
1494 _chain = other._chain->deepCopy();
1501 _chain->invalidate();
1505 Size
size()
const {
return _chain->size(); }
1508 bool isEmpty()
const {
return _chain->size() == 0; }
1514 void append(
const Bytes& data);
1520 void append(
Bytes&& data);
1526 void append(std::unique_ptr<const Byte*> data);
1532 void append(
const char* data,
size_t len);
1577 View view(
bool expanding =
true)
const {
return expanding ?
View(begin()) : View(begin(), end()); }
1582 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1603 Stream(
Chunk&& ch) : _chain(make_intrusive<Chain>(std::make_unique<Chunk>(std::move(ch)))) {}
1609 inline std::string detail::to_string_for_print<stream::View>(
const stream::View& x) {
1610 return escapeBytes(x.dataForPrint(),
true);
1614 inline std::string detail::to_string_for_print<Stream>(
const Stream& x) {
1615 return to_string_for_print(x.view());
1618 inline std::ostream& operator<<(std::ostream& out,
const Stream& x) {
return out << to_string_for_print(x); }
1620 namespace detail::adl {
Chain(std::unique_ptr< Chunk > head)
Definition: stream.h:267
View extract(Byte(&dst)[N]) const
Definition: stream.h:1289
std::tuple< bool, SafeConstIterator > find(const Bytes &v, Direction d=Direction::Forward) const
Definition: stream.h:1147
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:1233
const auto operator--(int)
Definition: stream.h:743
auto & operator+=(integer::safe< uint64_t > i)
Definition: stream.h:427
void trim(const SafeConstIterator &i)
Definition: stream.h:1542
View(SafeConstIterator begin)
Definition: stream.h:1032
bool operator>=(const UnsafeConstIterator &other) const
Definition: stream.h:807
auto operator*() const
Definition: stream.h:756
const detail::Chunk * _block
Definition: stream.h:1330
bool isUnset() const
Definition: stream.h:818
detail::UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1309
SafeConstIterator end() const
Definition: stream.h:1557
SafeConstIterator at(Offset offset) const
Definition: stream.h:1569
Stream(const char *d)
Definition: stream.h:1439
std::tuple< bool, UnsafeConstIterator > find(const Bytes &v, UnsafeConstIterator n, Direction d=Direction::Forward) const
Definition: stream.h:1184
bool operator>(const SafeConstIterator &other) const
Definition: stream.h:511
bool operator<=(const UnsafeConstIterator &other) const
Definition: stream.h:801
Definition: intrusive-ptr.h:25
const auto operator++(int)
Definition: stream.h:730
Stream & operator=(const Stream &other)
Definition: stream.h:1489
Offset offset() const
Definition: stream.h:1038
void internalError(const std::string &msg) __attribute__((noreturn))
Definition: logging.cc:17
uint64_t offset
Definition: stream.h:1327
auto & operator-=(integer::safe< uint64_t > i)
Definition: stream.h:750
Definition: optional.h:79
UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1560
const Byte * start
Definition: stream.h:1325
Definition: intrusive-ptr.h:28
integer::safe< int64_t > operator-(const SafeConstIterator &other) const
Definition: stream.h:473
Definition: stream.h:1324
bool operator==(const UnsafeConstIterator &other) const
Definition: stream.h:786
SafeConstIterator begin() const
Definition: stream.h:1554
const auto operator++(int)
Definition: stream.h:420
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.h:201
bool isEmpty() const
Definition: stream.h:1048
Stream & operator=(Stream &&other) noexcept
Definition: stream.h:1475
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:52
View sub(Offset to) const
Definition: stream.h:1252
View limit(Offset incr) const
Definition: stream.h:1279
bool is_first
Definition: stream.h:1328
bool isEmpty() const
Definition: stream.h:1508
bool operator<=(const SafeConstIterator &other) const
Definition: stream.h:505
auto & operator--()
Definition: stream.h:737
bool operator<(const SafeConstIterator &other) const
Definition: stream.h:499
bool operator!=(const SafeConstIterator &other) const
Definition: stream.h:493
SafeConstIterator find(Byte b, const SafeConstIterator &n) const
Definition: stream.h:1078
Definition: stream.h:1001
auto & operator--()
Definition: stream.h:433
bool isEnd() const
Definition: stream.h:838
detail::UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1312
bool isValid() const
Definition: stream.h:835
UnsafeConstIterator()=default
void unfreeze()
Definition: stream.h:1548
bool isExpired() const
Definition: stream.h:824
int numberOfChunks() const
Definition: stream.h:1590
Offset offset() const
Definition: stream.h:718
View advance(SafeConstIterator i) const
Definition: stream.h:1198
Stream(const stream::View &d)
Definition: stream.h:1450
bool isFrozen() const
Definition: stream.h:721
SafeConstIterator()=default
bool isExpired() const
Definition: stream.h:537
std::tuple< bool, SafeConstIterator > find(const View &v) const
Definition: stream.h:1102
bool isValid() const
Definition: stream.h:548
bool operator!=(const UnsafeConstIterator &other) const
Definition: stream.h:795
bool isUnset() const
Definition: stream.h:531
View sub(SafeConstIterator from, SafeConstIterator to) const
Definition: stream.h:1221
View advance(integer::safe< uint64_t > i) const
Definition: stream.h:1208
Stream(std::vector< std::array< Byte, N >> d)
Definition: stream.h:1457
Stream(std::vector< Byte > d)
Definition: stream.h:1427
auto & operator-=(integer::safe< uint64_t > i)
Definition: stream.h:446
bool is_last
Definition: stream.h:1329
Definition: stream.h:1407
Definition: intrusive-ptr.h:69
Stream()
Definition: stream.h:1421
Stream(Stream &&other) noexcept
Definition: stream.h:1469
const auto operator--(int)
Definition: stream.h:439
void debugPrint(std::ostream &out) const
Definition: stream.cc:577
Size size() const
Definition: stream.h:1505
bool isOpenEnded() const
Definition: stream.h:1058
bool isFrozen() const
Definition: stream.h:1551
bool isFrozen() const
Definition: stream.h:1051
bool operator==(const SafeConstIterator &other) const
Definition: stream.h:483
std::tuple< bool, SafeConstIterator > find(const View &v, const SafeConstIterator &n) const
Definition: stream.h:1118
auto operator*() const
Definition: stream.h:452
bool operator>=(const SafeConstIterator &other) const
Definition: stream.h:517
bool isEnd() const
Definition: stream.h:555
~Stream()
Definition: stream.h:1499
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:455
View(SafeConstIterator begin, SafeConstIterator end)
Definition: stream.h:1018
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:759
UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1563
SafeConstIterator end() const
Definition: stream.h:1318
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:113
const SafeConstIterator & begin() const
Definition: stream.h:1315
bool isFrozen() const
Definition: stream.h:411
SafeConstIterator find(Byte b) const
Definition: stream.h:1066
bool operator>(const UnsafeConstIterator &other) const
Definition: stream.h:804
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:462
void freeze()
Definition: stream.h:1545
bool operator<(const UnsafeConstIterator &other) const
Definition: stream.h:798
auto & operator++()
Definition: stream.h:724
View trim(const SafeConstIterator &nbegin) const
Definition: stream.h:1262
Stream(const Stream &other) noexcept
Definition: stream.h:1463
integer::safe< int64_t > operator-(const UnsafeConstIterator &other) const
Definition: stream.h:777
SafeConstIterator at(Offset offset) const
Definition: stream.h:1255
auto & operator++()
Definition: stream.h:414
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
View sub(Offset from, Offset to) const
Definition: stream.h:1244
std::tuple< bool, SafeConstIterator > find(const Bytes &v, const SafeConstIterator &n, Direction d=Direction::Forward) const
Definition: stream.h:1165
Offset offset() const
Definition: stream.h:408
View view(bool expanding=true) const
Definition: stream.h:1577
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:766
uint64_t size
Definition: stream.h:1326