decode_view.ipp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //
  2. // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/url
  8. //
  9. #ifndef BOOST_URL_IMPL_DECODE_VIEW_IPP
  10. #define BOOST_URL_IMPL_DECODE_VIEW_IPP
  11. #include <boost/url/decode_view.hpp>
  12. #include <ostream>
  13. namespace boost {
  14. namespace urls {
  15. namespace detail {
  16. template <class T>
  17. int
  18. decoded_strcmp(decode_view s0, T s1)
  19. {
  20. auto const n0 = s0.size();
  21. auto const n1 = s1.size();
  22. auto n = (std::min)(n0, n1);
  23. auto it0 = s0.begin();
  24. auto it1 = s1.begin();
  25. while (n--)
  26. {
  27. const char c0 = *it0++;
  28. const char c1 = *it1++;
  29. if (c0 == c1)
  30. continue;
  31. return 1 - 2 * (static_cast<unsigned char>(c0)
  32. < static_cast<unsigned char>(c1));
  33. }
  34. return 1 - (n0 == n1) - 2 * (n0 < n1);
  35. }
  36. } // detail
  37. //------------------------------------------------
  38. auto
  39. decode_view::
  40. iterator::
  41. operator*() const noexcept ->
  42. reference
  43. {
  44. if (space_as_plus_ &&
  45. *pos_ == '+')
  46. return ' ';
  47. if (*pos_ != '%')
  48. return *pos_;
  49. auto d0 = grammar::hexdig_value(pos_[1]);
  50. auto d1 = grammar::hexdig_value(pos_[2]);
  51. return static_cast<char>(
  52. ((static_cast<
  53. unsigned char>(d0) << 4) +
  54. (static_cast<
  55. unsigned char>(d1))));
  56. }
  57. // unchecked constructor
  58. decode_view::
  59. decode_view(
  60. string_view s,
  61. std::size_t n,
  62. encoding_opts opt) noexcept
  63. : p_(s.data())
  64. , n_(s.size())
  65. , dn_(n)
  66. , space_as_plus_(
  67. opt.space_as_plus)
  68. {
  69. }
  70. int
  71. decode_view::
  72. compare(string_view other) const noexcept
  73. {
  74. return detail::decoded_strcmp(*this, other);
  75. }
  76. int
  77. decode_view::
  78. compare(decode_view other) const noexcept
  79. {
  80. return detail::decoded_strcmp(*this, other);
  81. }
  82. void
  83. decode_view::
  84. write(std::ostream& os) const
  85. {
  86. auto it = begin();
  87. auto const end_ = end();
  88. while(it != end_)
  89. os.put(*it++);
  90. }
  91. void
  92. decode_view::
  93. remove_prefix( size_type n )
  94. {
  95. auto it = begin();
  96. auto n0 = n;
  97. while (n)
  98. {
  99. ++it;
  100. --n;
  101. }
  102. n_ -= (it.base() - begin().base());
  103. dn_ -= n0;
  104. p_ = it.base();
  105. }
  106. void
  107. decode_view::
  108. remove_suffix( size_type n )
  109. {
  110. auto it = end();
  111. auto n0 = n;
  112. while (n)
  113. {
  114. --it;
  115. --n;
  116. }
  117. n_ -= (end().base() - it.base());
  118. dn_ -= n0;
  119. }
  120. bool
  121. decode_view::
  122. starts_with( string_view s ) const noexcept
  123. {
  124. if (s.size() > size())
  125. return false;
  126. auto it0 = begin();
  127. auto it1 = s.begin();
  128. std::size_t n = s.size();
  129. while (n)
  130. {
  131. if (*it0 != *it1)
  132. return false;
  133. ++it0;
  134. ++it1;
  135. --n;
  136. }
  137. return true;
  138. }
  139. bool
  140. decode_view::
  141. ends_with( string_view s ) const noexcept
  142. {
  143. if (s.size() > size())
  144. return false;
  145. auto it0 = end();
  146. auto it1 = s.end();
  147. std::size_t n = s.size();
  148. --it0;
  149. --it1;
  150. while (n - 1)
  151. {
  152. if (*it0 != *it1)
  153. return false;
  154. --it0;
  155. --it1;
  156. --n;
  157. }
  158. return *it0 == *it1;
  159. }
  160. bool
  161. decode_view::
  162. starts_with( char ch ) const noexcept
  163. {
  164. return
  165. !empty() &&
  166. front() == ch;
  167. }
  168. bool
  169. decode_view::
  170. ends_with( char ch ) const noexcept
  171. {
  172. return
  173. !empty() &&
  174. back() == ch;
  175. }
  176. decode_view::const_iterator
  177. decode_view::
  178. find( char ch ) const noexcept
  179. {
  180. auto it = begin();
  181. auto end = this->end();
  182. while (it != end)
  183. {
  184. if (*it == ch)
  185. return it;
  186. ++it;
  187. }
  188. return it;
  189. }
  190. decode_view::const_iterator
  191. decode_view::
  192. rfind( char ch ) const noexcept
  193. {
  194. if (empty())
  195. return end();
  196. auto it = end();
  197. auto begin = this->begin();
  198. --it;
  199. while (it != begin)
  200. {
  201. if (*it == ch)
  202. return it;
  203. --it;
  204. }
  205. if (*it == ch)
  206. return it;
  207. return end();
  208. }
  209. } // urls
  210. } // boost
  211. #endif