string_view 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // -*-c++-*-
  2. // vim: set ft=cpp:
  3. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  4. file LICENSE.rst or https://cmake.org/licensing for details. */
  5. #pragma once
  6. #if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
  7. # define CMake_HAVE_CXX_STRING_VIEW
  8. #endif
  9. #include <cm/bits/container_helpers.hxx> // IWYU pragma: export
  10. #ifdef CMake_HAVE_CXX_STRING_VIEW
  11. # include <string_view> // IWYU pragma: export
  12. namespace cm {
  13. using std::string_view;
  14. }
  15. #else
  16. # include <cstddef>
  17. # include <functional>
  18. # include <iosfwd>
  19. # include <iterator>
  20. # include <string>
  21. namespace cm {
  22. class string_view
  23. {
  24. public:
  25. using traits_type = std::string::traits_type;
  26. using value_type = char;
  27. using pointer = char*;
  28. using const_pointer = char const*;
  29. using reference = char&;
  30. using const_reference = char const&;
  31. using const_iterator = char const*;
  32. using iterator = const_iterator;
  33. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  34. using reverse_iterator = const_reverse_iterator;
  35. using size_type = std::string::size_type;
  36. using difference_type = std::string::difference_type;
  37. static size_type const npos = static_cast<size_type>(-1);
  38. string_view() noexcept = default;
  39. string_view(string_view const&) noexcept = default;
  40. string_view(char const* s, size_t count) noexcept
  41. : data_(s)
  42. , size_(count)
  43. {
  44. }
  45. string_view(char const* s) noexcept
  46. : data_(s)
  47. , size_(traits_type::length(s))
  48. {
  49. }
  50. // C++17 does not define this constructor. Instead it defines
  51. // a conversion operator on std::string to create a string_view.
  52. // Since this implementation is used in C++11, std::string does
  53. // not have that conversion.
  54. string_view(std::string const& s) noexcept
  55. : data_(s.data())
  56. , size_(s.size())
  57. {
  58. }
  59. // C++17 does not define this conversion. Instead it defines
  60. // a constructor on std::string that can take a string_view.
  61. // Since this implementation is used in C++11, std::string does
  62. // not have that constructor.
  63. explicit operator std::string() const { return std::string(data_, size_); }
  64. string_view& operator=(string_view const&) = default;
  65. const_iterator begin() const noexcept { return data_; }
  66. const_iterator end() const noexcept { return data_ + size_; }
  67. const_iterator cbegin() const noexcept { return begin(); }
  68. const_iterator cend() const noexcept { return end(); }
  69. const_reverse_iterator rbegin() const noexcept
  70. {
  71. return const_reverse_iterator(end());
  72. }
  73. const_reverse_iterator rend() const noexcept
  74. {
  75. return const_reverse_iterator(begin());
  76. }
  77. const_reverse_iterator crbegin() const noexcept { return rbegin(); }
  78. const_reverse_iterator crend() const noexcept { return rend(); }
  79. const_reference operator[](size_type pos) const noexcept
  80. {
  81. return data_[pos];
  82. }
  83. const_reference at(size_type pos) const;
  84. const_reference front() const noexcept { return data_[0]; }
  85. const_reference back() const noexcept { return data_[size_ - 1]; }
  86. const_pointer data() const noexcept { return data_; }
  87. size_type size() const noexcept { return size_; }
  88. size_type length() const noexcept { return size_; }
  89. size_type max_size() const noexcept { return npos - 1; }
  90. bool empty() const noexcept { return size_ == 0; }
  91. void remove_prefix(size_type n) noexcept
  92. {
  93. data_ += n;
  94. size_ -= n;
  95. }
  96. void remove_suffix(size_type n) noexcept { size_ -= n; }
  97. void swap(string_view& v) noexcept
  98. {
  99. string_view tmp = v;
  100. v = *this;
  101. *this = tmp;
  102. }
  103. size_type copy(char* dest, size_type count, size_type pos = 0) const;
  104. string_view substr(size_type pos = 0, size_type count = npos) const;
  105. int compare(string_view v) const noexcept;
  106. int compare(size_type pos1, size_type count1, string_view v) const;
  107. int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
  108. size_type count2) const;
  109. int compare(char const* s) const;
  110. int compare(size_type pos1, size_type count1, char const* s) const;
  111. int compare(size_type pos1, size_type count1, char const* s,
  112. size_type count2) const;
  113. size_type find(string_view v, size_type pos = 0) const noexcept;
  114. size_type find(char c, size_type pos = 0) const noexcept;
  115. size_type find(char const* s, size_type pos, size_type count) const;
  116. size_type find(char const* s, size_type pos = 0) const;
  117. size_type rfind(string_view v, size_type pos = npos) const noexcept;
  118. size_type rfind(char c, size_type pos = npos) const noexcept;
  119. size_type rfind(char const* s, size_type pos, size_type count) const;
  120. size_type rfind(char const* s, size_type pos = npos) const;
  121. size_type find_first_of(string_view v, size_type pos = 0) const noexcept;
  122. size_type find_first_of(char c, size_type pos = 0) const noexcept;
  123. size_type find_first_of(char const* s, size_type pos, size_type count) const;
  124. size_type find_first_of(char const* s, size_type pos = 0) const;
  125. size_type find_last_of(string_view v, size_type pos = npos) const noexcept;
  126. size_type find_last_of(char c, size_type pos = npos) const noexcept;
  127. size_type find_last_of(char const* s, size_type pos, size_type count) const;
  128. size_type find_last_of(char const* s, size_type pos = npos) const;
  129. size_type find_first_not_of(string_view v, size_type pos = 0) const noexcept;
  130. size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
  131. size_type find_first_not_of(char const* s, size_type pos,
  132. size_type count) const;
  133. size_type find_first_not_of(char const* s, size_type pos = 0) const;
  134. size_type find_last_not_of(string_view v,
  135. size_type pos = npos) const noexcept;
  136. size_type find_last_not_of(char c, size_type pos = npos) const noexcept;
  137. size_type find_last_not_of(char const* s, size_type pos,
  138. size_type count) const;
  139. size_type find_last_not_of(char const* s, size_type pos = npos) const;
  140. private:
  141. char const* data_ = nullptr;
  142. size_type size_ = 0;
  143. };
  144. std::ostream& operator<<(std::ostream& o, string_view v);
  145. std::string& operator+=(std::string& s, string_view v);
  146. inline bool operator==(string_view l, string_view r) noexcept
  147. {
  148. return l.compare(r) == 0;
  149. }
  150. inline bool operator!=(string_view l, string_view r) noexcept
  151. {
  152. return l.compare(r) != 0;
  153. }
  154. inline bool operator<(string_view l, string_view r) noexcept
  155. {
  156. return l.compare(r) < 0;
  157. }
  158. inline bool operator<=(string_view l, string_view r) noexcept
  159. {
  160. return l.compare(r) <= 0;
  161. }
  162. inline bool operator>(string_view l, string_view r) noexcept
  163. {
  164. return l.compare(r) > 0;
  165. }
  166. inline bool operator>=(string_view l, string_view r) noexcept
  167. {
  168. return l.compare(r) >= 0;
  169. }
  170. }
  171. namespace std {
  172. template <>
  173. struct hash<cm::string_view>
  174. {
  175. using argument_type = cm::string_view;
  176. using result_type = size_t;
  177. result_type operator()(argument_type const& s) const noexcept;
  178. };
  179. }
  180. #endif