fields.ipp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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_IPP
  10. #define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
  11. #include <boost/beast/http/fields.hpp>
  12. namespace boost {
  13. namespace beast {
  14. namespace http {
  15. namespace detail {
  16. // `basic_fields` assumes that `std::size_t` is larger than `uint16_t`, so we
  17. // verify it explicitly here, so that users that use split compilation don't
  18. // need to pay the (fairly small) price for this sanity check
  19. BOOST_STATIC_ASSERT((std::numeric_limits<std::size_t>::max)() >=
  20. (std::numeric_limits<std::uint32_t>::max)());
  21. // Filter a token list
  22. //
  23. inline
  24. void
  25. filter_token_list(
  26. beast::detail::temporary_buffer& s,
  27. string_view value,
  28. iequals_predicate const& pred)
  29. {
  30. token_list te{value};
  31. auto it = te.begin();
  32. auto last = te.end();
  33. if(it == last)
  34. return;
  35. while(pred(*it))
  36. if(++it == last)
  37. return;
  38. s.append(*it);
  39. while(++it != last)
  40. {
  41. if(! pred(*it))
  42. {
  43. s.append(", ", *it);
  44. }
  45. }
  46. }
  47. void
  48. filter_token_list_last(
  49. beast::detail::temporary_buffer& s,
  50. string_view value,
  51. iequals_predicate const& pred)
  52. {
  53. token_list te{value};
  54. if(te.begin() != te.end())
  55. {
  56. auto it = te.begin();
  57. auto next = std::next(it);
  58. if(next == te.end())
  59. {
  60. if(! pred(*it))
  61. s.append(*it);
  62. return;
  63. }
  64. s.append(*it);
  65. for(;;)
  66. {
  67. it = next;
  68. next = std::next(it);
  69. if(next == te.end())
  70. {
  71. if(! pred(*it))
  72. {
  73. s.append(", ", *it);
  74. }
  75. return;
  76. }
  77. s.append(", ", *it);
  78. }
  79. }
  80. }
  81. void
  82. keep_alive_impl(
  83. beast::detail::temporary_buffer& s, string_view value,
  84. unsigned version, bool keep_alive)
  85. {
  86. if(version < 11)
  87. {
  88. if(keep_alive)
  89. {
  90. // remove close
  91. filter_token_list(s, value, iequals_predicate{"close", {}});
  92. // add keep-alive
  93. if(s.empty())
  94. s.append("keep-alive");
  95. else if(! token_list{value}.exists("keep-alive"))
  96. s.append(", keep-alive");
  97. }
  98. else
  99. {
  100. // remove close and keep-alive
  101. filter_token_list(s, value,
  102. iequals_predicate{"close", "keep-alive"});
  103. }
  104. }
  105. else
  106. {
  107. if(keep_alive)
  108. {
  109. // remove close and keep-alive
  110. filter_token_list(s, value,
  111. iequals_predicate{"close", "keep-alive"});
  112. }
  113. else
  114. {
  115. // remove keep-alive
  116. filter_token_list(s, value, iequals_predicate{"keep-alive", {}});
  117. // add close
  118. if(s.empty())
  119. s.append("close");
  120. else if(! token_list{value}.exists("close"))
  121. s.append(", close");
  122. }
  123. }
  124. }
  125. } // detail
  126. } // http
  127. } // beast
  128. } // boost
  129. #endif // BOOST_BEAST_HTTP_IMPL_FIELDS_IPP