2018-12-31 20:04:05 +01:00
|
|
|
//
|
2018-01-02 14:42:31 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
2018-12-31 20:04:05 +01:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "td/utils/Slice-decl.h"
|
|
|
|
|
|
|
|
#include "td/utils/logging.h"
|
|
|
|
|
|
|
|
#include <cstring>
|
2018-07-01 16:19:59 +02:00
|
|
|
#include <type_traits>
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
namespace td {
|
2018-06-30 14:55:58 +02:00
|
|
|
|
|
|
|
inline MutableSlice::MutableSlice() : s_(const_cast<char *>("")), len_(0) {
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice::MutableSlice(char *s, size_t len) : s_(s), len_(len) {
|
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice::MutableSlice(unsigned char *s, size_t len) : s_(reinterpret_cast<char *>(s)), len_(len) {
|
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
}
|
|
|
|
|
2018-10-25 17:10:14 +02:00
|
|
|
inline MutableSlice::MutableSlice(string &s) : s_(&s[0]), len_(s.size()) {
|
2018-06-30 14:55:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2018-09-14 20:41:03 +02:00
|
|
|
MutableSlice::MutableSlice(T s, std::enable_if_t<std::is_same<char *, T>::value, private_tag>) : s_(s) {
|
2018-06-30 14:55:58 +02:00
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
len_ = std::strlen(s_);
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice::MutableSlice(char *s, char *t) : MutableSlice(s, t - s) {
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice::MutableSlice(unsigned char *s, unsigned char *t) : MutableSlice(s, t - s) {
|
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t MutableSlice::size() const {
|
|
|
|
return len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice &MutableSlice::remove_prefix(size_t prefix_len) {
|
|
|
|
CHECK(prefix_len <= len_);
|
|
|
|
s_ += prefix_len;
|
|
|
|
len_ -= prefix_len;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
inline MutableSlice &MutableSlice::remove_suffix(size_t suffix_len) {
|
|
|
|
CHECK(suffix_len <= len_);
|
|
|
|
len_ -= suffix_len;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice &MutableSlice::truncate(size_t size) {
|
|
|
|
if (len_ > size) {
|
|
|
|
len_ = size;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice MutableSlice::copy() const {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool MutableSlice::empty() const {
|
|
|
|
return len_ == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char *MutableSlice::data() const {
|
|
|
|
return s_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char *MutableSlice::begin() const {
|
|
|
|
return s_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned char *MutableSlice::ubegin() const {
|
|
|
|
return reinterpret_cast<unsigned char *>(s_);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char *MutableSlice::end() const {
|
|
|
|
return s_ + len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned char *MutableSlice::uend() const {
|
|
|
|
return reinterpret_cast<unsigned char *>(s_) + len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline string MutableSlice::str() const {
|
|
|
|
return string(begin(), size());
|
|
|
|
}
|
|
|
|
|
|
|
|
inline MutableSlice MutableSlice::substr(size_t from) const {
|
|
|
|
CHECK(from <= len_);
|
|
|
|
return MutableSlice(s_ + from, len_ - from);
|
|
|
|
}
|
|
|
|
inline MutableSlice MutableSlice::substr(size_t from, size_t size) const {
|
|
|
|
CHECK(from <= len_);
|
2018-02-12 11:37:54 +01:00
|
|
|
return MutableSlice(s_ + from, min(size, len_ - from));
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t MutableSlice::find(char c) const {
|
|
|
|
for (size_t pos = 0; pos < len_; pos++) {
|
|
|
|
if (s_[pos] == c) {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return static_cast<size_t>(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t MutableSlice::rfind(char c) const {
|
|
|
|
for (size_t pos = len_; pos-- > 0;) {
|
|
|
|
if (s_[pos] == c) {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return static_cast<size_t>(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void MutableSlice::copy_from(Slice from) {
|
|
|
|
CHECK(size() >= from.size());
|
|
|
|
std::memcpy(ubegin(), from.ubegin(), from.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char &MutableSlice::back() {
|
|
|
|
CHECK(1 <= len_);
|
|
|
|
return s_[len_ - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char &MutableSlice::operator[](size_t i) {
|
|
|
|
return s_[i];
|
|
|
|
}
|
|
|
|
|
2018-06-30 14:55:58 +02:00
|
|
|
inline Slice::Slice() : s_(""), len_(0) {
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 14:55:58 +02:00
|
|
|
inline Slice::Slice(const MutableSlice &other) : s_(other.begin()), len_(other.size()) {
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice::Slice(const char *s, size_t len) : s_(s), len_(len) {
|
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice::Slice(const unsigned char *s, size_t len) : s_(reinterpret_cast<const char *>(s)), len_(len) {
|
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
}
|
|
|
|
|
2018-06-30 14:55:58 +02:00
|
|
|
inline Slice::Slice(const string &s) : s_(s.c_str()), len_(s.size()) {
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 14:55:58 +02:00
|
|
|
template <class T>
|
2018-09-14 20:41:03 +02:00
|
|
|
Slice::Slice(T s, std::enable_if_t<std::is_same<char *, std::remove_const_t<T>>::value, private_tag>) : s_(s) {
|
2018-06-30 14:55:58 +02:00
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
len_ = std::strlen(s_);
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 14:55:58 +02:00
|
|
|
template <class T>
|
2018-10-14 03:01:02 +02:00
|
|
|
Slice::Slice(T s, std::enable_if_t<std::is_same<const char *, std::remove_const_t<T>>::value, private_tag>) : s_(s) {
|
2018-06-30 14:55:58 +02:00
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
len_ = std::strlen(s_);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice::Slice(const char *s, const char *t) : s_(s), len_(t - s) {
|
|
|
|
CHECK(s_ != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice::Slice(const unsigned char *s, const unsigned char *t)
|
|
|
|
: s_(reinterpret_cast<const char *>(s)), len_(t - s) {
|
|
|
|
CHECK(s_ != nullptr);
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t Slice::size() const {
|
|
|
|
return len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice &Slice::remove_prefix(size_t prefix_len) {
|
|
|
|
CHECK(prefix_len <= len_);
|
|
|
|
s_ += prefix_len;
|
|
|
|
len_ -= prefix_len;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice &Slice::remove_suffix(size_t suffix_len) {
|
|
|
|
CHECK(suffix_len <= len_);
|
|
|
|
len_ -= suffix_len;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice &Slice::truncate(size_t size) {
|
|
|
|
if (len_ > size) {
|
|
|
|
len_ = size;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice Slice::copy() const {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool Slice::empty() const {
|
|
|
|
return len_ == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const char *Slice::data() const {
|
|
|
|
return s_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const char *Slice::begin() const {
|
|
|
|
return s_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const unsigned char *Slice::ubegin() const {
|
|
|
|
return reinterpret_cast<const unsigned char *>(s_);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const char *Slice::end() const {
|
|
|
|
return s_ + len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const unsigned char *Slice::uend() const {
|
|
|
|
return reinterpret_cast<const unsigned char *>(s_) + len_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline string Slice::str() const {
|
|
|
|
return string(begin(), size());
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Slice Slice::substr(size_t from) const {
|
|
|
|
CHECK(from <= len_);
|
|
|
|
return Slice(s_ + from, len_ - from);
|
|
|
|
}
|
|
|
|
inline Slice Slice::substr(size_t from, size_t size) const {
|
|
|
|
CHECK(from <= len_);
|
2018-02-12 11:37:54 +01:00
|
|
|
return Slice(s_ + from, min(size, len_ - from));
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t Slice::find(char c) const {
|
|
|
|
for (size_t pos = 0; pos < len_; pos++) {
|
|
|
|
if (s_[pos] == c) {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return static_cast<size_t>(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline size_t Slice::rfind(char c) const {
|
|
|
|
for (size_t pos = len_; pos-- > 0;) {
|
|
|
|
if (s_[pos] == c) {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return static_cast<size_t>(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char Slice::back() const {
|
|
|
|
CHECK(1 <= len_);
|
|
|
|
return s_[len_ - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline char Slice::operator[](size_t i) const {
|
|
|
|
return s_[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(const Slice &a, const Slice &b) {
|
|
|
|
return a.size() == b.size() && std::memcmp(a.data(), b.data(), a.size()) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator!=(const Slice &a, const Slice &b) {
|
|
|
|
return !(a == b);
|
|
|
|
}
|
|
|
|
|
2018-08-13 19:15:09 +02:00
|
|
|
inline bool operator<(const Slice &a, const Slice &b) {
|
2018-09-07 02:41:21 +02:00
|
|
|
auto x = std::memcmp(a.data(), b.data(), td::min(a.size(), b.size()));
|
2018-08-13 19:15:09 +02:00
|
|
|
if (x == 0) {
|
|
|
|
return a.size() < b.size();
|
|
|
|
}
|
|
|
|
return x < 0;
|
|
|
|
}
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
inline MutableCSlice::MutableCSlice(char *s, char *t) : MutableSlice(s, t) {
|
|
|
|
CHECK(*t == '\0');
|
|
|
|
}
|
|
|
|
|
|
|
|
inline CSlice::CSlice(const char *s, const char *t) : Slice(s, t) {
|
|
|
|
CHECK(*t == '\0');
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::size_t SliceHash::operator()(Slice slice) const {
|
|
|
|
// simple string hash
|
|
|
|
std::size_t result = 0;
|
|
|
|
constexpr std::size_t MUL = 123456789;
|
|
|
|
for (auto c : slice) {
|
|
|
|
result = result * MUL + c;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-12-19 15:48:39 +01:00
|
|
|
inline Slice as_slice(Slice slice) {
|
|
|
|
return slice;
|
|
|
|
}
|
|
|
|
inline MutableSlice as_slice(MutableSlice slice) {
|
|
|
|
return slice;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
Slice UInt<N>::as_slice() const {
|
|
|
|
return Slice(raw, N / 8);
|
|
|
|
}
|
|
|
|
template <size_t N>
|
|
|
|
MutableSlice UInt<N>::as_slice() {
|
|
|
|
return MutableSlice(raw, N / 8);
|
|
|
|
}
|
2018-03-26 16:05:41 +02:00
|
|
|
template <size_t N>
|
2018-12-19 15:48:39 +01:00
|
|
|
Slice as_slice(const UInt<N> &value) {
|
|
|
|
return value.as_slice();
|
2018-03-26 16:05:41 +02:00
|
|
|
}
|
|
|
|
template <size_t N>
|
2018-12-19 15:48:39 +01:00
|
|
|
MutableSlice as_slice(UInt<N> &value) {
|
|
|
|
return value.as_slice();
|
2018-03-26 16:05:41 +02:00
|
|
|
}
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
} // namespace td
|