fields.hpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406
  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_FIELDS_HPP
  10. #define BOOST_BEAST_HTTP_IMPL_FIELDS_HPP
  11. #include <boost/beast/core/buffers_cat.hpp>
  12. #include <boost/beast/core/string.hpp>
  13. #include <boost/beast/core/static_string.hpp>
  14. #include <boost/beast/core/detail/buffers_ref.hpp>
  15. #include <boost/beast/core/detail/clamp.hpp>
  16. #include <boost/beast/http/verb.hpp>
  17. #include <boost/beast/http/rfc7230.hpp>
  18. #include <boost/beast/http/status.hpp>
  19. #include <boost/beast/http/chunk_encode.hpp>
  20. #include <boost/core/exchange.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <stdexcept>
  23. #include <string>
  24. #if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
  25. // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
  26. #ifndef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
  27. #define BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
  28. #endif
  29. #endif
  30. namespace boost {
  31. namespace beast {
  32. namespace http {
  33. template<class Allocator>
  34. class basic_fields<Allocator>::writer
  35. {
  36. public:
  37. using iter_type = typename list_t::const_iterator;
  38. struct field_iterator
  39. {
  40. iter_type it_;
  41. using value_type = net::const_buffer;
  42. using pointer = value_type const*;
  43. using reference = value_type const;
  44. using difference_type = std::ptrdiff_t;
  45. using iterator_category =
  46. std::bidirectional_iterator_tag;
  47. field_iterator() = default;
  48. field_iterator(field_iterator&& other) = default;
  49. field_iterator(field_iterator const& other) = default;
  50. field_iterator& operator=(field_iterator&& other) = default;
  51. field_iterator& operator=(field_iterator const& other) = default;
  52. explicit
  53. field_iterator(iter_type it)
  54. : it_(it)
  55. {
  56. }
  57. bool
  58. operator==(field_iterator const& other) const
  59. {
  60. return it_ == other.it_;
  61. }
  62. bool
  63. operator!=(field_iterator const& other) const
  64. {
  65. return !(*this == other);
  66. }
  67. reference
  68. operator*() const
  69. {
  70. return it_->buffer();
  71. }
  72. field_iterator&
  73. operator++()
  74. {
  75. ++it_;
  76. return *this;
  77. }
  78. field_iterator
  79. operator++(int)
  80. {
  81. auto temp = *this;
  82. ++(*this);
  83. return temp;
  84. }
  85. field_iterator&
  86. operator--()
  87. {
  88. --it_;
  89. return *this;
  90. }
  91. field_iterator
  92. operator--(int)
  93. {
  94. auto temp = *this;
  95. --(*this);
  96. return temp;
  97. }
  98. };
  99. class field_range
  100. {
  101. field_iterator first_;
  102. field_iterator last_;
  103. public:
  104. using const_iterator =
  105. field_iterator;
  106. using value_type =
  107. typename const_iterator::value_type;
  108. field_range(iter_type first, iter_type last)
  109. : first_(first)
  110. , last_(last)
  111. {
  112. }
  113. const_iterator
  114. begin() const
  115. {
  116. return first_;
  117. }
  118. const_iterator
  119. end() const
  120. {
  121. return last_;
  122. }
  123. };
  124. using view_type = buffers_cat_view<
  125. net::const_buffer,
  126. net::const_buffer,
  127. net::const_buffer,
  128. field_range,
  129. chunk_crlf>;
  130. basic_fields const& f_;
  131. boost::optional<view_type> view_;
  132. char buf_[13];
  133. public:
  134. using const_buffers_type =
  135. beast::detail::buffers_ref<view_type>;
  136. writer(basic_fields const& f,
  137. unsigned version, verb v);
  138. writer(basic_fields const& f,
  139. unsigned version, unsigned code);
  140. writer(basic_fields const& f);
  141. const_buffers_type
  142. get() const
  143. {
  144. return const_buffers_type(*view_);
  145. }
  146. };
  147. template<class Allocator>
  148. basic_fields<Allocator>::writer::
  149. writer(basic_fields const& f)
  150. : f_(f)
  151. {
  152. view_.emplace(
  153. net::const_buffer{nullptr, 0},
  154. net::const_buffer{nullptr, 0},
  155. net::const_buffer{nullptr, 0},
  156. field_range(f_.list_.begin(), f_.list_.end()),
  157. chunk_crlf());
  158. }
  159. template<class Allocator>
  160. basic_fields<Allocator>::writer::
  161. writer(basic_fields const& f,
  162. unsigned version, verb v)
  163. : f_(f)
  164. {
  165. /*
  166. request
  167. "<method>"
  168. " <target>"
  169. " HTTP/X.Y\r\n" (11 chars)
  170. */
  171. string_view sv;
  172. if(v == verb::unknown)
  173. sv = f_.get_method_impl();
  174. else
  175. sv = to_string(v);
  176. // target_or_reason_ has a leading SP
  177. buf_[0] = ' ';
  178. buf_[1] = 'H';
  179. buf_[2] = 'T';
  180. buf_[3] = 'T';
  181. buf_[4] = 'P';
  182. buf_[5] = '/';
  183. buf_[6] = '0' + static_cast<char>(version / 10);
  184. buf_[7] = '.';
  185. buf_[8] = '0' + static_cast<char>(version % 10);
  186. buf_[9] = '\r';
  187. buf_[10]= '\n';
  188. view_.emplace(
  189. net::const_buffer{sv.data(), sv.size()},
  190. net::const_buffer{
  191. f_.target_or_reason_.data(),
  192. f_.target_or_reason_.size()},
  193. net::const_buffer{buf_, 11},
  194. field_range(f_.list_.begin(), f_.list_.end()),
  195. chunk_crlf());
  196. }
  197. template<class Allocator>
  198. basic_fields<Allocator>::writer::
  199. writer(basic_fields const& f,
  200. unsigned version, unsigned code)
  201. : f_(f)
  202. {
  203. /*
  204. response
  205. "HTTP/X.Y ### " (13 chars)
  206. "<reason>"
  207. "\r\n"
  208. */
  209. buf_[0] = 'H';
  210. buf_[1] = 'T';
  211. buf_[2] = 'T';
  212. buf_[3] = 'P';
  213. buf_[4] = '/';
  214. buf_[5] = '0' + static_cast<char>(version / 10);
  215. buf_[6] = '.';
  216. buf_[7] = '0' + static_cast<char>(version % 10);
  217. buf_[8] = ' ';
  218. buf_[9] = '0' + static_cast<char>(code / 100);
  219. buf_[10]= '0' + static_cast<char>((code / 10) % 10);
  220. buf_[11]= '0' + static_cast<char>(code % 10);
  221. buf_[12]= ' ';
  222. string_view sv;
  223. if(! f_.target_or_reason_.empty())
  224. sv = f_.target_or_reason_;
  225. else
  226. sv = obsolete_reason(static_cast<status>(code));
  227. view_.emplace(
  228. net::const_buffer{buf_, 13},
  229. net::const_buffer{sv.data(), sv.size()},
  230. net::const_buffer{"\r\n", 2},
  231. field_range(f_.list_.begin(), f_.list_.end()),
  232. chunk_crlf{});
  233. }
  234. //------------------------------------------------------------------------------
  235. template<class Allocator>
  236. char*
  237. basic_fields<Allocator>::
  238. value_type::
  239. data() const
  240. {
  241. return const_cast<char*>(
  242. reinterpret_cast<char const*>(
  243. static_cast<element const*>(this) + 1));
  244. }
  245. template<class Allocator>
  246. net::const_buffer
  247. basic_fields<Allocator>::
  248. value_type::
  249. buffer() const
  250. {
  251. return net::const_buffer{data(),
  252. static_cast<std::size_t>(off_) + len_ + 2};
  253. }
  254. template<class Allocator>
  255. basic_fields<Allocator>::
  256. value_type::
  257. value_type(field name,
  258. string_view sname, string_view value)
  259. : off_(static_cast<off_t>(sname.size() + 2))
  260. , len_(static_cast<off_t>(value.size()))
  261. , f_(name)
  262. {
  263. //BOOST_ASSERT(name == field::unknown ||
  264. // iequals(sname, to_string(name)));
  265. char* p = data();
  266. p[off_-2] = ':';
  267. p[off_-1] = ' ';
  268. p[off_ + len_] = '\r';
  269. p[off_ + len_ + 1] = '\n';
  270. sname.copy(p, sname.size());
  271. value.copy(p + off_, value.size());
  272. }
  273. template<class Allocator>
  274. field
  275. basic_fields<Allocator>::
  276. value_type::
  277. name() const
  278. {
  279. return f_;
  280. }
  281. template<class Allocator>
  282. string_view const
  283. basic_fields<Allocator>::
  284. value_type::
  285. name_string() const
  286. {
  287. return {data(),
  288. static_cast<std::size_t>(off_ - 2)};
  289. }
  290. template<class Allocator>
  291. string_view const
  292. basic_fields<Allocator>::
  293. value_type::
  294. value() const
  295. {
  296. return {data() + off_,
  297. static_cast<std::size_t>(len_)};
  298. }
  299. template<class Allocator>
  300. basic_fields<Allocator>::
  301. element::
  302. element(field name,
  303. string_view sname, string_view value)
  304. : value_type(name, sname, value)
  305. {
  306. }
  307. //------------------------------------------------------------------------------
  308. template<class Allocator>
  309. basic_fields<Allocator>::
  310. ~basic_fields()
  311. {
  312. delete_list();
  313. realloc_string(method_, {});
  314. realloc_string(
  315. target_or_reason_, {});
  316. }
  317. template<class Allocator>
  318. basic_fields<Allocator>::
  319. basic_fields(Allocator const& alloc) noexcept
  320. : boost::empty_value<Allocator>(boost::empty_init_t(), alloc)
  321. {
  322. }
  323. template<class Allocator>
  324. basic_fields<Allocator>::
  325. basic_fields(basic_fields&& other) noexcept
  326. : boost::empty_value<Allocator>(boost::empty_init_t(),
  327. std::move(other.get()))
  328. , set_(std::move(other.set_))
  329. , list_(std::move(other.list_))
  330. , method_(boost::exchange(other.method_, {}))
  331. , target_or_reason_(boost::exchange(other.target_or_reason_, {}))
  332. {
  333. }
  334. template<class Allocator>
  335. basic_fields<Allocator>::
  336. basic_fields(basic_fields&& other, Allocator const& alloc)
  337. : boost::empty_value<Allocator>(boost::empty_init_t(), alloc)
  338. {
  339. if(this->get() != other.get())
  340. {
  341. copy_all(other);
  342. other.clear_all();
  343. }
  344. else
  345. {
  346. set_ = std::move(other.set_);
  347. list_ = std::move(other.list_);
  348. method_ = other.method_;
  349. target_or_reason_ = other.target_or_reason_;
  350. }
  351. }
  352. template<class Allocator>
  353. basic_fields<Allocator>::
  354. basic_fields(basic_fields const& other)
  355. : boost::empty_value<Allocator>(boost::empty_init_t(), alloc_traits::
  356. select_on_container_copy_construction(other.get()))
  357. {
  358. copy_all(other);
  359. }
  360. template<class Allocator>
  361. basic_fields<Allocator>::
  362. basic_fields(basic_fields const& other,
  363. Allocator const& alloc)
  364. : boost::empty_value<Allocator>(boost::empty_init_t(), alloc)
  365. {
  366. copy_all(other);
  367. }
  368. template<class Allocator>
  369. template<class OtherAlloc>
  370. basic_fields<Allocator>::
  371. basic_fields(basic_fields<OtherAlloc> const& other)
  372. {
  373. copy_all(other);
  374. }
  375. template<class Allocator>
  376. template<class OtherAlloc>
  377. basic_fields<Allocator>::
  378. basic_fields(basic_fields<OtherAlloc> const& other,
  379. Allocator const& alloc)
  380. : boost::empty_value<Allocator>(boost::empty_init_t(), alloc)
  381. {
  382. copy_all(other);
  383. }
  384. template<class Allocator>
  385. auto
  386. basic_fields<Allocator>::
  387. operator=(basic_fields&& other) noexcept(
  388. alloc_traits::propagate_on_container_move_assignment::value)
  389. -> basic_fields&
  390. {
  391. static_assert(is_nothrow_move_assignable<Allocator>::value,
  392. "Allocator must be noexcept assignable.");
  393. if(this == &other)
  394. return *this;
  395. move_assign(other, std::integral_constant<bool,
  396. alloc_traits:: propagate_on_container_move_assignment::value>{});
  397. return *this;
  398. }
  399. template<class Allocator>
  400. auto
  401. basic_fields<Allocator>::
  402. operator=(basic_fields const& other) ->
  403. basic_fields&
  404. {
  405. copy_assign(other, std::integral_constant<bool,
  406. alloc_traits::propagate_on_container_copy_assignment::value>{});
  407. return *this;
  408. }
  409. template<class Allocator>
  410. template<class OtherAlloc>
  411. auto
  412. basic_fields<Allocator>::
  413. operator=(basic_fields<OtherAlloc> const& other) ->
  414. basic_fields&
  415. {
  416. clear_all();
  417. copy_all(other);
  418. return *this;
  419. }
  420. //------------------------------------------------------------------------------
  421. //
  422. // Element access
  423. //
  424. //------------------------------------------------------------------------------
  425. template<class Allocator>
  426. string_view const
  427. basic_fields<Allocator>::
  428. at(field name) const
  429. {
  430. BOOST_ASSERT(name != field::unknown);
  431. auto const it = find(name);
  432. if(it == end())
  433. BOOST_THROW_EXCEPTION(std::out_of_range{
  434. "field not found"});
  435. return it->value();
  436. }
  437. template<class Allocator>
  438. string_view const
  439. basic_fields<Allocator>::
  440. at(string_view name) const
  441. {
  442. auto const it = find(name);
  443. if(it == end())
  444. BOOST_THROW_EXCEPTION(std::out_of_range{
  445. "field not found"});
  446. return it->value();
  447. }
  448. template<class Allocator>
  449. string_view const
  450. basic_fields<Allocator>::
  451. operator[](field name) const
  452. {
  453. BOOST_ASSERT(name != field::unknown);
  454. auto const it = find(name);
  455. if(it == end())
  456. return {};
  457. return it->value();
  458. }
  459. template<class Allocator>
  460. string_view const
  461. basic_fields<Allocator>::
  462. operator[](string_view name) const
  463. {
  464. auto const it = find(name);
  465. if(it == end())
  466. return {};
  467. return it->value();
  468. }
  469. //------------------------------------------------------------------------------
  470. //
  471. // Modifiers
  472. //
  473. //------------------------------------------------------------------------------
  474. template<class Allocator>
  475. void
  476. basic_fields<Allocator>::
  477. clear()
  478. {
  479. delete_list();
  480. set_.clear();
  481. list_.clear();
  482. }
  483. template<class Allocator>
  484. inline
  485. void
  486. basic_fields<Allocator>::
  487. insert(field name, string_param const& value)
  488. {
  489. BOOST_ASSERT(name != field::unknown);
  490. insert(name, to_string(name), value);
  491. }
  492. template<class Allocator>
  493. void
  494. basic_fields<Allocator>::
  495. insert(string_view sname, string_param const& value)
  496. {
  497. auto const name =
  498. string_to_field(sname);
  499. insert(name, sname, value);
  500. }
  501. template<class Allocator>
  502. void
  503. basic_fields<Allocator>::
  504. insert(field name,
  505. string_view sname, string_param const& value)
  506. {
  507. auto& e = new_element(name, sname,
  508. static_cast<string_view>(value));
  509. auto const before =
  510. set_.upper_bound(sname, key_compare{});
  511. if(before == set_.begin())
  512. {
  513. BOOST_ASSERT(count(sname) == 0);
  514. set_.insert_before(before, e);
  515. list_.push_back(e);
  516. return;
  517. }
  518. auto const last = std::prev(before);
  519. // VFALCO is it worth comparing `field name` first?
  520. if(! iequals(sname, last->name_string()))
  521. {
  522. BOOST_ASSERT(count(sname) == 0);
  523. set_.insert_before(before, e);
  524. list_.push_back(e);
  525. return;
  526. }
  527. // keep duplicate fields together in the list
  528. set_.insert_before(before, e);
  529. list_.insert(++list_.iterator_to(*last), e);
  530. }
  531. template<class Allocator>
  532. void
  533. basic_fields<Allocator>::
  534. set(field name, string_param const& value)
  535. {
  536. BOOST_ASSERT(name != field::unknown);
  537. set_element(new_element(name, to_string(name),
  538. static_cast<string_view>(value)));
  539. }
  540. template<class Allocator>
  541. void
  542. basic_fields<Allocator>::
  543. set(string_view sname, string_param const& value)
  544. {
  545. set_element(new_element(
  546. string_to_field(sname), sname,
  547. static_cast<string_view>(value)));
  548. }
  549. template<class Allocator>
  550. auto
  551. basic_fields<Allocator>::
  552. erase(const_iterator pos) ->
  553. const_iterator
  554. {
  555. auto next = pos;
  556. auto& e = *next++;
  557. set_.erase(e);
  558. list_.erase(pos);
  559. delete_element(const_cast<element&>(e));
  560. return next;
  561. }
  562. template<class Allocator>
  563. std::size_t
  564. basic_fields<Allocator>::
  565. erase(field name)
  566. {
  567. BOOST_ASSERT(name != field::unknown);
  568. return erase(to_string(name));
  569. }
  570. template<class Allocator>
  571. std::size_t
  572. basic_fields<Allocator>::
  573. erase(string_view name)
  574. {
  575. std::size_t n =0;
  576. set_.erase_and_dispose(name, key_compare{},
  577. [&](element* e)
  578. {
  579. ++n;
  580. list_.erase(list_.iterator_to(*e));
  581. delete_element(*e);
  582. });
  583. return n;
  584. }
  585. template<class Allocator>
  586. void
  587. basic_fields<Allocator>::
  588. swap(basic_fields<Allocator>& other)
  589. {
  590. swap(other, std::integral_constant<bool,
  591. alloc_traits::propagate_on_container_swap::value>{});
  592. }
  593. template<class Allocator>
  594. void
  595. swap(
  596. basic_fields<Allocator>& lhs,
  597. basic_fields<Allocator>& rhs)
  598. {
  599. lhs.swap(rhs);
  600. }
  601. //------------------------------------------------------------------------------
  602. //
  603. // Lookup
  604. //
  605. //------------------------------------------------------------------------------
  606. template<class Allocator>
  607. inline
  608. std::size_t
  609. basic_fields<Allocator>::
  610. count(field name) const
  611. {
  612. BOOST_ASSERT(name != field::unknown);
  613. return count(to_string(name));
  614. }
  615. template<class Allocator>
  616. std::size_t
  617. basic_fields<Allocator>::
  618. count(string_view name) const
  619. {
  620. return set_.count(name, key_compare{});
  621. }
  622. template<class Allocator>
  623. inline
  624. auto
  625. basic_fields<Allocator>::
  626. find(field name) const ->
  627. const_iterator
  628. {
  629. BOOST_ASSERT(name != field::unknown);
  630. return find(to_string(name));
  631. }
  632. template<class Allocator>
  633. auto
  634. basic_fields<Allocator>::
  635. find(string_view name) const ->
  636. const_iterator
  637. {
  638. auto const it = set_.find(
  639. name, key_compare{});
  640. if(it == set_.end())
  641. return list_.end();
  642. return list_.iterator_to(*it);
  643. }
  644. template<class Allocator>
  645. inline
  646. auto
  647. basic_fields<Allocator>::
  648. equal_range(field name) const ->
  649. std::pair<const_iterator, const_iterator>
  650. {
  651. BOOST_ASSERT(name != field::unknown);
  652. return equal_range(to_string(name));
  653. }
  654. template<class Allocator>
  655. auto
  656. basic_fields<Allocator>::
  657. equal_range(string_view name) const ->
  658. std::pair<const_iterator, const_iterator>
  659. {
  660. auto result =
  661. set_.equal_range(name, key_compare{});
  662. if(result.first == result.second)
  663. return {list_.end(), list_.end()};
  664. return {
  665. list_.iterator_to(*result.first),
  666. ++list_.iterator_to(*(--result.second))};
  667. }
  668. //------------------------------------------------------------------------------
  669. namespace detail {
  670. // Filter a token list
  671. //
  672. template<class String, class Pred>
  673. void
  674. filter_token_list(
  675. String& s,
  676. string_view value,
  677. Pred&& pred)
  678. {
  679. token_list te{value};
  680. auto it = te.begin();
  681. auto last = te.end();
  682. if(it == last)
  683. return;
  684. while(pred(*it))
  685. if(++it == last)
  686. return;
  687. s.append(it->data(), it->size());
  688. while(++it != last)
  689. {
  690. if(! pred(*it))
  691. {
  692. s.append(", ");
  693. s.append(it->data(), it->size());
  694. }
  695. }
  696. }
  697. // Filter the last item in a token list
  698. template<class String, class Pred>
  699. void
  700. filter_token_list_last(
  701. String& s,
  702. string_view value,
  703. Pred&& pred)
  704. {
  705. token_list te{value};
  706. if(te.begin() != te.end())
  707. {
  708. auto it = te.begin();
  709. auto next = std::next(it);
  710. if(next == te.end())
  711. {
  712. if(! pred(*it))
  713. s.append(it->data(), it->size());
  714. return;
  715. }
  716. s.append(it->data(), it->size());
  717. for(;;)
  718. {
  719. it = next;
  720. next = std::next(it);
  721. if(next == te.end())
  722. {
  723. if(! pred(*it))
  724. {
  725. s.append(", ");
  726. s.append(it->data(), it->size());
  727. }
  728. return;
  729. }
  730. s.append(", ");
  731. s.append(it->data(), it->size());
  732. }
  733. }
  734. }
  735. template<class String>
  736. void
  737. keep_alive_impl(
  738. String& s, string_view value,
  739. unsigned version, bool keep_alive)
  740. {
  741. if(version < 11)
  742. {
  743. if(keep_alive)
  744. {
  745. // remove close
  746. filter_token_list(s, value,
  747. [](string_view s)
  748. {
  749. return iequals(s, "close");
  750. });
  751. // add keep-alive
  752. if(s.empty())
  753. s.append("keep-alive");
  754. else if(! token_list{value}.exists("keep-alive"))
  755. s.append(", keep-alive");
  756. }
  757. else
  758. {
  759. // remove close and keep-alive
  760. filter_token_list(s, value,
  761. [](string_view s)
  762. {
  763. return
  764. iequals(s, "close") ||
  765. iequals(s, "keep-alive");
  766. });
  767. }
  768. }
  769. else
  770. {
  771. if(keep_alive)
  772. {
  773. // remove close and keep-alive
  774. filter_token_list(s, value,
  775. [](string_view s)
  776. {
  777. return
  778. iequals(s, "close") ||
  779. iequals(s, "keep-alive");
  780. });
  781. }
  782. else
  783. {
  784. // remove keep-alive
  785. filter_token_list(s, value,
  786. [](string_view s)
  787. {
  788. return iequals(s, "keep-alive");
  789. });
  790. // add close
  791. if(s.empty())
  792. s.append("close");
  793. else if(! token_list{value}.exists("close"))
  794. s.append(", close");
  795. }
  796. }
  797. }
  798. } // detail
  799. //------------------------------------------------------------------------------
  800. // Fields
  801. template<class Allocator>
  802. inline
  803. string_view
  804. basic_fields<Allocator>::
  805. get_method_impl() const
  806. {
  807. return method_;
  808. }
  809. template<class Allocator>
  810. inline
  811. string_view
  812. basic_fields<Allocator>::
  813. get_target_impl() const
  814. {
  815. if(target_or_reason_.empty())
  816. return target_or_reason_;
  817. return {
  818. target_or_reason_.data() + 1,
  819. target_or_reason_.size() - 1};
  820. }
  821. template<class Allocator>
  822. inline
  823. string_view
  824. basic_fields<Allocator>::
  825. get_reason_impl() const
  826. {
  827. return target_or_reason_;
  828. }
  829. template<class Allocator>
  830. bool
  831. basic_fields<Allocator>::
  832. get_chunked_impl() const
  833. {
  834. auto const te = token_list{
  835. (*this)[field::transfer_encoding]};
  836. for(auto it = te.begin(); it != te.end();)
  837. {
  838. auto const next = std::next(it);
  839. if(next == te.end())
  840. return iequals(*it, "chunked");
  841. it = next;
  842. }
  843. return false;
  844. }
  845. template<class Allocator>
  846. bool
  847. basic_fields<Allocator>::
  848. get_keep_alive_impl(unsigned version) const
  849. {
  850. auto const it = find(field::connection);
  851. if(version < 11)
  852. {
  853. if(it == end())
  854. return false;
  855. return token_list{
  856. it->value()}.exists("keep-alive");
  857. }
  858. if(it == end())
  859. return true;
  860. return ! token_list{
  861. it->value()}.exists("close");
  862. }
  863. template<class Allocator>
  864. bool
  865. basic_fields<Allocator>::
  866. has_content_length_impl() const
  867. {
  868. return count(field::content_length) > 0;
  869. }
  870. template<class Allocator>
  871. inline
  872. void
  873. basic_fields<Allocator>::
  874. set_method_impl(string_view s)
  875. {
  876. realloc_string(method_, s);
  877. }
  878. template<class Allocator>
  879. inline
  880. void
  881. basic_fields<Allocator>::
  882. set_target_impl(string_view s)
  883. {
  884. realloc_target(
  885. target_or_reason_, s);
  886. }
  887. template<class Allocator>
  888. inline
  889. void
  890. basic_fields<Allocator>::
  891. set_reason_impl(string_view s)
  892. {
  893. realloc_string(
  894. target_or_reason_, s);
  895. }
  896. template<class Allocator>
  897. void
  898. basic_fields<Allocator>::
  899. set_chunked_impl(bool value)
  900. {
  901. auto it = find(field::transfer_encoding);
  902. if(value)
  903. {
  904. // append "chunked"
  905. if(it == end())
  906. {
  907. set(field::transfer_encoding, "chunked");
  908. return;
  909. }
  910. auto const te = token_list{it->value()};
  911. for(auto itt = te.begin();;)
  912. {
  913. auto const next = std::next(itt);
  914. if(next == te.end())
  915. {
  916. if(iequals(*itt, "chunked"))
  917. return; // already set
  918. break;
  919. }
  920. itt = next;
  921. }
  922. static_string<max_static_buffer> buf;
  923. if(! beast::detail::sum_exceeds(
  924. it->value().size(), 9u, buf.max_size()))
  925. {
  926. buf.append(it->value().data(), it->value().size());
  927. buf.append(", chunked", 9);
  928. set(field::transfer_encoding, buf);
  929. }
  930. else
  931. {
  932. #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
  933. // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
  934. std::string s;
  935. #else
  936. using A =
  937. typename beast::detail::allocator_traits<
  938. Allocator>::template rebind_alloc<char>;
  939. std::basic_string<
  940. char,
  941. std::char_traits<char>,
  942. A> s{A{this->get()}};
  943. #endif
  944. s.reserve(it->value().size() + 9);
  945. s.append(it->value().data(), it->value().size());
  946. s.append(", chunked", 9);
  947. set(field::transfer_encoding, s);
  948. }
  949. return;
  950. }
  951. // filter "chunked"
  952. if(it == end())
  953. return;
  954. #ifndef BOOST_NO_EXCEPTIONS
  955. try
  956. {
  957. static_string<max_static_buffer> buf;
  958. detail::filter_token_list_last(buf, it->value(),
  959. [](string_view s)
  960. {
  961. return iequals(s, "chunked");
  962. });
  963. if(! buf.empty())
  964. set(field::transfer_encoding, buf);
  965. else
  966. erase(field::transfer_encoding);
  967. }
  968. catch(std::length_error const&)
  969. #endif
  970. {
  971. #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
  972. // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
  973. std::string s;
  974. #else
  975. using A =
  976. typename beast::detail::allocator_traits<
  977. Allocator>::template rebind_alloc<char>;
  978. std::basic_string<
  979. char,
  980. std::char_traits<char>,
  981. A> s{A{this->get()}};
  982. #endif
  983. s.reserve(it->value().size());
  984. detail::filter_token_list_last(s, it->value(),
  985. [](string_view s)
  986. {
  987. return iequals(s, "chunked");
  988. });
  989. if(! s.empty())
  990. set(field::transfer_encoding, s);
  991. else
  992. erase(field::transfer_encoding);
  993. }
  994. }
  995. template<class Allocator>
  996. void
  997. basic_fields<Allocator>::
  998. set_content_length_impl(
  999. boost::optional<std::uint64_t> const& value)
  1000. {
  1001. if(! value)
  1002. erase(field::content_length);
  1003. else
  1004. set(field::content_length, *value);
  1005. }
  1006. template<class Allocator>
  1007. void
  1008. basic_fields<Allocator>::
  1009. set_keep_alive_impl(
  1010. unsigned version, bool keep_alive)
  1011. {
  1012. // VFALCO What about Proxy-Connection ?
  1013. auto const value = (*this)[field::connection];
  1014. #ifndef BOOST_NO_EXCEPTIONS
  1015. try
  1016. {
  1017. static_string<max_static_buffer> buf;
  1018. detail::keep_alive_impl(
  1019. buf, value, version, keep_alive);
  1020. if(buf.empty())
  1021. erase(field::connection);
  1022. else
  1023. set(field::connection, buf);
  1024. }
  1025. catch(std::length_error const&)
  1026. #endif
  1027. {
  1028. #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
  1029. // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
  1030. std::string s;
  1031. #else
  1032. using A =
  1033. typename beast::detail::allocator_traits<
  1034. Allocator>::template rebind_alloc<char>;
  1035. std::basic_string<
  1036. char,
  1037. std::char_traits<char>,
  1038. A> s{A{this->get()}};
  1039. #endif
  1040. s.reserve(value.size());
  1041. detail::keep_alive_impl(
  1042. s, value, version, keep_alive);
  1043. if(s.empty())
  1044. erase(field::connection);
  1045. else
  1046. set(field::connection, s);
  1047. }
  1048. }
  1049. //------------------------------------------------------------------------------
  1050. template<class Allocator>
  1051. auto
  1052. basic_fields<Allocator>::
  1053. new_element(field name,
  1054. string_view sname, string_view value) ->
  1055. element&
  1056. {
  1057. if(sname.size() + 2 >
  1058. (std::numeric_limits<off_t>::max)())
  1059. BOOST_THROW_EXCEPTION(std::length_error{
  1060. "field name too large"});
  1061. if(value.size() + 2 >
  1062. (std::numeric_limits<off_t>::max)())
  1063. BOOST_THROW_EXCEPTION(std::length_error{
  1064. "field value too large"});
  1065. value = detail::trim(value);
  1066. std::uint16_t const off =
  1067. static_cast<off_t>(sname.size() + 2);
  1068. std::uint16_t const len =
  1069. static_cast<off_t>(value.size());
  1070. auto a = rebind_type{this->get()};
  1071. auto const p = alloc_traits::allocate(a,
  1072. (sizeof(element) + off + len + 2 + sizeof(align_type) - 1) /
  1073. sizeof(align_type));
  1074. return *(::new(p) element(name, sname, value));
  1075. }
  1076. template<class Allocator>
  1077. void
  1078. basic_fields<Allocator>::
  1079. delete_element(element& e)
  1080. {
  1081. auto a = rebind_type{this->get()};
  1082. auto const n =
  1083. (sizeof(element) + e.off_ + e.len_ + 2 + sizeof(align_type) - 1) /
  1084. sizeof(align_type);
  1085. e.~element();
  1086. alloc_traits::deallocate(a, &e, n);
  1087. //reinterpret_cast<align_type*>(&e), n);
  1088. }
  1089. template<class Allocator>
  1090. void
  1091. basic_fields<Allocator>::
  1092. set_element(element& e)
  1093. {
  1094. auto it = set_.lower_bound(
  1095. e.name_string(), key_compare{});
  1096. if(it == set_.end() || ! iequals(
  1097. e.name_string(), it->name_string()))
  1098. {
  1099. set_.insert_before(it, e);
  1100. list_.push_back(e);
  1101. return;
  1102. }
  1103. for(;;)
  1104. {
  1105. auto next = it;
  1106. ++next;
  1107. set_.erase(it);
  1108. list_.erase(list_.iterator_to(*it));
  1109. delete_element(*it);
  1110. it = next;
  1111. if(it == set_.end() ||
  1112. ! iequals(e.name_string(), it->name_string()))
  1113. break;
  1114. }
  1115. set_.insert_before(it, e);
  1116. list_.push_back(e);
  1117. }
  1118. template<class Allocator>
  1119. void
  1120. basic_fields<Allocator>::
  1121. realloc_string(string_view& dest, string_view s)
  1122. {
  1123. if(dest.empty() && s.empty())
  1124. return;
  1125. auto a = typename beast::detail::allocator_traits<
  1126. Allocator>::template rebind_alloc<
  1127. char>(this->get());
  1128. char* p = nullptr;
  1129. if(! s.empty())
  1130. {
  1131. p = a.allocate(s.size());
  1132. s.copy(p, s.size());
  1133. }
  1134. if(! dest.empty())
  1135. a.deallocate(const_cast<char*>(
  1136. dest.data()), dest.size());
  1137. if(p)
  1138. dest = {p, s.size()};
  1139. else
  1140. dest = {};
  1141. }
  1142. template<class Allocator>
  1143. void
  1144. basic_fields<Allocator>::
  1145. realloc_target(
  1146. string_view& dest, string_view s)
  1147. {
  1148. // The target string are stored with an
  1149. // extra space at the beginning to help
  1150. // the writer class.
  1151. if(dest.empty() && s.empty())
  1152. return;
  1153. auto a = typename beast::detail::allocator_traits<
  1154. Allocator>::template rebind_alloc<
  1155. char>(this->get());
  1156. char* p = nullptr;
  1157. if(! s.empty())
  1158. {
  1159. p = a.allocate(1 + s.size());
  1160. p[0] = ' ';
  1161. s.copy(p + 1, s.size());
  1162. }
  1163. if(! dest.empty())
  1164. a.deallocate(const_cast<char*>(
  1165. dest.data()), dest.size());
  1166. if(p)
  1167. dest = {p, 1 + s.size()};
  1168. else
  1169. dest = {};
  1170. }
  1171. template<class Allocator>
  1172. template<class OtherAlloc>
  1173. void
  1174. basic_fields<Allocator>::
  1175. copy_all(basic_fields<OtherAlloc> const& other)
  1176. {
  1177. for(auto const& e : other.list_)
  1178. insert(e.name(), e.name_string(), e.value());
  1179. realloc_string(method_, other.method_);
  1180. realloc_string(target_or_reason_,
  1181. other.target_or_reason_);
  1182. }
  1183. template<class Allocator>
  1184. void
  1185. basic_fields<Allocator>::
  1186. clear_all()
  1187. {
  1188. clear();
  1189. realloc_string(method_, {});
  1190. realloc_string(target_or_reason_, {});
  1191. }
  1192. template<class Allocator>
  1193. void
  1194. basic_fields<Allocator>::
  1195. delete_list()
  1196. {
  1197. for(auto it = list_.begin(); it != list_.end();)
  1198. delete_element(*it++);
  1199. }
  1200. //------------------------------------------------------------------------------
  1201. template<class Allocator>
  1202. inline
  1203. void
  1204. basic_fields<Allocator>::
  1205. move_assign(basic_fields& other, std::true_type)
  1206. {
  1207. clear_all();
  1208. set_ = std::move(other.set_);
  1209. list_ = std::move(other.list_);
  1210. method_ = other.method_;
  1211. target_or_reason_ = other.target_or_reason_;
  1212. other.method_ = {};
  1213. other.target_or_reason_ = {};
  1214. this->get() = other.get();
  1215. }
  1216. template<class Allocator>
  1217. inline
  1218. void
  1219. basic_fields<Allocator>::
  1220. move_assign(basic_fields& other, std::false_type)
  1221. {
  1222. clear_all();
  1223. if(this->get() != other.get())
  1224. {
  1225. copy_all(other);
  1226. other.clear_all();
  1227. }
  1228. else
  1229. {
  1230. set_ = std::move(other.set_);
  1231. list_ = std::move(other.list_);
  1232. method_ = other.method_;
  1233. target_or_reason_ = other.target_or_reason_;
  1234. other.method_ = {};
  1235. other.target_or_reason_ = {};
  1236. }
  1237. }
  1238. template<class Allocator>
  1239. inline
  1240. void
  1241. basic_fields<Allocator>::
  1242. copy_assign(basic_fields const& other, std::true_type)
  1243. {
  1244. clear_all();
  1245. this->get() = other.get();
  1246. copy_all(other);
  1247. }
  1248. template<class Allocator>
  1249. inline
  1250. void
  1251. basic_fields<Allocator>::
  1252. copy_assign(basic_fields const& other, std::false_type)
  1253. {
  1254. clear_all();
  1255. copy_all(other);
  1256. }
  1257. template<class Allocator>
  1258. inline
  1259. void
  1260. basic_fields<Allocator>::
  1261. swap(basic_fields& other, std::true_type)
  1262. {
  1263. using std::swap;
  1264. swap(this->get(), other.get());
  1265. swap(set_, other.set_);
  1266. swap(list_, other.list_);
  1267. swap(method_, other.method_);
  1268. swap(target_or_reason_, other.target_or_reason_);
  1269. }
  1270. template<class Allocator>
  1271. inline
  1272. void
  1273. basic_fields<Allocator>::
  1274. swap(basic_fields& other, std::false_type)
  1275. {
  1276. BOOST_ASSERT(this->get() == other.get());
  1277. using std::swap;
  1278. swap(set_, other.set_);
  1279. swap(list_, other.list_);
  1280. swap(method_, other.method_);
  1281. swap(target_or_reason_, other.target_or_reason_);
  1282. }
  1283. } // http
  1284. } // beast
  1285. } // boost
  1286. #endif