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(Offset o, std::array<Byte, SmallBufferSize> d, Size n) : _offset(o), _data(std::make_pair(n, d)) {}
95 Chunk(Offset o, Vector&& d) : _offset(o), _data(std::move(d)) {}
97 Chunk(Offset o,
const std::string& s);
100 Chunk(Offset o, std::array<Byte, N> d) : Chunk(_fromArray(o, std::move(d))) {}
101 Chunk(Offset o,
const char* d, Size n) : Chunk(_fromArray(o, d, n)) {}
104 Chunk(Offset o,
size_t len) : _offset(o), _data(
Gap{len}) {}
106 Chunk(
const Chunk& other) : _offset(other._offset), _data(other._data) {}
107 Chunk(Chunk&& other) noexcept
108 : _offset(other._offset), _data(std::move(other._data)), _next(std::move(other._next)) {}
110 Chunk& operator=(
const Chunk& other) =
delete;
112 Chunk& operator=(Chunk&& other) noexcept {
113 _offset = other._offset;
114 _data = std::move(other._data);
115 _next = std::move(other._next);
116 _chain = other._chain;
122 Offset offset()
const {
return _offset; }
123 Offset endOffset()
const {
return _offset + size(); }
124 bool isGap()
const {
return std::holds_alternative<Gap>(_data); }
125 bool inRange(Offset offset)
const {
return offset >= _offset && offset < endOffset(); }
127 const Byte* data()
const {
128 if (
auto a = std::get_if<Array>(&_data) )
129 return a->second.data();
130 else if (
auto a = std::get_if<Vector>(&_data) ) {
133 else if ( std::holds_alternative<Gap>(_data) )
134 throw MissingData(
"data is missing");
139 const Byte* data(Offset offset)
const {
140 assert(inRange(offset));
141 return data() + (offset - _offset).Ref();
144 const Byte* endData()
const {
145 if (
auto a = std::get_if<Array>(&_data) )
146 return a->second.data() + a->first.Ref();
147 else if (
auto a = std::get_if<Vector>(&_data) ) {
148 return a->data() + a->size();
150 else if ( std::holds_alternative<Gap>(_data) )
151 throw MissingData(
"data is missing");
157 if (
auto a = std::get_if<Array>(&_data) )
159 else if (
auto a = std::get_if<Vector>(&_data) )
161 else if (
auto a = std::get_if<Gap>(&_data) )
167 bool isLast()
const {
return ! _next; }
168 const Chunk* next()
const {
return _next.get(); }
171 const Chunk* i =
this;
172 while ( i && i->_next )
179 while ( i && i->_next )
184 void debugPrint(std::ostream& out)
const;
194 void setOffset(Offset o) {
204 void setChain(
const Chain* chain) {
212 Chunk* next() {
return _next.get(); }
216 void setNext(std::unique_ptr<Chunk> next) {
219 Offset offset = endOffset();
220 _next = std::move(next);
222 auto c = _next.get();
231 void clearNext() { _next =
nullptr; }
234 inline Chunk _fromArray(Offset o,
const char* d, Size n) {
235 auto ud =
reinterpret_cast<const Byte*
>(d);
237 if ( n <= Chunk::SmallBufferSize ) {
238 std::array<Byte, Chunk::SmallBufferSize> x{};
239 std::copy(ud, ud + n.Ref(), x.data());
240 return Chunk(o, x, n);
243 return Chunk(o, Chunk::Vector(ud, ud + n.Ref()));
247 std::variant<Array, Vector, Gap> _data;
248 const Chain* _chain =
nullptr;
250 std::unique_ptr<Chunk> _next =
nullptr;
263 using Size = stream::Size;
268 Chain(std::unique_ptr<Chunk> head) : _head(
std::move(head)), _tail(_head->last()) { _head->setChain(
this); }
272 Chain& operator=(
const Chain& other) =
delete;
273 Chain& operator=(
const Chain&& other) =
delete;
275 const Chunk* head()
const {
return _head.get(); }
276 const Chunk* tail()
const {
return _tail; }
277 Size size()
const {
return (endOffset() - offset()).Ref(); }
278 bool isFrozen()
const {
return _state == State::Frozen; }
279 bool isValid()
const {
return _state != State::Invalid; }
280 bool inRange(Offset o)
const {
return o >= offset() && o < endOffset(); }
282 Offset offset()
const {
return _head_offset; }
283 Offset endOffset()
const {
return _tail ? _tail->endOffset() : _head_offset; }
290 const Chunk* findChunk(Offset offset,
const Chunk* hint_prev =
nullptr)
const;
291 Chunk* findChunk(Offset offset,
Chunk* hint_prev =
nullptr);
295 const Byte* data(Offset offset,
Chunk* hint_prev =
nullptr)
const;
307 void append(std::unique_ptr<Chunk> chunk);
308 void append(
Chain&& other);
310 void trim(Offset offset);
317 _state = State::Invalid;
325 _state = State::Mutable;
333 _state = State::Frozen;
337 _state = State::Mutable;
341 int numberOfChunks()
const;
344 void _ensureValid()
const {
346 throw InvalidIterator(
"stream object no longer available");
349 void _ensureMutable()
const {
351 throw Frozen(
"stream object can no longer be modified");
361 State _state = State::Mutable;
364 std::unique_ptr<Chunk> _head =
nullptr;
370 Offset _head_offset = 0;
374 Chunk* _tail =
nullptr;
394 using Byte = stream::Byte;
398 using Offset = stream::Offset;
399 using Size = stream::Size;
409 Offset
offset()
const {
return _offset; }
412 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
475 _ensureSameChain(other);
476 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
485 _ensureSameChain(other);
486 return (_offset == other._offset) || (isEnd() && other.
isEnd());
495 _ensureSameChain(other);
496 return ! (*
this == other);
501 _ensureSameChain(other);
502 return offset() < other.
offset();
507 _ensureSameChain(other);
508 return offset() <= other.
offset();
513 _ensureSameChain(other);
514 return offset() > other.
offset();
519 _ensureSameChain(other);
520 return offset() >= other.
offset();
524 explicit operator bool()
const {
return ! isUnset(); }
526 std::ostream& operator<<(std::ostream& out)
const {
542 return ! _chain->isValid();
549 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
561 return _offset >= _chain->endOffset();
568 void debugPrint(std::ostream& out)
const;
577 const Chunk* chunk()
const {
return _chain && _chain->isValid() && _chain->inRange(_offset) ? _chunk :
nullptr; }
578 const Chain* chain()
const {
return _chain.get(); }
582 : _chain(std::move(chain)), _offset(offset), _chunk(chunk) {
586 void _ensureValidChain()
const {
590 if ( ! _chain->isValid() )
591 throw InvalidIterator(
"stream object no longer available");
595 if ( ! (_chain && other._chain) )
600 throw InvalidIterator(
"stream object no longer available");
602 if ( _chain != other._chain )
603 throw InvalidIterator(
"incompatible iterators");
606 void _increment(integer::safe<uint64_t> n) {
608 throw InvalidIterator(
"unbound stream iterator");
615 if ( ! (_chain && _chain->isValid()) )
618 _chunk = _chain->findChunk(_offset, chunk());
622 void _decrement(integer::safe<uint64_t> n) {
624 throw InvalidIterator(
"unbound stream iterator");
627 throw InvalidIterator(
"attempt to move before beginning of stream");
634 if ( _chunk && _offset > _chunk->offset() )
637 if ( ! (_chain && _chain->isValid()) )
640 _chunk = _chain->findChunk(_offset, _chunk);
644 Byte _dereference()
const {
646 throw InvalidIterator(
"unbound stream iterator");
650 if ( ! _chain->inRange(_offset) )
651 throw InvalidIterator(
"stream iterator outside of valid range");
653 auto c = _chain->findChunk(_offset, chunk());
657 throw MissingData(
"data is missing");
659 return *c->data(_offset);
683 const Chunk* _chunk =
nullptr;
705 using Byte = stream::Byte;
709 using Offset = stream::Offset;
710 using Size = stream::Size;
719 Offset
offset()
const {
return _offset; }
722 bool isFrozen()
const {
return ! _chain || _chain->isFrozen(); }
779 return static_cast<int64_t
>(_offset) - static_cast<int64_t>(other._offset);
788 return (_offset == other._offset) || (isEnd() && other.
isEnd());
811 explicit operator bool()
const {
return ! isUnset(); }
813 std::ostream& operator<<(std::ostream& out)
const {
829 return ! _chain->isValid();
836 bool isValid()
const {
return ! isUnset() && ! isExpired(); }
843 return _offset >= _chain->endOffset();
850 void debugPrint(std::ostream& out)
const;
857 const Chunk* chunk()
const {
return _chunk; }
858 const Chain* chain()
const {
return _chain; }
862 : _chain(chain.get()), _offset(offset), _chunk(chunk) {
867 : _chain(chain), _offset(offset), _chunk(chunk) {
871 void _increment(integer::safe<uint64_t> n) {
874 if ( _chunk && _offset < _chunk->endOffset() )
877 _chunk = _chain->findChunk(_offset, _chunk);
880 void _decrement(integer::safe<uint64_t> n) {
883 if ( _chunk && _offset > _chunk->offset() )
886 _chunk = _chain->findChunk(_offset, _chunk);
889 Byte _dereference()
const {
898 auto* byte = _chunk->data(_offset);
901 throw MissingData(
"data is missing");
909 const Chain* _chain =
nullptr;
919 const Chunk* _chunk =
nullptr;
923 : _chain(i.chain()), _offset(i.
offset()), _chunk(i.chain() ? i.chain()->findChunk(_offset, i.chunk()) : nullptr) {}
960 if ( i.chain() != this )
961 throw InvalidIterator(
"incompatible iterator");
964 throw InvalidIterator(
"stream object no longer available");
974 : _chain(detail::
ConstChainPtr(intrusive_ptr::NewRef(), i._chain)), _offset(i._offset), _chunk(i._chunk) {}
985 using Byte = stream::Byte;
989 using Offset = stream::Offset;
990 using Size = stream::Size;
1003 if ( ! _end->_chain )
1004 _end = _begin.chain()->end();
1006 _ensureSameChain(*_end);
1020 Offset
offset()
const {
return _begin.offset(); }
1028 return _end->offset();
1030 return std::nullopt;
1073 _ensureSameChain(n);
1095 std::tuple<bool, SafeConstIterator>
find(
const View& v)
const {
1113 _ensureSameChain(n);
1140 std::tuple<bool, SafeConstIterator>
find(
const Bytes& v, Direction d = Direction::Forward)
const {
1142 auto i = (d == Direction::Forward ? unsafeBegin() : unsafeEnd());
1143 auto x = find(v, std::move(i), d);
1159 Direction d = Direction::Forward)
const {
1161 _ensureSameChain(n);
1178 Direction d = Direction::Forward)
const {
1179 if ( d == Direction::Forward )
1180 return _findForward(v, std::move(n));
1182 return _findBackward(v, std::move(n));
1192 _ensureSameChain(i);
1193 return View(std::move(i), _end);
1206 View advanceToNextData()
const;
1215 _ensureSameChain(from);
1216 _ensureSameChain(to);
1217 return View(std::move(from), std::move(to));
1227 _ensureSameChain(to);
1228 return View(begin(), std::move(to));
1237 View sub(Offset from, Offset to)
const {
return View(begin() + from, begin() + to); }
1256 _ensureSameChain(nbegin);
1259 return View(nbegin);
1261 if ( nbegin.
offset() > _end->offset() )
1262 return View(*_end, *_end);
1264 return View(nbegin, *_end);
1287 auto p = unsafeBegin();
1288 for (
int i = 0; i < n; ++i )
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);
1580 View view(
bool expanding =
true)
const {
return expanding ?
View(begin()) : View(begin(), end()); }
1585 bool operator!=(
const Bytes& other)
const {
return ! (*
this == other); }
1606 Stream(
Chunk&& ch) : _chain(make_intrusive<Chain>(std::make_unique<Chunk>(std::move(ch)))) {}
1612 inline std::string detail::to_string_for_print<stream::View>(
const stream::View& x) {
1613 return escapeBytes(x.dataForPrint(),
true);
1617 inline std::string detail::to_string_for_print<Stream>(
const Stream& x) {
1618 return to_string_for_print(x.view());
1621 inline std::ostream& operator<<(std::ostream& out,
const Stream& x) {
return out << to_string_for_print(x); }
1623 namespace detail::adl {
Chain(std::unique_ptr< Chunk > head)
Definition: stream.h:268
std::tuple< bool, SafeConstIterator > find(const Bytes &v, Direction d=Direction::Forward) const
Definition: stream.h:1140
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:1226
auto & operator+=(integer::safe< uint64_t > i)
Definition: stream.h:428
void trim(const SafeConstIterator &i)
Definition: stream.h:1542
View(SafeConstIterator begin)
Definition: stream.h:1014
bool operator>=(const UnsafeConstIterator &other) const
Definition: stream.h:808
auto operator*() const
Definition: stream.h:757
const detail::Chunk * _block
Definition: stream.h:1330
bool isUnset() const
Definition: stream.h:819
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:1177
bool operator>(const SafeConstIterator &other) const
Definition: stream.h:512
bool operator<=(const UnsafeConstIterator &other) const
Definition: stream.h:802
Definition: intrusive-ptr.h:26
std::optional< Offset > endOffset() const
Definition: stream.h:1026
Stream & operator=(const Stream &other)
Definition: stream.h:1489
Offset offset() const
Definition: stream.h:1020
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:751
Definition: optional.h:79
UnsafeConstIterator unsafeBegin() const
Definition: stream.h:1560
const Byte * start
Definition: stream.h:1325
Definition: intrusive-ptr.h:29
integer::safe< int64_t > operator-(const SafeConstIterator &other) const
Definition: stream.h:474
Definition: stream.h:1324
auto operator--(int)
Definition: stream.h:744
bool operator==(const UnsafeConstIterator &other) const
Definition: stream.h:787
SafeConstIterator begin() const
Definition: stream.h:1554
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.h:201
bool isEmpty() const
Definition: stream.h:1041
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:1245
View limit(Offset incr) const
Definition: stream.h:1272
bool is_first
Definition: stream.h:1328
bool isEmpty() const
Definition: stream.h:1508
bool operator<=(const SafeConstIterator &other) const
Definition: stream.h:506
auto & operator--()
Definition: stream.h:738
bool operator<(const SafeConstIterator &other) const
Definition: stream.h:500
bool operator!=(const SafeConstIterator &other) const
Definition: stream.h:494
auto operator++(int)
Definition: stream.h:731
SafeConstIterator find(Byte b, const SafeConstIterator &n) const
Definition: stream.h:1071
auto & operator--()
Definition: stream.h:434
bool isEnd() const
Definition: stream.h:839
auto operator--(int)
Definition: stream.h:440
detail::UnsafeConstIterator unsafeEnd() const
Definition: stream.h:1312
bool isValid() const
Definition: stream.h:836
UnsafeConstIterator()=default
void unfreeze()
Definition: stream.h:1548
bool isExpired() const
Definition: stream.h:825
int numberOfChunks() const
Definition: stream.h:1593
Offset offset() const
Definition: stream.h:719
View advance(SafeConstIterator i) const
Definition: stream.h:1191
Stream(const stream::View &d)
Definition: stream.h:1450
bool isFrozen() const
Definition: stream.h:722
SafeConstIterator()=default
bool isExpired() const
Definition: stream.h:538
std::tuple< bool, SafeConstIterator > find(const View &v) const
Definition: stream.h:1095
Offset endOffset() const
Definition: stream.h:1572
bool isValid() const
Definition: stream.h:549
bool operator!=(const UnsafeConstIterator &other) const
Definition: stream.h:796
bool isUnset() const
Definition: stream.h:532
View sub(SafeConstIterator from, SafeConstIterator to) const
Definition: stream.h:1214
View advance(integer::safe< uint64_t > i) const
Definition: stream.h:1201
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:447
bool is_last
Definition: stream.h:1329
Definition: stream.h:1407
Definition: intrusive-ptr.h:70
Stream()
Definition: stream.h:1421
Stream(Stream &&other) noexcept
Definition: stream.h:1469
auto operator++(int)
Definition: stream.h:421
void debugPrint(std::ostream &out) const
Definition: stream.cc:592
Size size() const
Definition: stream.h:1505
bool isOpenEnded() const
Definition: stream.h:1051
bool isFrozen() const
Definition: stream.h:1551
bool isFrozen() const
Definition: stream.h:1044
bool operator==(const SafeConstIterator &other) const
Definition: stream.h:484
View extract(Byte *dst, uint64_t n) const
Definition: stream.h:1281
std::tuple< bool, SafeConstIterator > find(const View &v, const SafeConstIterator &n) const
Definition: stream.h:1111
auto operator*() const
Definition: stream.h:453
bool operator>=(const SafeConstIterator &other) const
Definition: stream.h:518
bool isEnd() const
Definition: stream.h:556
~Stream()
Definition: stream.h:1499
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:456
View(SafeConstIterator begin, SafeConstIterator end)
Definition: stream.h:1000
auto operator+(integer::safe< uint64_t > i) const
Definition: stream.h:760
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:412
SafeConstIterator find(Byte b) const
Definition: stream.h:1059
bool operator>(const UnsafeConstIterator &other) const
Definition: stream.h:805
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:463
void freeze()
Definition: stream.h:1545
bool operator<(const UnsafeConstIterator &other) const
Definition: stream.h:799
auto & operator++()
Definition: stream.h:725
View trim(const SafeConstIterator &nbegin) const
Definition: stream.h:1255
Stream(const Stream &other) noexcept
Definition: stream.h:1463
integer::safe< int64_t > operator-(const UnsafeConstIterator &other) const
Definition: stream.h:778
SafeConstIterator at(Offset offset) const
Definition: stream.h:1248
auto & operator++()
Definition: stream.h:415
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
View sub(Offset from, Offset to) const
Definition: stream.h:1237
std::tuple< bool, SafeConstIterator > find(const Bytes &v, const SafeConstIterator &n, Direction d=Direction::Forward) const
Definition: stream.h:1158
Offset offset() const
Definition: stream.h:409
View view(bool expanding=true) const
Definition: stream.h:1580
auto operator-(integer::safe< uint64_t > i) const
Definition: stream.h:767
uint64_t size
Definition: stream.h:1326