260 lines
8.9 KiB
C++
260 lines
8.9 KiB
C++
#ifndef _TILE_BASE_SLICE_H
|
|
#define _TILE_BASE_SLICE_H
|
|
|
|
#pragma once
|
|
|
|
#include "tile/base/internal/format.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
namespace tile {
|
|
namespace detail {
|
|
static constexpr char kChars[] = {
|
|
char(-128), char(-127), char(-126), char(-125), char(-124), char(-123), char(-122), char(-121), char(-120),
|
|
char(-119), char(-118), char(-117), char(-116), char(-115), char(-114), char(-113), char(-112), char(-111),
|
|
char(-110), char(-109), char(-108), char(-107), char(-106), char(-105), char(-104), char(-103), char(-102),
|
|
char(-101), char(-100), char(-99), char(-98), char(-97), char(-96), char(-95), char(-94), char(-93),
|
|
char(-92), char(-91), char(-90), char(-89), char(-88), char(-87), char(-86), char(-85), char(-84),
|
|
char(-83), char(-82), char(-81), char(-80), char(-79), char(-78), char(-77), char(-76), char(-75),
|
|
char(-74), char(-73), char(-72), char(-71), char(-70), char(-69), char(-68), char(-67), char(-66),
|
|
char(-65), char(-64), char(-63), char(-62), char(-61), char(-60), char(-59), char(-58), char(-57),
|
|
char(-56), char(-55), char(-54), char(-53), char(-52), char(-51), char(-50), char(-49), char(-48),
|
|
char(-47), char(-46), char(-45), char(-44), char(-43), char(-42), char(-41), char(-40), char(-39),
|
|
char(-38), char(-37), char(-36), char(-35), char(-34), char(-33), char(-32), char(-31), char(-30),
|
|
char(-29), char(-28), char(-27), char(-26), char(-25), char(-24), char(-23), char(-22), char(-21),
|
|
char(-20), char(-19), char(-18), char(-17), char(-16), char(-15), char(-14), char(-13), char(-12),
|
|
char(-11), char(-10), char(-9), char(-8), char(-7), char(-6), char(-5), char(-4), char(-3),
|
|
char(-2), char(-1), char(0), char(1), char(2), char(3), char(4), char(5), char(6),
|
|
char(7), char(8), char(9), char(10), char(11), char(12), char(13), char(14), char(15),
|
|
char(16), char(17), char(18), char(19), char(20), char(21), char(22), char(23), char(24),
|
|
char(25), char(26), char(27), char(28), char(29), char(30), char(31), char(32), char(33),
|
|
char(34), char(35), char(36), char(37), char(38), char(39), char(40), char(41), char(42),
|
|
char(43), char(44), char(45), char(46), char(47), char(48), char(49), char(50), char(51),
|
|
char(52), char(53), char(54), char(55), char(56), char(57), char(58), char(59), char(60),
|
|
char(61), char(62), char(63), char(64), char(65), char(66), char(67), char(68), char(69),
|
|
char(70), char(71), char(72), char(73), char(74), char(75), char(76), char(77), char(78),
|
|
char(79), char(80), char(81), char(82), char(83), char(84), char(85), char(86), char(87),
|
|
char(88), char(89), char(90), char(91), char(92), char(93), char(94), char(95), char(96),
|
|
char(97), char(98), char(99), char(100), char(101), char(102), char(103), char(104), char(105),
|
|
char(106), char(107), char(108), char(109), char(110), char(111), char(112), char(113), char(114),
|
|
char(115), char(116), char(117), char(118), char(119), char(120), char(121), char(122), char(123),
|
|
char(124), char(125), char(126), char(127)};
|
|
|
|
// char [-128, 127]
|
|
static std::array<char, 256> &
|
|
GetChars()
|
|
{
|
|
static std::array<char, 256> chars;
|
|
static std::once_flag flag;
|
|
std::call_once(flag, [] {
|
|
for (int i = 0; i < 256; i++) { chars[i] = static_cast<char>(i - 128); }
|
|
});
|
|
return chars;
|
|
}
|
|
}// namespace detail
|
|
|
|
class Slice {
|
|
public:
|
|
using string_t = ::std::string;
|
|
static constexpr std::size_t npos = std::string::npos;
|
|
|
|
constexpr Slice() : data_(""), len_(0) {}
|
|
|
|
// char
|
|
constexpr Slice(const char &ch) : data_(&detail::kChars[128 + ch]), len_(1) {}
|
|
|
|
// std::string
|
|
Slice(const std::string &str) : data_(str.data()), len_(str.size()) {}
|
|
|
|
// const char*
|
|
Slice(const char *c_str) : data_(c_str), len_(strlen(c_str)) {}
|
|
|
|
Slice(const void *data, size_t len) : data_(reinterpret_cast<const char *>(data)), len_(len) {}
|
|
|
|
constexpr Slice(const char *begin, const char *end) : data_(begin), len_(end - begin) {}
|
|
|
|
constexpr Slice(const char *data, size_t len) : data_(data), len_(len) {}
|
|
|
|
constexpr Slice(const Slice &other) : data_(other.data_), len_(other.len_) {}
|
|
|
|
char front() const
|
|
{
|
|
assert(len_ > 0);
|
|
return *data_;
|
|
}
|
|
|
|
char back() const
|
|
{
|
|
assert(len_ > 0);
|
|
return data_[len_ - 1];
|
|
}
|
|
|
|
Slice &operator=(const Slice &other)
|
|
{
|
|
data_ = other.data_;
|
|
len_ = other.len_;
|
|
return *this;
|
|
}
|
|
|
|
void RemovePrefix(size_t n)
|
|
{
|
|
assert(len_ >= n && n >= 0);
|
|
data_ += n;
|
|
len_ -= n;
|
|
}
|
|
|
|
void RemoveSuffix(size_t n)
|
|
{
|
|
assert(len_ >= n && n >= 0);
|
|
len_ -= n;
|
|
}
|
|
|
|
Slice substr(size_t pos, size_t n) const
|
|
{
|
|
if (n == npos) { return substr(pos, len_ - pos); }
|
|
|
|
assert(pos <= len_ && n <= len_ - pos);
|
|
return Slice(data_ + pos, n);
|
|
}
|
|
|
|
Slice substr(size_t pos) const
|
|
{
|
|
assert(pos <= len_);
|
|
return Slice(data_ + pos, len_ - pos);
|
|
}
|
|
|
|
std::string ToString() const { return std::string(data_, len_); }
|
|
|
|
void clear()
|
|
{
|
|
data_ = "";
|
|
len_ = 0;
|
|
}
|
|
|
|
std::size_t find(Slice s, std::size_t pos = 0) const;
|
|
|
|
std::size_t find_first_of(Slice s) const { return find(s); }
|
|
|
|
// TODO: Optimize it
|
|
std::size_t find_last_of(Slice s) const
|
|
{
|
|
if (s.empty() || s.size() > size()) { return npos; }
|
|
|
|
auto ptr = data_ + len_ - s.size();
|
|
for (; ptr >= data_; --ptr) {
|
|
if (std::find(s.begin(), s.end(), *ptr) != s.end()) { return ptr - data_; }
|
|
}
|
|
|
|
return npos;
|
|
}
|
|
|
|
const char *cbegin() const { return data_; }
|
|
|
|
const char *cend() const { return data_ + len_; }
|
|
|
|
const char *begin() const { return data_; }
|
|
|
|
const char *end() const { return data_ + len_; }
|
|
|
|
const char *data() const { return data_; }
|
|
|
|
size_t size() const { return len_; }
|
|
|
|
bool empty() const { return len_ == 0; }
|
|
|
|
const char &operator[](size_t pos) const
|
|
{
|
|
assert(pos < len_ && pos >= 0);
|
|
return data_[pos];
|
|
}
|
|
|
|
inline operator string_t() const { return ToString(); }
|
|
|
|
private:
|
|
const char *data_{nullptr};
|
|
size_t len_{0};
|
|
};
|
|
|
|
inline bool
|
|
operator==(const Slice &lhs, const Slice &rhs)
|
|
{
|
|
return lhs.size() == rhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
|
|
}
|
|
|
|
inline bool
|
|
operator!=(const Slice &lhs, const Slice &rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
inline bool
|
|
operator<(const Slice &lhs, const Slice &rhs)
|
|
{
|
|
const size_t min_len = std::min(lhs.size(), rhs.size());
|
|
const int r = memcmp(lhs.data(), rhs.data(), min_len);
|
|
return r < 0 || (r == 0 && lhs.size() < rhs.size());
|
|
}
|
|
|
|
inline bool
|
|
operator==(const char *lhs, const Slice &rhs)
|
|
{
|
|
return Slice(lhs) == rhs;
|
|
}
|
|
|
|
inline bool
|
|
operator!=(const char *lhs, const Slice &rhs)
|
|
{
|
|
return Slice(lhs) != rhs;
|
|
}
|
|
|
|
inline std::ostream &
|
|
operator<<(std::ostream &os, const Slice &s)
|
|
{
|
|
return os << s.ToString();
|
|
}
|
|
|
|
inline std::string
|
|
operator+(const Slice &lhs, const Slice &rhs)
|
|
{
|
|
return lhs.ToString() + rhs.ToString();
|
|
}
|
|
|
|
static_assert(std::is_constructible<Slice, char>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, char &>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const char>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const char &>::value, "Can't Build Sliece");
|
|
|
|
static_assert(std::is_constructible<Slice, char[]>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const char[]>::value, "Can't Build Sliece");
|
|
|
|
static_assert(std::is_constructible<Slice, char[2]>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const char[2]>::value, "Can't Build Sliece");
|
|
|
|
static_assert(std::is_constructible<Slice, char *>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const char *>::value, "Can't Build Sliece");
|
|
|
|
static_assert(std::is_constructible<Slice, void *, int>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const void *, int>::value, "Can't Build Sliece");
|
|
|
|
static_assert(std::is_constructible<Slice, std::string>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, std::string &>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const std::string>::value, "Can't Build Sliece");
|
|
static_assert(std::is_constructible<Slice, const std::string &>::value, "Can't Build Sliece");
|
|
|
|
}// namespace tile
|
|
|
|
namespace std {
|
|
template<>
|
|
struct hash<::tile::Slice> {
|
|
std::size_t operator()(const ::tile::Slice &s) const noexcept { return 0; }
|
|
};
|
|
}// namespace std
|
|
|
|
#endif// _TILE_BASE_SLICE_H
|