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 { Forward, Backward };
84 static const int SmallBufferSize = 32;
85 using Array = std::pair<Size, std::array<Byte, SmallBufferSize>>;
86 using Vector = std::vector<Byte>;
88 Chunk(Offset o, std::array<Byte, SmallBufferSize>&& d, Size n)
89 : _offset(o), _data(std::make_pair(n, std::move(d))) {}
90 Chunk(Offset o, Vector&& d) : _offset(o), _data(std::move(d)) {}
92 Chunk(Offset o,
const std::string& s);
95 Chunk(Offset o, std::array<Byte, N> d) : Chunk(_fromArray(o, std::move(d))) {}
96 Chunk(Offset o,
const char* d, Size n) : Chunk(_fromArray(o, d, n)) {}
98 Chunk(
const Chunk& other) : _offset(other._offset), _data(other._data) {}
99 Chunk(Chunk&& other) noexcept
100 : _offset(other._offset), _data(std::move(other._data)), _next(std::move(other._next)) {}
102 Chunk& operator=(
const Chunk& other) =
delete;
104 Chunk& operator=(Chunk&& other) noexcept {
105 _offset = other._offset;
106 _data = std::move(other._data);
107 _next = std::move(other._next);
108 _chain = std::move(other._chain);
114 Offset offset()
const {
return _offset; }
115 Offset endOffset()
const {
return _offset + size(); }
116 bool isCompact()
const {
return std::holds_alternative<Array>(_data); }
117 bool inRange(Offset offset)
const {
return offset >= _offset && offset < endOffset(); }
119 const Byte* data()
const {
120 if (
auto a = std::get_if<Array>(&_data) )
121 return a->second.data();
123 auto& v = std::get<Vector>(_data);
128 const Byte* data(Offset offset)
const {
129 assert(inRange(offset));
130 return data() + (offset - _offset).Ref();
133 const Byte* endData()
const {
134 if (
auto a = std::get_if<Array>(&_data) )
135 return a->second.data() + a->first.Ref();
137 auto& v = std::get<Vector>(_data);
138 return v.data() + v.size();
143 if (
auto a = std::get_if<Array>(&_data) )
146 auto& v = std::get<Vector>(_data);
150 bool isLast()
const {
return ! _next.get(); }
151 const Chunk* next()
const {
return _next.get(); }
154 const Chunk* i =
this;
155 while ( i && i->_next )
162 while ( i && i->_next )
167 void debugPrint(std::ostream& out)
const;
177 void setOffset(Offset o) {
187 void setChain(
const Chain* chain) {
195 Chunk* next() {
return _next.get(); }
199 void setNext(std::unique_ptr<Chunk> next) {
202 Offset offset = endOffset();
203 _next = std::move(next);
205 auto c = _next.get();
214 void clearNext() { _next =
nullptr; }
217 inline Chunk _fromArray(Offset o,
const char* d, Size n) {
218 auto ud =
reinterpret_cast<const Byte*
>(d);
220 if ( n <= Chunk::SmallBufferSize ) {
221 std::array<Byte, Chunk::SmallBufferSize> x{};
222 std::copy(ud, ud + n.Ref(), x.data());
223 return Chunk(o, std::move(x), n);
226 return Chunk(o, Chunk::Vector(ud, ud + n.Ref()));
230 std::variant<Array, Vector> _data;
231 const Chain* _chain =
nullptr;
233 std::unique_ptr<Chunk> _next =
nullptr;
246 using Size = stream::Size;
251 Chain(std::unique_ptr<Chunk> head) : _head(
std::move(head)), _tail(_head->last()) { _head->setChain(
this); }
255 Chain& operator=(
const Chain& other) =
delete;
256 Chain& operator=(
const Chain&& other) =
delete;
258 const Chunk* head()
const {
return _head.get(); }
259 const Chunk* tail()
const {
return _tail; }
260 Size size()
const {
return (endOffset() - offset()).Ref(); }
261 bool isFrozen()
const {
return _state == State::Frozen; }
262 bool isValid()
const {
return _state != State::Invalid; }
263 bool inRange(Offset o)
const {
return o >= offset() && o < endOffset(); }
265 Offset offset()
const {
return _head_offset; }
266 Offset endOffset()
const {
return _tail ? _tail->endOffset() : _head_offset; }
273 const Chunk* findChunk(Offset offset,
const Chunk* hint_prev =
nullptr)
const;
274 Chunk* findChunk(Offset offset,
Chunk* hint_prev =
nullptr);
278 const Byte* data(Offset offset,
Chunk* hint_prev =
nullptr)
const;
290 void append(std::unique_ptr<Chunk> chunk);
291 void append(
Chain&& other);
293 void trim(Offset offset);
300 _state = State::Invalid;
308 _state = State::Mutable;
316 _state = State::Frozen;
320 _state = State::Mutable;
324 int numberOfChunks()
const;
327 void _ensureValid()
const {
329 throw InvalidIterator(
"stream object no longer available");
332 void _ensureMutable()
const {
334 throw Frozen(
"stream object can no longer be modified");
344 State _state = State::Mutable;
347 std::unique_ptr<Chunk> _head =
nullptr;
353 Offset _head_offset = 0;
357 Chunk* _tail =
nullptr;
377 using Byte = stream::Byte;
381 using Offset = stream::Offset;
382 using Size = stream::Size;
392 Offset
offset()
const {
return _offset; }
395 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
458 _ensureSameChain(other);
459 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
468 _ensureSameChain(other);
469 return (_offset == other._offset) || (isEnd() && other.
isEnd());
478 _ensureSameChain(other);
479 return ! (*
this == other);
484 _ensureSameChain(other);
485 return offset() < other.
offset();
490 _ensureSameChain(other);
491 return offset() <= other.
offset();
496 _ensureSameChain(other);
497 return offset() > other.
offset();
502 _ensureSameChain(other);
503 return offset() >= other.
offset();
507 explicit operator bool()
const {
return ! isUnset(); }
509 std::ostream& operator<<(std::ostream& out)
const {
525 return ! _chain->isValid();
532 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
544 return _offset >= _chain->endOffset();
551 void debugPrint(std::ostream& out)
const;
560 const Chunk* chunk()
const {
return _chain && _chain->isValid() && _chain->inRange(_offset) ? _chunk :
nullptr; }
561 const Chain* chain()
const {
return _chain.get(); }
565 : _chain(chain), _offset(offset), _chunk(chunk) {
569 void _ensureValidChain()
const {
573 if ( ! _chain->isValid() )
574 throw InvalidIterator(
"stream object no longer available");
578 if ( ! (_chain && other._chain) )
583 throw InvalidIterator(
"stream object no longer available");
585 if ( _chain != other._chain )
586 throw InvalidIterator(
"incompatible iterators");
589 void _increment(integer::safe<uint64_t> n) {
591 throw InvalidIterator(
"unbound stream iterator");
598 if ( ! (_chain && _chain->isValid()) )
601 _chunk = _chain->findChunk(_offset, chunk());
605 void _decrement(integer::safe<uint64_t> n) {
607 throw InvalidIterator(
"unbound stream iterator");
610 throw InvalidIterator(
"attempt to move before beginning of stream");
617 if ( _chunk && _offset > _chunk->offset() )
620 if ( ! (_chain && _chain->isValid()) )
623 _chunk = _chain->findChunk(_offset, _chunk);
627 Byte _dereference()
const {
629 throw InvalidIterator(
"unbound stream iterator");
633 if ( ! _chain->inRange(_offset) )
634 throw InvalidIterator(
"stream iterator outside of valid range");
636 auto c = _chain->findChunk(_offset, chunk());
638 return *c->data(_offset);
662 const Chunk* _chunk =
nullptr;
684 using Byte = stream::Byte;
688 using Offset = stream::Offset;
689 using Size = stream::Size;
698 Offset
offset()
const {
return _offset; }
701 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
758 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
767 return (_offset == other._offset) || (isEnd() && other.
isEnd());
790 explicit operator bool()
const {
return ! isUnset(); }
792 std::ostream& operator<<(std::ostream& out)
const {
808 return ! _chain->isValid();
815 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
822 return _offset >= _chain->endOffset();
829 void debugPrint(std::ostream& out)
const;
836 const Chunk* chunk()
const {
return _chunk; }
837 const Chain* chain()
const {
return _chain; }
841 : _chain(chain.get()), _offset(offset), _chunk(chunk) {
846 : _chain(chain), _offset(offset), _chunk(chunk) {
850 void _increment(integer::safe<uint64_t> n) {
853 if ( _chunk && _offset < _chunk->endOffset() )
856 _chunk = _chain->findChunk(_offset, _chunk);
859 void _decrement(integer::safe<uint64_t> n) {
862 if ( _chunk && _offset > _chunk->offset() )
865 _chunk = _chain->findChunk(_offset, _chunk);
868 Byte _dereference()
const {
877 auto* byte = _chunk->data(_offset);
885 const Chain* _chain =
nullptr;
895 const Chunk* _chunk =
nullptr;
899 : _chain(i._chain.get()), _offset(i._offset), _chunk(i._chain ? i._chain->findChunk(_offset, i._chunk) : nullptr) {}
909 return _extract<N - 1>(dst + 1, i + 1);
922 return _extract<N>(dst, i);
955 if ( i.chain() != this )
956 throw InvalidIterator(
"incompatible iterator");
959 throw InvalidIterator(
"stream object no longer available");
969 : _chain(detail::
ConstChainPtr(intrusive_ptr::NewRef(), i._chain)), _offset(i._offset), _chunk(i._chunk) {}
980 using Byte = stream::Byte;
984 using Offset = stream::Offset;
985 using Size = stream::Size;
998 if ( ! _end->_chain )
999 _end = _begin.chain()->end();
1001 _ensureSameChain(*_end);
1015 Offset
offset()
const {
return _begin.offset(); }
1057 _ensureSameChain(n);
1079 std::tuple<bool, SafeConstIterator>
find(
const View& v)
const {
1097 _ensureSameChain(n);
1124 std::tuple<bool, SafeConstIterator>
find(
const Bytes& v, Direction d = Direction::Forward)
const {
1126 auto i = (d == Direction::Forward ? unsafeBegin() : unsafeEnd());
1127 auto x = find(v, std::move(i), d);
1143 Direction d = Direction::Forward)
const {
1145 _ensureSameChain(n);
1162 Direction d = Direction::Forward)
const {
1163 if ( d == Direction::Forward )
1164 return _findForward(v, std::move(n));
1166 return _findBackward(v, std::move(n));
1176 _ensureSameChain(i);
1177 return View(std::move(i), _end);
1194 _ensureSameChain(from);
1195 _ensureSameChain(to);
1196 return View(std::move(from), std::move(to));
1206 _ensureSameChain(to);
1207 return View(begin(), std::move(to));
1216 View sub(Offset from, Offset to)
const {
return View(begin() + from, begin() + to); }
1235 _ensureSameChain(nbegin);
1238 return View(nbegin);
1240 if ( nbegin.
offset() > _end->offset() )
1241 return View(*_end, *_end);
1243 return View(nbegin, *_end);
1272 void copyRaw(Byte* dst)
const;
1288 assert(_begin.chain());
1289 return _end ? *_end : _begin.chain()->end();
1305 std::optional<Block> firstBlock()
const;
1310 std::optional<Block> nextBlock(std::optional<Block> current)
const;
1321 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1323 bool operator!=(
const View& other)
const {
return ! (*
this == other); }
1332 : _begin(
std::move(begin)), _end(
std::move(end)) {
1334 _ensureSameChain(*_end);
1338 if ( _begin.chain() != other.chain() )
1339 throw InvalidIterator(
"incompatible iterator");
1342 void _ensureValid()
const {
1349 if ( _end && ! _end->isValid() )
1350 throw InvalidIterator(
"view has invalid end");
1360 std::optional<SafeConstIterator> _end;
1363 inline std::ostream& operator<<(std::ostream& out,
const View& x) {
1364 out << escapeBytes(x.
data().
str());
1381 using Byte = stream::Byte;
1385 using Offset = stream::Offset;
1387 using Size = stream::Size;
1439 Stream(
Stream&& other) noexcept : _chain(std::move(other._chain)) { other._chain = make_intrusive<Chain>(); }
1446 if ( &other ==
this )
1449 _chain->invalidate();
1450 _chain = std::move(other._chain);
1451 other._chain = make_intrusive<Chain>();
1460 if ( &other ==
this )
1463 _chain->invalidate();
1464 _chain = other._chain->deepCopy();
1471 _chain->invalidate();
1475 Size
size()
const {
return _chain->size(); }
1478 bool isEmpty()
const {
return _chain->size() == 0; }
1484 void append(
const Bytes& data);
1490 void append(
Bytes&& data);
1496 void append(std::unique_ptr<const Byte*> data);
1502 void append(
const char* data,
size_t len);
1547 View view(
bool expanding =
true)
const {
return expanding ?
View(begin()) : View(begin(), end()); }
1558 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1579 Stream(
Chunk&& ch) : _chain(make_intrusive<Chain>(std::make_unique<Chunk>(std::move(ch)))) {}
1584 inline std::ostream& operator<<(std::ostream& out,
const Stream& x) {
1585 out << escapeBytes(x.
data().
str());
1590 inline std::string detail::to_string_for_print<Stream>(
const Stream& x) {
1591 return escapeBytes(x.
data().
str(),
true);
1595 inline std::string detail::to_string_for_print<stream::View>(
const stream::View& x) {
1596 return escapeBytes(x.
data().
str(),
true);
1599 namespace detail::adl {
1601 return fmt(
"b\"%s\"", escapeBytes(x.
data().
str(),
true));
1604 return fmt(
"b\"%s\"", escapeBytes(x.
data().
str(),
true));
Chain(std::unique_ptr< Chunk > head)
Definition: stream.h:251
View extract(Byte(&dst)[N]) const
Definition: stream.h:1261
std::tuple< bool, SafeConstIterator > find(const Bytes &v, Direction d=Direction::Forward) const
Definition: stream.h:1124
std::string to_string(T &&x)
Definition: extension-points.h:26
Definition: exception.h:190
View sub(SafeConstIterator to) const
Definition: stream.h:1205
auto & operator+=(integer::safe< uint64_t > i)
Definition: stream.h:411
void trim(const SafeConstIterator &i)
Definition: stream.h:1512
View(SafeConstIterator begin)
Definition: stream.h:1009
bool operator>=(const UnsafeConstIterator &other) const
Definition: stream.h:787
auto operator*() const
Definition: stream.h:736
const detail::Chunk * _block
Definition: stream.h:1299
bool isUnset() const
Definition: stream.h:798
detail::UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1278
SafeConstIterator end() const
Definition: stream.h:1527
SafeConstIterator at(Offset offset) const
Definition: stream.h:1539
Stream(const char *d)
Definition: stream.h:1411
Stream(const char *d, Size n)
Definition: stream.h:1414
std::tuple< bool, UnsafeConstIterator > find(const Bytes &v, UnsafeConstIterator n, Direction d=Direction::Forward) const
Definition: stream.h:1161
bool operator>(const SafeConstIterator &other) const
Definition: stream.h:495
bool operator<=(const UnsafeConstIterator &other) const
Definition: stream.h:781
Definition: intrusive-ptr.h:25
Bytes data() const
Definition: stream.cc:429
Stream & operator=(const Stream &other)
Definition: stream.h:1459
Offset offset() const
Definition: stream.h:1015
void internalError(const std::string &msg) __attribute__((noreturn))
Definition: logging.cc:17
uint64_t offset
Definition: stream.h:1296
auto & operator-=(integer::safe< uint64_t > i)
Definition: stream.h:730
Definition: optional.h:79
UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1530
const Byte * start
Definition: stream.h:1294
Definition: intrusive-ptr.h:28
integer::safe< int64_t > operator-(const SafeConstIterator &other) const
Definition: stream.h:457
Definition: stream.h:1293
auto operator--(int)
Definition: stream.h:723
bool operator==(const UnsafeConstIterator &other) const
Definition: stream.h:766
SafeConstIterator begin() const
Definition: stream.h:1524
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.h:200
bool isEmpty() const
Definition: stream.h:1025
Stream & operator=(Stream &&other) noexcept
Definition: stream.h:1445
View sub(Offset to) const
Definition: stream.h:1224
View limit(Offset incr) const
Definition: stream.h:1251
bool is_first
Definition: stream.h:1297
bool isEmpty() const
Definition: stream.h:1478
bool operator<=(const SafeConstIterator &other) const
Definition: stream.h:489
auto & operator--()
Definition: stream.h:717
bool operator<(const SafeConstIterator &other) const
Definition: stream.h:483
bool operator!=(const SafeConstIterator &other) const
Definition: stream.h:477
auto operator++(int)
Definition: stream.h:710
SafeConstIterator find(Byte b, const SafeConstIterator &n) const
Definition: stream.h:1055
auto & operator--()
Definition: stream.h:417
bool isEnd() const
Definition: stream.h:818
auto operator--(int)
Definition: stream.h:423
detail::UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1281
bool isValid() const
Definition: stream.h:815
UnsafeConstIterator()=default
void unfreeze()
Definition: stream.h:1518
bool isExpired() const
Definition: stream.h:804
int numberOfChunks() const
Definition: stream.h:1566
Offset offset() const
Definition: stream.h:698
View advance(SafeConstIterator i) const
Definition: stream.h:1175
Stream(const stream::View &d)
Definition: stream.h:1420
bool isFrozen() const
Definition: stream.h:701
SafeConstIterator()=default
bool isExpired() const
Definition: stream.h:521
std::tuple< bool, SafeConstIterator > find(const View &v) const
Definition: stream.h:1079
bool isValid() const
Definition: stream.h:532
bool operator!=(const UnsafeConstIterator &other) const
Definition: stream.h:775
bool isUnset() const
Definition: stream.h:515
View sub(SafeConstIterator from, SafeConstIterator to) const
Definition: stream.h:1193
View advance(integer::safe< uint64_t > i) const
Definition: stream.h:1185
Stream(std::vector< std::array< Byte, N >> d)
Definition: stream.h:1427
Stream(std::vector< Byte > d)
Definition: stream.h:1399
auto & operator-=(integer::safe< uint64_t > i)
Definition: stream.h:430
bool is_last
Definition: stream.h:1298
Definition: stream.h:1379
const std::string & str() const &
Definition: bytes.h:216
Definition: intrusive-ptr.h:69
Stream()
Definition: stream.h:1393
Stream(Stream &&other) noexcept
Definition: stream.h:1439
auto operator++(int)
Definition: stream.h:404
void debugPrint(std::ostream &out) const
Definition: stream.cc:489
Size size() const
Definition: stream.h:1475
bool isOpenEnded() const
Definition: stream.h:1035
bool isFrozen() const
Definition: stream.h:1521
bool isFrozen() const
Definition: stream.h:1028
bool operator==(const SafeConstIterator &other) const
Definition: stream.h:467
std::tuple< bool, SafeConstIterator > find(const View &v, const SafeConstIterator &n) const
Definition: stream.h:1095
auto operator*() const
Definition: stream.h:436
bool operator>=(const SafeConstIterator &other) const
Definition: stream.h:501
bool isEnd() const
Definition: stream.h:539
~Stream()
Definition: stream.h:1469
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:439
View(SafeConstIterator begin, SafeConstIterator end)
Definition: stream.h:995
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:739
UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1533
SafeConstIterator end() const
Definition: stream.h:1287
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:112
const SafeConstIterator & begin() const
Definition: stream.h:1284
bool isFrozen() const
Definition: stream.h:395
SafeConstIterator find(Byte b) const
Definition: stream.h:1043
bool operator>(const UnsafeConstIterator &other) const
Definition: stream.h:784
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:446
void freeze()
Definition: stream.h:1515
bool operator<(const UnsafeConstIterator &other) const
Definition: stream.h:778
Bytes data() const
Definition: stream.cc:425
auto & operator++()
Definition: stream.h:704
View trim(const SafeConstIterator &nbegin) const
Definition: stream.h:1234
Stream(const Stream &other) noexcept
Definition: stream.h:1433
integer::safe< int64_t > operator-(const UnsafeConstIterator &other) const
Definition: stream.h:757
SafeConstIterator at(Offset offset) const
Definition: stream.h:1227
auto & operator++()
Definition: stream.h:398
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
View sub(Offset from, Offset to) const
Definition: stream.h:1216
std::tuple< bool, SafeConstIterator > find(const Bytes &v, const SafeConstIterator &n, Direction d=Direction::Forward) const
Definition: stream.h:1142
Offset offset() const
Definition: stream.h:392
View view(bool expanding=true) const
Definition: stream.h:1547
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:746
uint64_t size
Definition: stream.h:1295