tile/tile/base/slice.h
2025-01-09 11:14:38 +08:00

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