cstring_ref.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_PROCESS_V2_CSTRING_REF_HPP
  6. #define BOOST_PROCESS_V2_CSTRING_REF_HPP
  7. #include <boost/process/v2/detail/config.hpp>
  8. #if defined(BOOST_PROCESS_V2_STANDALONE)
  9. #include <string_view>
  10. #else
  11. #include <boost/utility/string_view.hpp>
  12. #endif
  13. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  14. namespace detail
  15. {
  16. BOOST_CONSTEXPR static const char* null_char_(char) {return "";}
  17. BOOST_CONSTEXPR static const wchar_t* null_char_(wchar_t) {return L"";}
  18. BOOST_CONSTEXPR static const char16_t* null_char_(char16_t) {return u"";}
  19. BOOST_CONSTEXPR static const char32_t* null_char_(char32_t) {return U"";}
  20. #if defined(BOOST_PROCESS_V2_HAS_CHAR8_T)
  21. BOOST_CONSTEXPR static const char8_t* null_char_(char8_t) {return u8"";}
  22. #endif
  23. }
  24. #if defined(BOOST_PROCESS_V2_STANDALONE)
  25. using std::basic_string_view;
  26. using std:: string_view;
  27. using std:: wstring_view;
  28. #else
  29. using boost::basic_string_view;
  30. using boost:: string_view;
  31. using boost:: wstring_view;
  32. #endif
  33. /// Small wrapper for a null-terminated string that can be directly passed to C APIS
  34. /** This ref can only be modified by moving the front pointer. It does not store the
  35. * size, but can detect values that can directly be passed to system APIs.
  36. *
  37. * It can be constructed from a `char*` pointer or any class that has a `c_str()`
  38. * member function, e.g. std::string or boost::static_string.
  39. *
  40. */
  41. template<typename CharT, typename Traits = std::char_traits<CharT>>
  42. struct basic_cstring_ref
  43. {
  44. using value_type = CharT;
  45. using traits_type = Traits;
  46. BOOST_CONSTEXPR basic_cstring_ref() noexcept : view_(detail::null_char_(value_type{})) {}
  47. BOOST_CONSTEXPR basic_cstring_ref(std::nullptr_t) = delete;
  48. BOOST_CONSTEXPR basic_cstring_ref( const value_type* s ) : view_(s) {}
  49. template<typename Source,
  50. typename =
  51. typename std::enable_if<
  52. std::is_same<const value_type,
  53. typename std::remove_pointer<decltype(std::declval<Source>().c_str())>::type
  54. >::value>::type>
  55. BOOST_CONSTEXPR basic_cstring_ref(Source && src) : view_(src.c_str()) {}
  56. BOOST_CONSTEXPR typename basic_string_view<value_type, Traits>::const_pointer c_str() const BOOST_NOEXCEPT
  57. {
  58. return this->data();
  59. }
  60. using string_view_type = basic_string_view<value_type, Traits>;
  61. constexpr operator string_view_type() const {return view_;}
  62. using pointer = CharT *;
  63. using const_pointer = const CharT *;
  64. using reference = CharT &;
  65. using const_reference = const CharT &;
  66. using const_iterator = const_pointer;
  67. using iterator = const_iterator;
  68. using const_reverse_iterator = typename std::reverse_iterator<const_iterator>;
  69. using reverse_iterator = typename std::reverse_iterator<iterator>;
  70. using size_type = std::size_t;
  71. using difference_type = std::ptrdiff_t;
  72. static BOOST_CONSTEXPR size_type npos = -1;
  73. BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT {return view_;};
  74. BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT {return view_ + length();};
  75. BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT {return view_;};
  76. BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT {return view_ + length();};
  77. BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT {return reverse_iterator(view_ + length());};
  78. BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT {return reverse_iterator(view_);};
  79. BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT {return reverse_iterator(view_ + length());};
  80. BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT {return reverse_iterator(view_);};
  81. BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT {return length(); }
  82. BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT {return traits_type::length(view_); }
  83. BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {return (std::numeric_limits<std::size_t>::max)() / sizeof(CharT); }
  84. BOOST_ATTRIBUTE_NODISCARD BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT {return *view_ == *detail::null_char_(CharT{}); }
  85. BOOST_CONSTEXPR const_reference operator[](size_type pos) const {return view_[pos] ;}
  86. BOOST_CXX14_CONSTEXPR const_reference at(size_type pos) const
  87. {
  88. if (pos >= size())
  89. throw_exception(std::out_of_range("cstring-view out of range"));
  90. return view_[pos];
  91. }
  92. BOOST_CONSTEXPR const_reference front() const {return *view_;}
  93. BOOST_CONSTEXPR const_reference back() const {return view_[length() - 1];}
  94. BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT {return view_;}
  95. BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {view_ = view_ + n;}
  96. void swap(basic_cstring_ref& s) BOOST_NOEXCEPT {std::swap(view_, s.view_);}
  97. size_type copy(value_type* s, size_type n, size_type pos = 0) const
  98. {
  99. return traits_type::copy(s, view_ + pos, n) - view_;
  100. }
  101. BOOST_CONSTEXPR basic_cstring_ref substr(size_type pos = 0) const
  102. {
  103. return basic_cstring_ref(view_ + pos);
  104. }
  105. BOOST_CONSTEXPR string_view_type substr(size_type pos, size_type length) const
  106. {
  107. return string_view_type(view_).substr(pos, length);
  108. }
  109. BOOST_CXX14_CONSTEXPR int compare(basic_cstring_ref x) const BOOST_NOEXCEPT
  110. {
  111. auto idx = 0u;
  112. for (; view_[idx] != null_char_()[0] && x[idx] != null_char_()[0]; idx++)
  113. if (!traits_type::eq(view_[idx], x[idx]))
  114. return traits_type::lt(view_[idx], x[idx]) ? -1 : 1;
  115. return traits_type::to_int_type(view_[idx]) -
  116. traits_type::to_int_type(x[idx]); // will compare to null char of either.
  117. }
  118. BOOST_CXX14_CONSTEXPR bool starts_with(string_view_type x) const BOOST_NOEXCEPT
  119. {
  120. if (x.empty())
  121. return true;
  122. auto idx = 0u;
  123. for (; view_[idx] != null_char_()[0] && idx < x.size(); idx++)
  124. if (!traits_type::eq(view_[idx], x[idx]))
  125. return false;
  126. return idx == x.size() || view_[idx] != null_char_()[0];
  127. }
  128. BOOST_CONSTEXPR bool starts_with(value_type x) const BOOST_NOEXCEPT
  129. {
  130. return traits_type::eq(view_[0], x);
  131. }
  132. BOOST_CXX14_CONSTEXPR size_type find( CharT ch, size_type pos = 0 ) const BOOST_NOEXCEPT
  133. {
  134. for (auto p = view_ + pos; *p != *null_char_(); p++)
  135. if (traits_type::eq(*p, ch))
  136. return p - view_;
  137. return npos;
  138. }
  139. friend BOOST_CXX14_CONSTEXPR bool operator==(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT
  140. {
  141. std::size_t idx = 0u;
  142. for (idx = 0u; x[idx] != null_char_()[0] && y[idx] != null_char_()[0]; idx++)
  143. if (!traits_type::eq(x[idx], y[idx]))
  144. return false;
  145. return x[idx] == y[idx];
  146. }
  147. friend BOOST_CXX14_CONSTEXPR bool operator!=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT
  148. {
  149. std::size_t idx = 0u;
  150. for (idx = 0u; x[idx] != null_char_()[0] &&
  151. y[idx] != null_char_()[0]; idx++)
  152. if (!traits_type::eq(x[idx], y[idx]))
  153. return true;
  154. return x[idx] != y[idx];
  155. }
  156. friend BOOST_CXX14_CONSTEXPR bool operator< (basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) < 0;}
  157. friend BOOST_CXX14_CONSTEXPR bool operator> (basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) > 0;}
  158. friend BOOST_CXX14_CONSTEXPR bool operator<=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) <= 0;}
  159. friend BOOST_CXX14_CONSTEXPR bool operator>=(basic_cstring_ref x, basic_cstring_ref y) BOOST_NOEXCEPT {return x.compare(y) >= 0;}
  160. // modifiers
  161. void clear() BOOST_NOEXCEPT { view_ = null_char_(); } // Boost extension
  162. std::basic_string<value_type, traits_type> to_string() const {
  163. return std::basic_string<CharT, Traits>(begin(), end());
  164. }
  165. template<typename Allocator>
  166. std::basic_string<value_type, traits_type, Allocator> to_string(const Allocator& a) const {
  167. return std::basic_string<value_type, traits_type, Allocator>(begin(), end(), a);
  168. }
  169. private:
  170. BOOST_CONSTEXPR static const_pointer null_char_() {return detail::null_char_(CharT{});}
  171. const_pointer view_;
  172. };
  173. template<class charT, class traits>
  174. inline std::basic_ostream<charT, traits>&
  175. operator<<(std::basic_ostream<charT, traits>& os,
  176. const basic_cstring_ref<charT,traits>& str)
  177. {
  178. return os << static_cast<basic_string_view<charT, traits>>(str);
  179. }
  180. template <class charT, class traits>
  181. std::size_t hash_value(basic_string_view<charT, traits> s) {
  182. return boost::hash_range(s.begin(), s.end());
  183. }
  184. using cstring_ref = basic_cstring_ref<char>;
  185. using wcstring_ref = basic_cstring_ref<wchar_t>;
  186. using u16cstring_ref = basic_cstring_ref<char16_t>;
  187. using u32cstring_ref = basic_cstring_ref<char32_t>;
  188. #if defined(BOOST_PROCESS_V2_HAS_CHAR8_T)
  189. using u8cstring_ref = basic_cstring_ref<char8_t>;
  190. #endif
  191. BOOST_PROCESS_V2_END_NAMESPACE
  192. #endif //BOOST_PROCESS_V2_CSTRING_REF_HPP