rfc7230.ipp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
  8. //
  9. #ifndef BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
  10. #define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
  11. #include <boost/beast/http/rfc7230.hpp>
  12. #include <algorithm>
  13. namespace boost {
  14. namespace beast {
  15. namespace http {
  16. void param_list::const_iterator::
  17. unquote(string_view sr, std::string &s)
  18. {
  19. s.clear();
  20. s.reserve(sr.size());
  21. auto it = sr.begin() + 1;
  22. auto end = sr.end() - 1;
  23. while(it != end)
  24. {
  25. if(*it == '\\')
  26. ++it;
  27. s.push_back(*it);
  28. ++it;
  29. }
  30. }
  31. void
  32. param_list::const_iterator::
  33. increment()
  34. {
  35. s_.clear();
  36. pi_.increment();
  37. if(pi_.empty())
  38. {
  39. pi_.it = pi_.last;
  40. pi_.first = pi_.last;
  41. }
  42. else if(! pi_.v.second.empty() &&
  43. pi_.v.second.front() == '"')
  44. {
  45. unquote(pi_.v.second, s_);
  46. pi_.v.second = string_view{
  47. s_.data(), s_.size()};
  48. }
  49. }
  50. void
  51. ext_list::const_iterator::
  52. increment()
  53. {
  54. /*
  55. ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
  56. ext = token param-list
  57. param-list = *( OWS ";" OWS param )
  58. param = token OWS "=" OWS ( token / quoted-string )
  59. chunked;a=b;i=j;gzip;windowBits=12
  60. x,y
  61. ,,,,,chameleon
  62. */
  63. auto const err =
  64. [&]
  65. {
  66. it_ = last_;
  67. first_ = last_;
  68. };
  69. auto need_comma = it_ != first_;
  70. v_.first = {};
  71. first_ = it_;
  72. for(;;)
  73. {
  74. detail::skip_ows(it_, last_);
  75. if(it_ == last_)
  76. return err();
  77. auto const c = *it_;
  78. if(detail::is_token_char(c))
  79. {
  80. if(need_comma)
  81. return err();
  82. auto const p0 = it_;
  83. for(;;)
  84. {
  85. ++it_;
  86. if(it_ == last_)
  87. break;
  88. if(! detail::is_token_char(*it_))
  89. break;
  90. }
  91. v_.first = string_view{&*p0,
  92. static_cast<std::size_t>(it_ - p0)};
  93. if (it_ == last_)
  94. return;
  95. detail::param_iter pi;
  96. pi.it = it_;
  97. pi.first = it_;
  98. pi.last = last_;
  99. for(;;)
  100. {
  101. pi.increment();
  102. if(pi.empty())
  103. break;
  104. }
  105. v_.second = param_list{string_view{&*it_,
  106. static_cast<std::size_t>(pi.it - it_)}};
  107. it_ = pi.it;
  108. return;
  109. }
  110. if(c != ',')
  111. return err();
  112. need_comma = false;
  113. ++it_;
  114. }
  115. }
  116. auto
  117. ext_list::
  118. find(string_view const& s) -> const_iterator
  119. {
  120. return std::find_if(begin(), end(),
  121. [&s](value_type const& v)
  122. {
  123. return beast::iequals(s, v.first);
  124. });
  125. }
  126. bool
  127. ext_list::
  128. exists(string_view const& s)
  129. {
  130. return find(s) != end();
  131. }
  132. void
  133. token_list::const_iterator::
  134. increment()
  135. {
  136. /*
  137. token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
  138. */
  139. auto const err =
  140. [&]
  141. {
  142. it_ = last_;
  143. first_ = last_;
  144. };
  145. auto need_comma = it_ != first_;
  146. v_ = {};
  147. first_ = it_;
  148. for(;;)
  149. {
  150. detail::skip_ows(it_, last_);
  151. if(it_ == last_)
  152. return err();
  153. auto const c = *it_;
  154. if(detail::is_token_char(c))
  155. {
  156. if(need_comma)
  157. return err();
  158. auto const p0 = it_;
  159. for(;;)
  160. {
  161. ++it_;
  162. if(it_ == last_)
  163. break;
  164. if(! detail::is_token_char(*it_))
  165. break;
  166. }
  167. v_ = string_view{&*p0,
  168. static_cast<std::size_t>(it_ - p0)};
  169. return;
  170. }
  171. if(c != ',')
  172. return err();
  173. need_comma = false;
  174. ++it_;
  175. }
  176. }
  177. bool
  178. token_list::
  179. exists(string_view const& s)
  180. {
  181. return std::find_if(begin(), end(),
  182. [&s](value_type const& v)
  183. {
  184. return beast::iequals(s, v);
  185. }
  186. ) != end();
  187. }
  188. } // http
  189. } // beast
  190. } // boost
  191. #endif // BOOST_BEAST_HTTP_IMPL_RFC7230_IPP