11 #include <hilti/rt/extension-points.h> 12 #include <hilti/rt/iterator.h> 13 #include <hilti/rt/json-fwd.h> 14 #include <hilti/rt/result.h> 15 #include <hilti/rt/safe-int.h> 16 #include <hilti/rt/types/string.h> 17 #include <hilti/rt/types/time.h> 18 #include <hilti/rt/types/vector.h> 19 #include <hilti/rt/util.h> 33 enum class Side : int64_t {
40 enum class Charset : int64_t { Undef, UTF8, ASCII };
43 using DecodeErrorStrategy = string::DecodeErrorStrategy;
46 using B = std::string;
47 using difference_type = B::const_iterator::difference_type;
49 std::weak_ptr<B*> _control;
50 typename integer::safe<std::uint64_t> _index = 0;
55 Iterator(
typename B::size_type index, std::weak_ptr<B*> control) : _control(std::move(control)), _index(index) {}
57 uint8_t operator*()
const {
58 if (
auto&& l = _control.lock() ) {
59 auto&& data =
static_cast<B&
>(**l);
61 if ( _index >= data.size() )
62 throw IndexError(
fmt(
"index %s out of bounds", _index));
67 throw InvalidIterator(
"bound object has expired");
71 auto& operator+=(
const hilti::rt::integer::safe<T>& n) {
72 return *
this += n.Ref();
75 auto& operator+=(uint64_t n) {
81 auto operator+(
const hilti::rt::integer::safe<T>& n)
const {
82 return *
this + n.Ref();
86 auto operator+(
const T& n)
const {
87 return Iterator{_index + n, _control};
90 explicit operator bool()
const {
return static_cast<bool>(_control.lock()); }
97 auto operator++(
int) {
104 if ( a._control.lock() != b._control.lock() )
105 throw InvalidArgument(
"cannot compare iterators into different bytes");
106 return a._index == b._index;
109 friend bool operator!=(
const Iterator& a,
const Iterator& b) {
return ! (a == b); }
112 if ( a._control.lock() != b._control.lock() )
113 throw InvalidArgument(
"cannot compare iterators into different bytes");
114 return a._index < b._index;
118 if ( a._control.lock() != b._control.lock() )
119 throw InvalidArgument(
"cannot compare iterators into different bytes");
120 return a._index <= b._index;
124 if ( a._control.lock() != b._control.lock() )
125 throw InvalidArgument(
"cannot compare iterators into different bytes");
126 return a._index > b._index;
130 if ( a._control.lock() != b._control.lock() )
131 throw InvalidArgument(
"cannot compare iterators into different bytes");
132 return a._index >= b._index;
136 if ( a._control.lock() != b._control.lock() )
137 throw InvalidArgument(
"cannot perform arithmetic with iterators into different bytes");
138 return a._index - b._index;
144 inline std::ostream& operator<<(std::ostream& out,
const Iterator& ) {
145 out <<
"<bytes iterator>";
157 class Bytes :
protected std::string {
159 using Base = std::string;
161 using Base::const_reference;
162 using Base::reference;
163 using Offset = uint64_t;
164 using size_type = integer::safe<uint64_t>;
178 Bytes(std::string s, bytes::Charset cs, bytes::DecodeErrorStrategy errors = bytes::DecodeErrorStrategy::REPLACE);
180 Bytes(Base&& str) : Base(std::move(str)), _control(std::make_shared<Base*>(static_cast<Base*>(
this))) {}
181 Bytes(
const Bytes& xs) : Base(xs), _control(std::make_shared<Base*>(static_cast<Base*>(
this))) {}
182 Bytes(
Bytes&& xs) noexcept : Base(std::move(xs)), _control(std::make_shared<Base*>(static_cast<Base*>(
this))) {}
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 return {substr(from - begin(), to - from)};
291 Bytes sub(Offset from, Offset to)
const {
return {substr(from, to - from)}; }
311 throw InvalidArgument(
"insufficient data in source");
313 memcpy(dst, data(), N);
314 return sub(N, std::string::npos);
325 std::string decode(bytes::Charset cs,
326 bytes::DecodeErrorStrategy errors = bytes::DecodeErrorStrategy::REPLACE)
const;
340 Bytes upper(bytes::Charset cs, bytes::DecodeErrorStrategy errors = bytes::DecodeErrorStrategy::REPLACE)
const {
341 return Bytes(hilti::rt::string::upper(decode(cs, errors), errors), cs, errors);
351 Bytes lower(bytes::Charset cs, bytes::DecodeErrorStrategy errors = bytes::DecodeErrorStrategy::REPLACE)
const {
352 return Bytes(hilti::rt::string::lower(decode(cs, errors), errors), cs, errors);
363 Bytes strip(
const Bytes&
set, bytes::Side side = bytes::Side::Both)
const;
372 Bytes strip(bytes::Side side = bytes::Side::Both)
const;
378 x.emplace_back(Bytes::Base(v));
386 std::tuple<Bytes, Bytes>
split1()
const {
388 return std::make_tuple(p.first, p.second);
395 x.push_back(Bytes::Base(v));
408 return std::make_tuple(p.first, p.second);
420 for (
size_t i = 0; i < parts.size(); ++i ) {
437 integer::safe<int64_t> toInt(uint64_t base = 10)
const;
446 integer::safe<uint64_t> toUInt(uint64_t base = 10)
const;
474 auto ns = ! isEmpty() ? toUInt(base) * integer::safe<uint64_t>(1
'000'000
'000) : integer::safe<uint64_t>(0); 475 return Time(ns, Time::NanosecondTag()); 485 Time toTime(hilti::rt::ByteOrder byte_order) const { 486 return Time(toUInt(byte_order) * integer::safe<uint64_t>(1'000
'000'000),
Time::NanosecondTag());
499 friend bool operator==(
const Bytes& a,
const Bytes& b) {
500 return static_cast<const Bytes::Base&
>(a) == static_cast<const Bytes::Base&>(b);
503 friend bool operator!=(
const Bytes& a,
const Bytes& b) {
return ! (a == b); }
506 friend bool operator<(
const Bytes& a,
const Bytes& b) {
507 return static_cast<const Bytes::Base&
>(a) < static_cast<const Bytes::Base&>(b);
510 friend bool operator<=(
const Bytes& a,
const Bytes& b) {
511 return static_cast<const Bytes::Base&
>(a) <= static_cast<const Bytes::Base&>(b);
514 friend bool operator>(
const Bytes& a,
const Bytes& b) {
515 return static_cast<const Bytes::Base&
>(a) > static_cast<const Bytes::Base&>(b);
518 friend bool operator>=(
const Bytes& a,
const Bytes& b) {
519 return static_cast<const Bytes::Base&
>(a) >= static_cast<const Bytes::Base&>(b);
523 return static_cast<const Bytes::Base&
>(a) + static_cast<const Bytes::Base&>(b);
528 std::shared_ptr<Base*> _control;
530 void invalidateIterators() { _control = std::make_shared<Base*>(
static_cast<Base*
>(
this)); }
533 inline std::ostream& operator<<(std::ostream& out,
const Bytes& x) {
534 out << escapeBytes(x.
str(),
false);
539 inline namespace literals {
540 inline Bytes operator"" _b(
const char* str,
size_t size) {
return Bytes(Bytes::Base(str, size)); }
545 inline std::string detail::to_string_for_print<Bytes>(
const Bytes& x) {
546 return escapeBytes(x.
str(),
false);
549 namespace detail::adl {
551 std::string
to_string(
const bytes::Side& x, adl::tag );
552 std::string
to_string(
const bytes::Charset& x, adl::tag );
553 std::string
to_string(
const bytes::DecodeErrorStrategy& x, adl::tag );
566 struct adl_serializer<
hilti::rt::Bytes> {};
Bytes upper(bytes::Charset cs, bytes::DecodeErrorStrategy errors=bytes::DecodeErrorStrategy::REPLACE) const
Definition: bytes.h:340
Bytes sub(const const_iterator &to) const
Definition: bytes.h:282
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:291
Bytes extract(unsigned char(&dst)[N]) const
Definition: bytes.h:309
Bytes sub(Offset to) const
Definition: bytes.h:299
std::tuple< Bytes, Bytes > split1(const Bytes &sep) const
Definition: bytes.h:406
Time toTime(uint64_t base=10) const
Definition: bytes.h:473
std::pair< std::string, std::string > split1(std::string s)
Definition: util.cc:146
bool startsWith(const std::string &s, const std::string &prefix)
Definition: util.cc:380
const_iterator begin() const
Definition: bytes.h:226
Definition: stream.h:1001
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:102
bool startsWith(const Bytes &b) const
Definition: bytes.h:329
Bytes & operator=(Bytes &&b) noexcept
Definition: bytes.h:207
void append(const Bytes &d)
Definition: bytes.h:214
ByteOrder
Definition: util.h:503
Bytes sub(const const_iterator &from, const const_iterator &to) const
Definition: bytes.h:272
const std::string & str() const &
Definition: bytes.h:223
Bytes lower(bytes::Charset cs, bytes::DecodeErrorStrategy errors=bytes::DecodeErrorStrategy::REPLACE) const
Definition: bytes.h:351
Definition: extension-points.h:12
std::tuple< Bytes, Bytes > split1() const
Definition: bytes.h:386
Vector< Bytes > split() const
Definition: bytes.h:375
const_iterator find(value_type b, const const_iterator &n=const_iterator()) const
Definition: bytes.h:246
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:392
Bytes join(const Vector< T > &parts) const
Definition: bytes.h:417