123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #pragma once
- #if __cplusplus >= 201703L
- // std::string_view is available
- #include <string_view>
- #endif
- #include <algorithm>
- #include <cstring>
- #include <memory>
- #include <string>
- #include <type_traits>
- namespace tsdb_shared {
- template <typename T, typename... Args>
- std::unique_ptr<T> make_unique(Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
- }
- #if __cplusplus >= 201703L
- using string_view = std::string_view;
- #else
- // Use a custom implementation
- class string_view {
- public:
- // Types
- using traits_type = std::char_traits<char>;
- using value_type = char;
- using pointer = char*;
- using const_pointer = const char*;
- using reference = char&;
- using const_reference = const char&;
- using iterator = const char*;
- using const_iterator = const char*;
- using size_type = size_t;
- using difference_type = ptrdiff_t;
- // Constants
- static constexpr size_type npos = size_type(-1);
- // Constructors
- string_view() noexcept : data_(nullptr), size_(0) {}
- string_view(const char* str) noexcept : data_(str), size_(strlen(str)) {}
- string_view(const char* str, size_t len) noexcept : data_(str), size_(len) {}
- string_view(const std::string& str) noexcept : data_(str.data()), size_(str.size()) {}
- // Conversion to std::string
- // NOTE: No explicit keyword here, might be too loose
- operator std::string() const { return std::string(data_, size_); }
- // Accessors
- const char* data() const noexcept { return data_; }
- size_t size() const noexcept { return size_; }
- bool empty() const noexcept { return size_ == 0; }
- // Iterators
- const char* begin() const noexcept { return data_; }
- const char* end() const noexcept { return data_ + size_; }
- const char* cbegin() const noexcept { return data_; }
- const char* cend() const noexcept { return data_ + size_; }
- // Element access
- const char& operator[](size_t pos) const noexcept { return data_[pos]; }
- const char& at(size_t pos) const {
- if (pos >= size_) {
- throw std::out_of_range("string_view::at");
- }
- return data_[pos];
- }
- const char& front() const noexcept { return data_[0]; }
- const char& back() const noexcept { return data_[size_ - 1]; }
- // Substring
- string_view substr(size_t pos = 0, size_t count = npos) const {
- if (pos > size_) {
- throw std::out_of_range("string_view::substr");
- }
- return string_view(data_ + pos, std::min(count, size_ - pos));
- }
- // Search
- size_t find(char c, size_t pos = 0) const noexcept {
- if (pos >= size_) {
- return npos;
- }
- const char* result = traits_type::find(data_ + pos, size_ - pos, c);
- return result ? result - data_ : npos;
- }
- size_t find(const char* s, size_t pos, size_t count) const noexcept {
- if (count == 0 || pos >= size_) {
- return npos;
- }
- const char* result = std::search(data_ + pos, data_ + size_, s, s + count);
- return result != data_ + size_ ? result - data_ : npos;
- }
- size_t find(const char* s, size_t pos = 0) const noexcept { return find(s, pos, strlen(s)); }
- size_t find(string_view sv, size_t pos = 0) const noexcept { return find(sv.data_, pos, sv.size_); }
- size_t find_first_of(char c, size_t pos = 0) const noexcept { return find(c, pos); }
- size_t find_first_of(const char* s, size_t pos, size_t count) const noexcept {
- if (pos >= size_) {
- return npos;
- }
- for (size_t i = pos; i < size_; ++i) {
- if (traits_type::find(s, count, data_[i]) != nullptr) {
- return i;
- }
- }
- return npos;
- }
- size_t find_first_of(const char* s, size_t pos = 0) const noexcept { return find_first_of(s, pos, strlen(s)); }
- size_t find_first_of(string_view sv, size_t pos = 0) const noexcept { return find_first_of(sv.data_, pos, sv.size_); }
- size_t find_last_of(char c, size_t pos = npos) const noexcept {
- if (size_ == 0) {
- return npos;
- }
- if (pos >= size_) {
- pos = size_ - 1;
- }
- for (size_t i = pos; i != npos; --i) {
- if (data_[i] == c) {
- return i;
- }
- }
- return npos;
- }
- size_t find_last_of(const char* s, size_t pos, size_t count) const noexcept {
- if (count == 0 || size_ == 0) {
- return npos;
- }
- if (pos >= size_) {
- pos = size_ - 1;
- }
- for (size_t i = pos; i != npos; --i) {
- if (traits_type::find(s, count, data_[i]) != nullptr) {
- return i;
- }
- }
- return npos;
- }
- size_t find_last_of(const char* s, size_t pos = npos) const noexcept { return find_last_of(s, pos, strlen(s)); }
- size_t find_last_of(string_view sv, size_t pos = npos) const noexcept { return find_last_of(sv.data_, pos, sv.size_); }
- // Comparison operators
- bool operator==(const string_view& other) const noexcept {
- return size_ == other.size_ && std::equal(data_, data_ + size_, other.data_);
- }
- bool operator!=(const string_view& other) const noexcept { return !(*this == other); }
- bool operator<(const string_view& other) const noexcept {
- return std::lexicographical_compare(data_, data_ + size_, other.data_, other.data_ + other.size_);
- }
- bool operator<=(const string_view& other) const noexcept { return !(other < *this); }
- bool operator>(const string_view& other) const noexcept { return other < *this; }
- bool operator>=(const string_view& other) const noexcept { return !(*this < other); }
- // Helper functions
- friend std::string to_string(const string_view& sv) { return std::string(sv.data_, sv.size_); }
- private:
- const char* data_;
- size_t size_;
- };
- #endif
- } // namespace tsdb_shared
- // Preludes
- namespace tsdb_preludes {
- using tsdb_shared::make_unique;
- using tsdb_shared::string_view;
- } // namespace tsdb_preludes
|