LCOV - code coverage report
Current view: top level - http_proto/impl - message_base.ipp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 99 116 85.3 %
Date: 2023-01-15 07:18:31 Functions: 3 6 50.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2021 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/CPPAlliance/http_proto
       8             : //
       9             : 
      10             : #ifndef BOOST_HTTP_PROTO_IMPL_MESSAGE_BASE_IPP
      11             : #define BOOST_HTTP_PROTO_IMPL_MESSAGE_BASE_IPP
      12             : 
      13             : #include <boost/http_proto/message_base.hpp>
      14             : 
      15             : namespace boost {
      16             : namespace http_proto {
      17             : 
      18             : void
      19           0 : message_base::
      20             : set_payload_size(
      21             :     std::uint64_t n)
      22             : {
      23             :     //if(! is_head_response())
      24             :     if(true)
      25             :     {
      26             :         // comes first for exception safety
      27           0 :         set_content_length(n);
      28             : 
      29           0 :         set_chunked(false);
      30             :     }
      31             :     else
      32             :     {
      33             :         // VFALCO ?
      34             :     }
      35           0 : }
      36             : 
      37             : void
      38           0 : message_base::
      39             : set_content_length(
      40             :     std::uint64_t n)
      41             : {
      42           0 :     set(field::content_length,
      43           0 :         detail::number_string(n));
      44           0 : }
      45             : 
      46             : void
      47           0 : message_base::
      48             : set_chunked(bool value)
      49             : {
      50           0 :     if(value)
      51             :     {
      52             :         // set chunked
      53           0 :         if(! h_.md.transfer_encoding.is_chunked )
      54             :         {
      55           0 :             append(
      56             :                 field::transfer_encoding,
      57             :                 "chunked");
      58           0 :             return;
      59             :         }
      60             :     }
      61             :     else
      62             :     {
      63             :         // clear chunked
      64             :         // VFALCO ?
      65             :     }
      66             : }
      67             : 
      68             : void
      69          12 : message_base::
      70             : set_keep_alive(bool value)
      71             : {
      72          12 :     if(ph_->md.connection.ec.failed())
      73             :     {
      74             :         // throw? return false?
      75           5 :         return;
      76             :     }
      77             : 
      78          12 :     if(ph_->md.connection.count == 0)
      79             :     {
      80             :         // no Connection field
      81           5 :         switch(ph_->version)
      82             :         {
      83           3 :         default:
      84             :         case version::http_1_1:
      85           3 :             if(! value)
      86           2 :                 set(field::connection, "close");
      87           3 :             break;
      88             : 
      89           2 :         case version::http_1_0:
      90           2 :             if(value)
      91           1 :                 set(field::connection, "keep-alive");
      92           2 :             break;
      93             :         }
      94           5 :         return;
      95             :     }
      96             : 
      97             :     // VFALCO TODO iterate in reverse order,
      98             :     // and cache the last iterator to use
      99             :     // for appending
     100             : 
     101             :     // one or more Connection fields
     102           7 :     auto it = begin();
     103             :     auto const erase_token =
     104          14 :         [&](string_view token)
     105             :         {
     106          14 :             while(it != end())
     107             :             {
     108           8 :                 if(it->id != field::connection)
     109             :                 {
     110           0 :                     ++it;
     111           4 :                     continue;
     112             :                 }
     113             :                 auto rv = grammar::parse(
     114           8 :                     it->value,
     115          16 :                     list_rule(token_rule, 1));
     116           8 :                 BOOST_ASSERT(! rv.has_error());
     117           8 :                 BOOST_ASSERT(! rv->empty());
     118           8 :                 auto itv = rv->begin();
     119           8 :                 if(urls::grammar::ci_is_equal(
     120           8 :                     *itv, token))
     121             :                 {
     122           4 :                     if(rv->size() == 1)
     123             :                     {
     124             :                         // only one token
     125           3 :                         it = erase(it);
     126             :                     }
     127             :                     else
     128             :                     {
     129             :                         // first token matches
     130           1 :                         ++itv;
     131           1 :                         set(it,
     132           1 :                             it->value.substr(
     133           2 :                                 (*itv).data() -
     134           1 :                                 it->value.data()));
     135           1 :                         ++it;
     136             :                     }
     137           4 :                     continue;
     138             :                 }
     139             :                 // search remaining tokens
     140           8 :                 std::string s = *itv++;
     141           7 :                 while(itv != rv->end())
     142             :                 {
     143           3 :                     if(! urls::grammar::ci_is_equal(
     144           3 :                         *itv, token))
     145           1 :                         s += ", " + std::string(*itv);
     146           3 :                     ++itv;
     147             :                 }
     148           4 :                 set(it, s);
     149           4 :                 ++it;
     150             :             }
     151           6 :         };
     152           7 :     if(value)
     153             :     {
     154           6 :         if(ph_->md.connection.close)
     155           5 :             erase_token("close");
     156             :     }
     157             :     else
     158             :     {
     159           1 :         if(ph_->md.connection.keep_alive)
     160           1 :             erase_token("keep-alive");
     161             :     }
     162           7 :     switch(ph_->version)
     163             :     {
     164           5 :     default:
     165             :     case version::http_1_1:
     166           5 :         if(! value)
     167             :         {
     168             :             // add one "close" token if needed
     169           0 :             if(! ph_->md.connection.close)
     170           0 :                 append(field::connection, "close");
     171             :         }
     172           5 :         break;
     173             : 
     174           2 :     case version::http_1_0:
     175           2 :         if(value)
     176             :         {
     177             :             // add one "keep-alive" token if needed
     178           1 :             if(! ph_->md.connection.keep_alive)
     179           0 :                 append(field::connection, "keep-alive");
     180             :         }
     181           2 :         break;
     182             :     }
     183             : }
     184             : 
     185             : //------------------------------------------------
     186             : 
     187             : char*
     188         266 : message_base::
     189             : set_prefix_impl(
     190             :     std::size_t n)
     191             : {
     192         266 :     if( n > h_.prefix ||
     193         216 :         h_.buf == nullptr)
     194             :     {
     195             :         // allocate or grow
     196         264 :         if( n > h_.prefix &&
     197             :             static_cast<std::size_t>(
     198          50 :                 n - h_.prefix) >
     199          50 :             static_cast<std::size_t>(
     200          50 :                 max_off_t - h_.size))
     201           1 :             detail::throw_length_error(
     202             :                 "too large",
     203           1 :                 BOOST_CURRENT_LOCATION);
     204         263 :         auto n0 = detail::header::bytes_needed(
     205         263 :             n + h_.size - h_.prefix,
     206         263 :             h_.count);
     207         263 :         auto buf = new char[n0];
     208         263 :         if(h_.buf != nullptr)
     209             :         {
     210           3 :             std::memcpy(
     211           3 :                 buf + n,
     212           3 :                 h_.buf + h_.prefix,
     213           3 :                 h_.size - h_.prefix);
     214             :             detail::header::table ft(
     215           3 :                 h_.buf + h_.cap);
     216           3 :             h_.copy_table(buf + n0);
     217           3 :             delete[] h_.buf;
     218             :         }
     219             :         else
     220             :         {
     221         260 :             std::memcpy(
     222         260 :                 buf + n,
     223         260 :                 h_.cbuf + h_.prefix,
     224         260 :                 h_.size - h_.prefix);
     225             :         }
     226         263 :         h_.buf = buf;
     227         263 :         h_.cbuf = buf;
     228         263 :         h_.size = static_cast<
     229         263 :             off_t>(h_.size +
     230         263 :                 n - h_.prefix);
     231         263 :         h_.prefix = static_cast<
     232             :             off_t>(n);
     233         263 :         h_.cap = n0;
     234         263 :         return h_.buf;
     235             :     }
     236             : 
     237             :     // shrink
     238           2 :     std::memmove(
     239           2 :         h_.buf + n,
     240           2 :         h_.buf + h_.prefix,
     241           2 :         h_.size - h_.prefix);
     242           2 :     h_.size = static_cast<
     243           2 :         off_t>(h_.size -
     244           2 :             h_.prefix + n);
     245           2 :     h_.prefix = static_cast<
     246             :         off_t>(n);
     247           2 :     return h_.buf;
     248             : }
     249             : 
     250             : } // http_proto
     251             : } // boost
     252             : 
     253             : #endif

Generated by: LCOV version 1.15