rfc7230.ipp 4.3 KB

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