12 #include <hilti/rt/exception.h> 13 #include <hilti/rt/extension-points.h> 14 #include <hilti/rt/iterator.h> 15 #include <hilti/rt/json-fwd.h> 16 #include <hilti/rt/result.h> 17 #include <hilti/rt/types/integer.h> 18 #include <hilti/rt/types/string.h> 19 #include <hilti/rt/types/time.h> 20 #include <hilti/rt/types/vector.h> 21 #include <hilti/rt/util.h> 35 enum class Side : int64_t {
42 enum class Charset : int64_t { Undef, UTF8, ASCII };
45 using B = std::string;
46 using difference_type = B::const_iterator::difference_type;
48 std::weak_ptr<B*> _control;
49 typename integer::safe<std::uint64_t> _index = 0;
54 Iterator(
typename B::size_type index, std::weak_ptr<B*> control) : _control(std::move(control)), _index(index) {}
56 uint8_t operator*()
const {
57 if (
auto&& l = _control.lock() ) {
58 auto&& data =
static_cast<B&
>(**l);
60 if ( _index >= data.size() )
61 throw IndexError(
fmt(
"index %s out of bounds", _index));
66 throw InvalidIterator(
"bound object has expired");
70 auto& operator+=(
const hilti::rt::integer::safe<T>& n) {
71 return *
this += n.Ref();
74 auto& operator+=(uint64_t n) {
80 auto operator+(
const hilti::rt::integer::safe<T>& n)
const {
81 return *
this + n.Ref();
85 auto operator+(
const T& n)
const {
86 return Iterator{_index + n, _control};
89 explicit operator bool()
const {
return static_cast<bool>(_control.lock()); }
96 auto operator++(
int) {
103 if ( a._control.lock() != b._control.lock() )
104 throw InvalidArgument(
"cannot compare iterators into different bytes");
105 return a._index == b._index;
108 friend bool operator!=(
const Iterator& a,
const Iterator& b) {
return ! (a == b); }
111 if ( a._control.lock() != b._control.lock() )
112 throw InvalidArgument(
"cannot compare iterators into different bytes");
113 return a._index < b._index;
117 if ( a._control.lock() != b._control.lock() )
118 throw InvalidArgument(
"cannot compare iterators into different bytes");
119 return a._index <= b._index;
123 if ( a._control.lock() != b._control.lock() )
124 throw InvalidArgument(
"cannot compare iterators into different bytes");
125 return a._index > b._index;
129 if ( a._control.lock() != b._control.lock() )
130 throw InvalidArgument(
"cannot compare iterators into different bytes");
131 return a._index >= b._index;
135 if ( a._control.lock() != b._control.lock() )
136 throw InvalidArgument(
"cannot perform arithmetic with iterators into different bytes");
137 return a._index - b._index;
140 friend class ::hilti::rt::Bytes;
145 inline std::ostream& operator<<(std::ostream& out,
const Iterator& ) {
146 out <<
"<bytes iterator>";
158 class Bytes :
protected std::string {
160 using Base = std::string;
162 using Base::const_reference;
163 using Base::reference;
164 using Offset = uint64_t;
165 using size_type = integer::safe<uint64_t>;
178 Bytes(std::string s, bytes::Charset cs);
180 Bytes(Base&& str) : Base(std::move(str)) {}
182 Bytes(
Bytes&& xs) noexcept : Base(std::move(xs)) {}
195 invalidateIterators();
196 this->Base::operator=(b);
208 invalidateIterators();
209 this->Base::operator=(std::move(b));
220 void append(
const uint8_t x) { Base::append(1, static_cast<Base::value_type>(x)); }
223 const std::string&
str() const& {
return *
this; }
238 size_type
size()
const {
return static_cast<int64_t
>(std::string::size()); }
247 if (
auto i = Base::find(b, (n ? n - begin() : 0)); i != Base::npos )
273 if ( from._control.lock() != to._control.lock() )
274 throw InvalidArgument(
"start and end iterator cannot belong to different bytes");
276 return sub(Offset(from - begin()), to._index);
296 return {substr(from, to - from)};
297 }
catch (
const std::out_of_range& ) {
298 throw OutOfRange(
fmt(
"start index %s out of range for bytes with length %d", from, size()));
319 throw InvalidArgument(
"insufficient data in source");
321 memcpy(dst, data(), n);
322 return sub(n, std::string::npos);
332 std::string decode(bytes::Charset cs)
const;
345 Bytes upper(bytes::Charset cs)
const {
return Bytes(hilti::rt::string::upper(decode(cs)), cs); }
352 Bytes lower(bytes::Charset cs)
const {
return Bytes(hilti::rt::string::lower(decode(cs)), cs); }
362 Bytes strip(
const Bytes&
set, bytes::Side side = bytes::Side::Both)
const;
371 Bytes strip(bytes::Side side = bytes::Side::Both)
const;
377 x.emplace_back(Bytes::Base(v));
385 std::tuple<Bytes, Bytes>
split1()
const {
387 return std::make_tuple(p.first, p.second);
394 x.push_back(Bytes::Base(v));
407 return std::make_tuple(p.first, p.second);
419 for (
size_t i = 0; i < parts.size(); ++i ) {
436 integer::safe<int64_t> toInt(uint64_t base = 10)
const;
445 integer::safe<uint64_t> toUInt(uint64_t base = 10)
const;
473 auto ns = ! isEmpty() ? toUInt(base) * integer::safe<uint64_t>(1
'000'000
'000) : integer::safe<uint64_t>(0); 474 return Time(ns, Time::NanosecondTag()); 484 Time toTime(hilti::rt::ByteOrder byte_order) const { 485 return Time(toUInt(byte_order) * integer::safe<uint64_t>(1'000
'000'000),
Time::NanosecondTag());
498 friend bool operator==(
const Bytes& a,
const Bytes& b) {
499 return static_cast<const Bytes::Base&
>(a) == static_cast<const Bytes::Base&>(b);
502 friend bool operator!=(
const Bytes& a,
const Bytes& b) {
return ! (a == b); }
505 friend bool operator<(
const Bytes& a,
const Bytes& b) {
506 return static_cast<const Bytes::Base&
>(a) < static_cast<const Bytes::Base&>(b);
509 friend bool operator<=(
const Bytes& a,
const Bytes& b) {
510 return static_cast<const Bytes::Base&
>(a) <= static_cast<const Bytes::Base&>(b);
513 friend bool operator>(
const Bytes& a,
const Bytes& b) {
514 return static_cast<const Bytes::Base&
>(a) > static_cast<const Bytes::Base&>(b);
517 friend bool operator>=(
const Bytes& a,
const Bytes& b) {
518 return static_cast<const Bytes::Base&
>(a) >= static_cast<const Bytes::Base&>(b);
522 return static_cast<const Bytes::Base&
>(a) + static_cast<const Bytes::Base&>(b);
527 std::shared_ptr<Base*> _control = std::make_shared<Base*>(
static_cast<Base*
>(
this));
529 void invalidateIterators() { _control = std::make_shared<Base*>(
static_cast<Base*
>(
this)); }
532 inline std::ostream& operator<<(std::ostream& out,
const Bytes& x) {
533 out << escapeBytes(x.
str(),
false);
538 inline namespace literals {
539 inline Bytes operator"" _b(
const char* str,
size_t size) {
return Bytes(Bytes::Base(str, size)); }
544 inline std::string detail::to_string_for_print<Bytes>(
const Bytes& x) {
545 return escapeBytes(x.
str(),
false);
548 namespace detail::adl {
550 std::string
to_string(
const bytes::Side& x, adl::tag );
551 std::string
to_string(
const bytes::Charset& x, adl::tag );
564 struct adl_serializer<
hilti::rt::Bytes> {};
Bytes sub(const const_iterator &to) const
Definition: bytes.h:285
std::string to_string(T &&x)
Definition: extension-points.h:26
bool isEmpty() const
Definition: bytes.h:235
std::string to_string_for_print(const T &x)
Definition: extension-points.h:45
void append(const uint8_t x)
Definition: bytes.h:220
size_type size() const
Definition: bytes.h:238
Bytes & operator=(const Bytes &b)
Definition: bytes.h:191
Bytes sub(Offset from, Offset to) const
Definition: bytes.h:294
Bytes extract(unsigned char *dst, uint64_t n) const
Definition: bytes.h:317
Bytes sub(Offset to) const
Definition: bytes.h:308
std::tuple< Bytes, Bytes > split1(const Bytes &sep) const
Definition: bytes.h:405
Time toTime(uint64_t base=10) const
Definition: bytes.h:472
std::pair< std::string, std::string > split1(std::string s)
Definition: util.cc:156
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.h:201
const_iterator begin() const
Definition: bytes.h:226
Bytes upper(bytes::Charset cs) const
Definition: bytes.h:345
const_iterator end() const
Definition: bytes.h:229
std::vector< std::string_view > split(std::string_view s, std::string_view delim)
Definition: util.cc:112
bool startsWith(const Bytes &b) const
Definition: bytes.h:335
Bytes & operator=(Bytes &&b) noexcept
Definition: bytes.h:207
void append(const Bytes &d)
Definition: bytes.h:214
ByteOrder
Definition: util.h:506
Bytes sub(const const_iterator &from, const const_iterator &to) const
Definition: bytes.h:272
const std::string & str() const &
Definition: bytes.h:223
Definition: extension-points.h:12
std::tuple< Bytes, Bytes > split1() const
Definition: bytes.h:385
Vector< Bytes > split() const
Definition: bytes.h:374
const_iterator find(value_type b, const const_iterator &n=const_iterator()) const
Definition: bytes.h:246
Bytes lower(bytes::Charset cs) const
Definition: bytes.h:352
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
const_iterator at(Offset o) const
Definition: bytes.h:232
Vector< Bytes > split(const Bytes &sep) const
Definition: bytes.h:391
Bytes join(const Vector< T > &parts) const
Definition: bytes.h:416