shared.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #if __cplusplus >= 201703L
  3. // std::string_view is available
  4. #include <string_view>
  5. #endif
  6. #include <algorithm>
  7. #include <cstring>
  8. #include <memory>
  9. #include <string>
  10. #include <type_traits>
  11. namespace tsdb_shared {
  12. template <typename T, typename... Args>
  13. std::unique_ptr<T> make_unique(Args&&... args) {
  14. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  15. }
  16. #if __cplusplus >= 201703L
  17. using string_view = std::string_view;
  18. #else
  19. // Use a custom implementation
  20. class string_view {
  21. public:
  22. // Types
  23. using traits_type = std::char_traits<char>;
  24. using value_type = char;
  25. using pointer = char*;
  26. using const_pointer = const char*;
  27. using reference = char&;
  28. using const_reference = const char&;
  29. using iterator = const char*;
  30. using const_iterator = const char*;
  31. using size_type = size_t;
  32. using difference_type = ptrdiff_t;
  33. // Constants
  34. static constexpr size_type npos = size_type(-1);
  35. // Constructors
  36. string_view() noexcept : data_(nullptr), size_(0) {}
  37. string_view(const char* str) noexcept : data_(str), size_(strlen(str)) {}
  38. string_view(const char* str, size_t len) noexcept : data_(str), size_(len) {}
  39. string_view(const std::string& str) noexcept : data_(str.data()), size_(str.size()) {}
  40. // Conversion to std::string
  41. // NOTE: No explicit keyword here, might be too loose
  42. operator std::string() const { return std::string(data_, size_); }
  43. // Accessors
  44. const char* data() const noexcept { return data_; }
  45. size_t size() const noexcept { return size_; }
  46. bool empty() const noexcept { return size_ == 0; }
  47. // Iterators
  48. const char* begin() const noexcept { return data_; }
  49. const char* end() const noexcept { return data_ + size_; }
  50. const char* cbegin() const noexcept { return data_; }
  51. const char* cend() const noexcept { return data_ + size_; }
  52. // Element access
  53. const char& operator[](size_t pos) const noexcept { return data_[pos]; }
  54. const char& at(size_t pos) const {
  55. if (pos >= size_) {
  56. throw std::out_of_range("string_view::at");
  57. }
  58. return data_[pos];
  59. }
  60. const char& front() const noexcept { return data_[0]; }
  61. const char& back() const noexcept { return data_[size_ - 1]; }
  62. // Substring
  63. string_view substr(size_t pos = 0, size_t count = npos) const {
  64. if (pos > size_) {
  65. throw std::out_of_range("string_view::substr");
  66. }
  67. return string_view(data_ + pos, std::min(count, size_ - pos));
  68. }
  69. // Search
  70. size_t find(char c, size_t pos = 0) const noexcept {
  71. if (pos >= size_) {
  72. return npos;
  73. }
  74. const char* result = traits_type::find(data_ + pos, size_ - pos, c);
  75. return result ? result - data_ : npos;
  76. }
  77. size_t find(const char* s, size_t pos, size_t count) const noexcept {
  78. if (count == 0 || pos >= size_) {
  79. return npos;
  80. }
  81. const char* result = std::search(data_ + pos, data_ + size_, s, s + count);
  82. return result != data_ + size_ ? result - data_ : npos;
  83. }
  84. size_t find(const char* s, size_t pos = 0) const noexcept { return find(s, pos, strlen(s)); }
  85. size_t find(string_view sv, size_t pos = 0) const noexcept { return find(sv.data_, pos, sv.size_); }
  86. size_t find_first_of(char c, size_t pos = 0) const noexcept { return find(c, pos); }
  87. size_t find_first_of(const char* s, size_t pos, size_t count) const noexcept {
  88. if (pos >= size_) {
  89. return npos;
  90. }
  91. for (size_t i = pos; i < size_; ++i) {
  92. if (traits_type::find(s, count, data_[i]) != nullptr) {
  93. return i;
  94. }
  95. }
  96. return npos;
  97. }
  98. size_t find_first_of(const char* s, size_t pos = 0) const noexcept { return find_first_of(s, pos, strlen(s)); }
  99. size_t find_first_of(string_view sv, size_t pos = 0) const noexcept { return find_first_of(sv.data_, pos, sv.size_); }
  100. size_t find_last_of(char c, size_t pos = npos) const noexcept {
  101. if (size_ == 0) {
  102. return npos;
  103. }
  104. if (pos >= size_) {
  105. pos = size_ - 1;
  106. }
  107. for (size_t i = pos; i != npos; --i) {
  108. if (data_[i] == c) {
  109. return i;
  110. }
  111. }
  112. return npos;
  113. }
  114. size_t find_last_of(const char* s, size_t pos, size_t count) const noexcept {
  115. if (count == 0 || size_ == 0) {
  116. return npos;
  117. }
  118. if (pos >= size_) {
  119. pos = size_ - 1;
  120. }
  121. for (size_t i = pos; i != npos; --i) {
  122. if (traits_type::find(s, count, data_[i]) != nullptr) {
  123. return i;
  124. }
  125. }
  126. return npos;
  127. }
  128. size_t find_last_of(const char* s, size_t pos = npos) const noexcept { return find_last_of(s, pos, strlen(s)); }
  129. size_t find_last_of(string_view sv, size_t pos = npos) const noexcept { return find_last_of(sv.data_, pos, sv.size_); }
  130. // Comparison operators
  131. bool operator==(const string_view& other) const noexcept {
  132. return size_ == other.size_ && std::equal(data_, data_ + size_, other.data_);
  133. }
  134. bool operator!=(const string_view& other) const noexcept { return !(*this == other); }
  135. bool operator<(const string_view& other) const noexcept {
  136. return std::lexicographical_compare(data_, data_ + size_, other.data_, other.data_ + other.size_);
  137. }
  138. bool operator<=(const string_view& other) const noexcept { return !(other < *this); }
  139. bool operator>(const string_view& other) const noexcept { return other < *this; }
  140. bool operator>=(const string_view& other) const noexcept { return !(*this < other); }
  141. // Helper functions
  142. friend std::string to_string(const string_view& sv) { return std::string(sv.data_, sv.size_); }
  143. private:
  144. const char* data_;
  145. size_t size_;
  146. };
  147. #endif
  148. } // namespace tsdb_shared
  149. // Preludes
  150. namespace tsdb_preludes {
  151. using tsdb_shared::make_unique;
  152. using tsdb_shared::string_view;
  153. } // namespace tsdb_preludes