rfc7230.ipp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. //
  2. // Copyright (c) 2016-2017 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/detail/rfc7230.hpp>
  12. #include <iterator>
  13. namespace boost {
  14. namespace beast {
  15. namespace http {
  16. class param_list::const_iterator
  17. {
  18. using iter_type = string_view::const_iterator;
  19. std::string s_;
  20. detail::param_iter pi_;
  21. public:
  22. using value_type = param_list::value_type;
  23. using pointer = value_type const*;
  24. using reference = value_type const&;
  25. using difference_type = std::ptrdiff_t;
  26. using iterator_category = std::input_iterator_tag;
  27. const_iterator() = default;
  28. bool
  29. operator==(const_iterator const& other) const
  30. {
  31. return
  32. other.pi_.it == pi_.it &&
  33. other.pi_.last == pi_.last &&
  34. other.pi_.first == pi_.first;
  35. }
  36. bool
  37. operator!=(const_iterator const& other) const
  38. {
  39. return !(*this == other);
  40. }
  41. reference
  42. operator*() const
  43. {
  44. return pi_.v;
  45. }
  46. pointer
  47. operator->() const
  48. {
  49. return &*(*this);
  50. }
  51. const_iterator&
  52. operator++()
  53. {
  54. increment();
  55. return *this;
  56. }
  57. const_iterator
  58. operator++(int)
  59. {
  60. auto temp = *this;
  61. ++(*this);
  62. return temp;
  63. }
  64. private:
  65. friend class param_list;
  66. const_iterator(iter_type first, iter_type last)
  67. {
  68. pi_.it = first;
  69. pi_.first = first;
  70. pi_.last = last;
  71. increment();
  72. }
  73. template<class = void>
  74. static
  75. std::string
  76. unquote(string_view sr);
  77. template<class = void>
  78. void
  79. increment();
  80. };
  81. inline
  82. auto
  83. param_list::
  84. begin() const ->
  85. const_iterator
  86. {
  87. return const_iterator{s_.begin(), s_.end()};
  88. }
  89. inline
  90. auto
  91. param_list::
  92. end() const ->
  93. const_iterator
  94. {
  95. return const_iterator{s_.end(), s_.end()};
  96. }
  97. inline
  98. auto
  99. param_list::
  100. cbegin() const ->
  101. const_iterator
  102. {
  103. return const_iterator{s_.begin(), s_.end()};
  104. }
  105. inline
  106. auto
  107. param_list::
  108. cend() const ->
  109. const_iterator
  110. {
  111. return const_iterator{s_.end(), s_.end()};
  112. }
  113. template<class>
  114. std::string
  115. param_list::const_iterator::
  116. unquote(string_view sr)
  117. {
  118. std::string s;
  119. s.reserve(sr.size());
  120. auto it = sr.begin() + 1;
  121. auto end = sr.end() - 1;
  122. while(it != end)
  123. {
  124. if(*it == '\\')
  125. ++it;
  126. s.push_back(*it);
  127. ++it;
  128. }
  129. return s;
  130. }
  131. template<class>
  132. void
  133. param_list::const_iterator::
  134. increment()
  135. {
  136. s_.clear();
  137. pi_.increment();
  138. if(pi_.empty())
  139. {
  140. pi_.it = pi_.last;
  141. pi_.first = pi_.last;
  142. }
  143. else if(! pi_.v.second.empty() &&
  144. pi_.v.second.front() == '"')
  145. {
  146. s_ = unquote(pi_.v.second);
  147. pi_.v.second = string_view{
  148. s_.data(), s_.size()};
  149. }
  150. }
  151. //------------------------------------------------------------------------------
  152. class ext_list::const_iterator
  153. {
  154. ext_list::value_type v_;
  155. iter_type it_;
  156. iter_type first_;
  157. iter_type last_;
  158. public:
  159. using value_type = ext_list::value_type;
  160. using pointer = value_type const*;
  161. using reference = value_type const&;
  162. using difference_type = std::ptrdiff_t;
  163. using iterator_category = std::forward_iterator_tag;
  164. const_iterator() = default;
  165. bool
  166. operator==(const_iterator const& other) const
  167. {
  168. return
  169. other.it_ == it_ &&
  170. other.first_ == first_ &&
  171. other.last_ == last_;
  172. }
  173. bool
  174. operator!=(const_iterator const& other) const
  175. {
  176. return !(*this == other);
  177. }
  178. reference
  179. operator*() const
  180. {
  181. return v_;
  182. }
  183. pointer
  184. operator->() const
  185. {
  186. return &*(*this);
  187. }
  188. const_iterator&
  189. operator++()
  190. {
  191. increment();
  192. return *this;
  193. }
  194. const_iterator
  195. operator++(int)
  196. {
  197. auto temp = *this;
  198. ++(*this);
  199. return temp;
  200. }
  201. private:
  202. friend class ext_list;
  203. const_iterator(iter_type begin, iter_type end)
  204. {
  205. it_ = begin;
  206. first_ = begin;
  207. last_ = end;
  208. increment();
  209. }
  210. template<class = void>
  211. void
  212. increment();
  213. };
  214. inline
  215. auto
  216. ext_list::
  217. begin() const ->
  218. const_iterator
  219. {
  220. return const_iterator{s_.begin(), s_.end()};
  221. }
  222. inline
  223. auto
  224. ext_list::
  225. end() const ->
  226. const_iterator
  227. {
  228. return const_iterator{s_.end(), s_.end()};
  229. }
  230. inline
  231. auto
  232. ext_list::
  233. cbegin() const ->
  234. const_iterator
  235. {
  236. return const_iterator{s_.begin(), s_.end()};
  237. }
  238. inline
  239. auto
  240. ext_list::
  241. cend() const ->
  242. const_iterator
  243. {
  244. return const_iterator{s_.end(), s_.end()};
  245. }
  246. template<class T>
  247. auto
  248. ext_list::
  249. find(T const& s) ->
  250. const_iterator
  251. {
  252. return std::find_if(begin(), end(),
  253. [&s](value_type const& v)
  254. {
  255. return iequals(s, v.first);
  256. });
  257. }
  258. template<class T>
  259. bool
  260. ext_list::
  261. exists(T const& s)
  262. {
  263. return find(s) != end();
  264. }
  265. template<class>
  266. void
  267. ext_list::const_iterator::
  268. increment()
  269. {
  270. /*
  271. ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
  272. ext = token param-list
  273. param-list = *( OWS ";" OWS param )
  274. param = token OWS "=" OWS ( token / quoted-string )
  275. chunked;a=b;i=j,gzip;windowBits=12
  276. x,y
  277. ,,,,,chameleon
  278. */
  279. auto const err =
  280. [&]
  281. {
  282. it_ = last_;
  283. first_ = last_;
  284. };
  285. auto need_comma = it_ != first_;
  286. v_.first = {};
  287. first_ = it_;
  288. for(;;)
  289. {
  290. detail::skip_ows(it_, last_);
  291. if(it_ == last_)
  292. return err();
  293. auto const c = *it_;
  294. if(detail::is_token_char(c))
  295. {
  296. if(need_comma)
  297. return err();
  298. auto const p0 = it_;
  299. for(;;)
  300. {
  301. ++it_;
  302. if(it_ == last_)
  303. break;
  304. if(! detail::is_token_char(*it_))
  305. break;
  306. }
  307. v_.first = string_view{&*p0,
  308. static_cast<std::size_t>(it_ - p0)};
  309. detail::param_iter pi;
  310. pi.it = it_;
  311. pi.first = it_;
  312. pi.last = last_;
  313. for(;;)
  314. {
  315. pi.increment();
  316. if(pi.empty())
  317. break;
  318. }
  319. v_.second = param_list{string_view{&*it_,
  320. static_cast<std::size_t>(pi.it - it_)}};
  321. it_ = pi.it;
  322. return;
  323. }
  324. if(c != ',')
  325. return err();
  326. need_comma = false;
  327. ++it_;
  328. }
  329. }
  330. //------------------------------------------------------------------------------
  331. class token_list::const_iterator
  332. {
  333. token_list::value_type v_;
  334. iter_type it_;
  335. iter_type first_;
  336. iter_type last_;
  337. public:
  338. using value_type = token_list::value_type;
  339. using pointer = value_type const*;
  340. using reference = value_type const&;
  341. using difference_type = std::ptrdiff_t;
  342. using iterator_category = std::forward_iterator_tag;
  343. const_iterator() = default;
  344. bool
  345. operator==(const_iterator const& other) const
  346. {
  347. return
  348. other.it_ == it_ &&
  349. other.first_ == first_ &&
  350. other.last_ == last_;
  351. }
  352. bool
  353. operator!=(const_iterator const& other) const
  354. {
  355. return !(*this == other);
  356. }
  357. reference
  358. operator*() const
  359. {
  360. return v_;
  361. }
  362. pointer
  363. operator->() const
  364. {
  365. return &*(*this);
  366. }
  367. const_iterator&
  368. operator++()
  369. {
  370. increment();
  371. return *this;
  372. }
  373. const_iterator
  374. operator++(int)
  375. {
  376. auto temp = *this;
  377. ++(*this);
  378. return temp;
  379. }
  380. private:
  381. friend class token_list;
  382. const_iterator(iter_type begin, iter_type end)
  383. {
  384. it_ = begin;
  385. first_ = begin;
  386. last_ = end;
  387. increment();
  388. }
  389. template<class = void>
  390. void
  391. increment();
  392. };
  393. inline
  394. auto
  395. token_list::
  396. begin() const ->
  397. const_iterator
  398. {
  399. return const_iterator{s_.begin(), s_.end()};
  400. }
  401. inline
  402. auto
  403. token_list::
  404. end() const ->
  405. const_iterator
  406. {
  407. return const_iterator{s_.end(), s_.end()};
  408. }
  409. inline
  410. auto
  411. token_list::
  412. cbegin() const ->
  413. const_iterator
  414. {
  415. return const_iterator{s_.begin(), s_.end()};
  416. }
  417. inline
  418. auto
  419. token_list::
  420. cend() const ->
  421. const_iterator
  422. {
  423. return const_iterator{s_.end(), s_.end()};
  424. }
  425. template<class>
  426. void
  427. token_list::const_iterator::
  428. increment()
  429. {
  430. /*
  431. token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
  432. */
  433. auto const err =
  434. [&]
  435. {
  436. it_ = last_;
  437. first_ = last_;
  438. };
  439. auto need_comma = it_ != first_;
  440. v_ = {};
  441. first_ = it_;
  442. for(;;)
  443. {
  444. detail::skip_ows(it_, last_);
  445. if(it_ == last_)
  446. return err();
  447. auto const c = *it_;
  448. if(detail::is_token_char(c))
  449. {
  450. if(need_comma)
  451. return err();
  452. auto const p0 = it_;
  453. for(;;)
  454. {
  455. ++it_;
  456. if(it_ == last_)
  457. break;
  458. if(! detail::is_token_char(*it_))
  459. break;
  460. }
  461. v_ = string_view{&*p0,
  462. static_cast<std::size_t>(it_ - p0)};
  463. return;
  464. }
  465. if(c != ',')
  466. return err();
  467. need_comma = false;
  468. ++it_;
  469. }
  470. }
  471. template<class T>
  472. bool
  473. token_list::
  474. exists(T const& s)
  475. {
  476. return std::find_if(begin(), end(),
  477. [&s](value_type const& v)
  478. {
  479. return iequals(s, v);
  480. }
  481. ) != end();
  482. }
  483. template<class Policy>
  484. bool
  485. validate_list(detail::basic_parsed_list<
  486. Policy> const& list)
  487. {
  488. auto const last = list.end();
  489. auto it = list.begin();
  490. if(it.error())
  491. return false;
  492. while(it != last)
  493. {
  494. ++it;
  495. if(it.error())
  496. return false;
  497. if(it == last)
  498. break;
  499. }
  500. return true;
  501. }
  502. } // http
  503. } // beast
  504. } // boost
  505. #endif