string_view 6.7 KB

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