LCOV - code coverage report
Current view: top level - boost/http_proto - fields_base.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 23 23 100.0 %
Date: 2024-03-08 19:26:15 Functions: 7 7 100.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.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_FIELDS_BASE_HPP
      11             : #define BOOST_HTTP_PROTO_FIELDS_BASE_HPP
      12             : 
      13             : #include <boost/http_proto/detail/config.hpp>
      14             : #include <boost/http_proto/fields_view_base.hpp>
      15             : #include <boost/core/detail/string_view.hpp>
      16             : #include <boost/system/result.hpp>
      17             : 
      18             : namespace boost {
      19             : namespace http_proto {
      20             : 
      21             : namespace detail {
      22             : struct prefix_op;
      23             : } // detail
      24             : 
      25             : /** Mixin for modifiable HTTP fields
      26             : 
      27             :     @par Iterators
      28             : 
      29             :     Iterators obtained from @ref fields
      30             :     containers are not invalidated when
      31             :     the underlying container is modified.
      32             : 
      33             :     @note HTTP field names are case-insensitive.
      34             : */
      35             : class BOOST_SYMBOL_VISIBLE
      36             :     fields_base
      37             :     : public virtual fields_view_base
      38             : {
      39             :     detail::header h_;
      40             : 
      41             :     class op_t;
      42             :     using entry =
      43             :         detail::header::entry;
      44             :     using table =
      45             :         detail::header::table;
      46             : 
      47             :     friend class fields;
      48             :     friend class request;
      49             :     friend class response;
      50             :     friend class serializer;
      51             :     friend class message_base;
      52             :     friend struct detail::header;
      53             :     friend struct detail::prefix_op;
      54             : 
      55             :     BOOST_HTTP_PROTO_DECL
      56             :     explicit
      57             :     fields_base(
      58             :         detail::kind) noexcept;
      59             : 
      60             :     BOOST_HTTP_PROTO_DECL
      61             :     fields_base(
      62             :         detail::kind,
      63             :         core::string_view);
      64             : 
      65             :     fields_base(detail::header const&);
      66             : 
      67             : public:
      68             :     /** Destructor
      69             :     */
      70             :     BOOST_HTTP_PROTO_DECL
      71             :     ~fields_base();
      72             : 
      73             :     //--------------------------------------------
      74             :     //
      75             :     // Capacity
      76             :     //
      77             :     //--------------------------------------------
      78             : 
      79             :     /** Returns the largest permissible capacity in bytes
      80             :     */
      81             :     static
      82             :     constexpr
      83             :     std::size_t
      84         718 :     max_capacity_in_bytes() noexcept
      85             :     {
      86             :         using T = detail::header::entry;
      87             :         return alignof(T) *
      88             :             (((max_offset - 2 + sizeof(T) * (
      89             :                     max_offset / 4)) +
      90             :                 alignof(T) - 1) /
      91         718 :             alignof(T));
      92             :     }
      93             : 
      94             :     /** Returns the total number of bytes allocated by the container
      95             :     */
      96             :     std::size_t
      97          61 :     capacity_in_bytes() const noexcept
      98             :     {
      99          61 :         return h_.cap;
     100             :     }
     101             : 
     102             :     /** Clear the contents, but not the capacity
     103             :     */
     104             :     BOOST_HTTP_PROTO_DECL
     105             :     void
     106             :     clear() noexcept;
     107             : 
     108             :     /** Reserve a minimum capacity
     109             :     */
     110             :     BOOST_HTTP_PROTO_DECL
     111             :     void
     112             :     reserve_bytes(std::size_t n);
     113             : 
     114             :     /** Remove excess capacity
     115             :     */
     116             :     BOOST_HTTP_PROTO_DECL
     117             :     void
     118             :     shrink_to_fit() noexcept;
     119             : 
     120             :     //--------------------------------------------
     121             :     //
     122             :     // Modifiers
     123             :     //
     124             :     //--------------------------------------------
     125             : 
     126             :     /** Append a header
     127             : 
     128             :         This function appends a new header with the
     129             :         specified id and value. The value must be
     130             :         syntactically valid or else an error is returned.
     131             :         Any leading or trailing whitespace in the new value
     132             :         is ignored.
     133             :         <br/>
     134             :         No iterators are invalidated.
     135             : 
     136             :         @par Example
     137             :         @code
     138             :         request req;
     139             : 
     140             :         req.append( field::user_agent, "Boost" );
     141             :         @endcode
     142             : 
     143             :         @par Complexity
     144             :         Linear in `to_string( id ).size() + value.size()`.
     145             : 
     146             :         @par Exception Safety
     147             :         Strong guarantee.
     148             :         Calls to allocate may throw.
     149             : 
     150             :         @param id The field name constant,
     151             :         which may not be @ref field::unknown.
     152             : 
     153             :         @param value A value, which must be semantically
     154             :         valid for the message.
     155             : 
     156             :         @return The error, if any occurred.
     157             :     */
     158             :     system::result<void>
     159          21 :     append(
     160             :         field id,
     161             :         core::string_view value)
     162             :     {
     163          21 :         BOOST_ASSERT(
     164             :             id != field::unknown);
     165             :         return insert_impl(
     166          21 :             id, to_string(id), value, h_.count);
     167             :     }
     168             : 
     169             :     /** Append a header
     170             : 
     171             :         This function appends a new header with the
     172             :         specified name and value. Both values must be
     173             :         syntactically valid or else an error is returned.
     174             :         Any leading or trailing whitespace in the new
     175             :         value is ignored.
     176             :         <br/>
     177             :         No iterators are invalidated.
     178             : 
     179             :         @par Example
     180             :         @code
     181             :         request req;
     182             : 
     183             :         req.append( "User-Agent", "Boost" );
     184             :         @endcode
     185             : 
     186             :         @par Complexity
     187             :         Linear in `name.size() + value.size()`.
     188             : 
     189             :         @par Exception Safety
     190             :         Strong guarantee.
     191             :         Calls to allocate may throw.
     192             : 
     193             :         @param name The header name.
     194             : 
     195             :         @param value A value, which must be semantically
     196             :         valid for the message.
     197             : 
     198             :         @return The error, if any occurred.
     199             :     */
     200             :     system::result<void>
     201          55 :     append(
     202             :         core::string_view name,
     203             :         core::string_view value)
     204             :     {
     205             :         return insert_impl(
     206             :             string_to_field(
     207             :                 name),
     208             :             name,
     209             :             value,
     210          55 :             h_.count);
     211             :     }
     212             : 
     213             :     /** Insert a header
     214             : 
     215             :         If a matching header with the same name
     216             :         exists, it is not replaced. Instead, an
     217             :         additional header with the same name is
     218             :         inserted. Names are not case-sensitive.
     219             :         Any leading or trailing whitespace in
     220             :         the new value is ignored.
     221             :         <br>
     222             :         All iterators that are equal to `before`
     223             :         or come after are invalidated.
     224             : 
     225             :         @par Example
     226             :         @code
     227             :         request req;
     228             : 
     229             :         req.insert( req.begin(), field::user_agent, "Boost" );
     230             :         @endcode
     231             : 
     232             :         @par Complexity
     233             :         Linear in `to_string( id ).size() + value.size()`.
     234             : 
     235             :         @par Exception Safety
     236             :         Strong guarantee.
     237             :         Calls to allocate may throw.
     238             : 
     239             :         @return An iterator the newly inserted header, or
     240             :         an error if any occurred.
     241             : 
     242             :         @param before Position to insert before.
     243             : 
     244             :         @param id The field name constant,
     245             :         which may not be @ref field::unknown.
     246             : 
     247             :         @param value A value, which must be semantically
     248             :         valid for the message.
     249             :     */
     250             :     system::result<iterator>
     251           7 :     insert(
     252             :         iterator before,
     253             :         field id,
     254             :         core::string_view value)
     255             :     {
     256             :         // TODO: this should probably return an error
     257           7 :         BOOST_ASSERT(
     258             :             id != field::unknown);
     259             : 
     260             :         auto rv = insert_impl(
     261           7 :             id, to_string(id), value, before.i_);
     262             : 
     263           7 :         if( rv.has_error() )
     264           1 :             return rv.error();
     265           6 :         return before;
     266             :     }
     267             : 
     268             :     /** Insert a header
     269             : 
     270             :         If a matching header with the same name
     271             :         exists, it is not replaced. Instead, an
     272             :         additional header with the same name is
     273             :         inserted. Names are not case-sensitive.
     274             :         Any leading or trailing whitespace in
     275             :         the new value is ignored.
     276             :         <br>
     277             :         All iterators that are equal to `before`
     278             :         or come after are invalidated.
     279             : 
     280             :         @par Example
     281             :         @code
     282             :         request req;
     283             : 
     284             :         req.insert( req.begin(), "User-Agent", "Boost" );
     285             :         @endcode
     286             : 
     287             :         @par Complexity
     288             :         Linear in `name.size() + value.size()`.
     289             : 
     290             :         @par Exception Safety
     291             :         Strong guarantee.
     292             :         Calls to allocate may throw.
     293             : 
     294             :         @return An iterator the newly inserted header, or
     295             :         an error if any occurred.
     296             : 
     297             :         @param before Position to insert before.
     298             : 
     299             :         @param name The header name.
     300             : 
     301             :         @param value A value, which must be semantically
     302             :         valid for the message.
     303             :     */
     304             :     system::result<iterator>
     305          15 :     insert(
     306             :         iterator before,
     307             :         core::string_view name,
     308             :         core::string_view value)
     309             :     {
     310             :         auto rv = insert_impl(
     311             :             string_to_field(
     312             :                 name),
     313             :             name,
     314             :             value,
     315          15 :             before.i_);
     316             : 
     317          15 :         if( rv.has_error() )
     318           3 :             return rv.error();
     319          12 :         return before;
     320             :     }
     321             : 
     322             :     //--------------------------------------------
     323             : 
     324             :     /** Erase headers
     325             : 
     326             :         This function removes the header pointed
     327             :         to by `it`.
     328             :         <br>
     329             :         All iterators that are equal to `it`
     330             :         or come after are invalidated.
     331             : 
     332             :         @par Complexity
     333             :         Linear in `name.size() + value.size()`.
     334             : 
     335             :         @par Exception Safety
     336             :         Throws nothing.
     337             : 
     338             :         @return An iterator to the inserted
     339             :         element.
     340             : 
     341             :         @param it An iterator to the element
     342             :         to erase.
     343             :     */
     344             :     iterator
     345          31 :     erase(iterator it) noexcept
     346             :     {
     347          31 :         erase_impl(it.i_, it->id);
     348          31 :         return it;
     349             :     }
     350             : 
     351             :     /** Erase headers
     352             : 
     353             :         This removes all headers whose name
     354             :         constant is equal to `id`.
     355             :         <br>
     356             :         If any headers are erased, then all
     357             :         iterators equal to or that come after
     358             :         the first erased element are invalidated.
     359             :         Otherwise, no iterators are invalidated.
     360             : 
     361             :         @par Complexity
     362             :         Linear in `this->string().size()`.
     363             : 
     364             :         @par Exception Safety
     365             :         Throws nothing.
     366             : 
     367             :         @return The number of headers erased.
     368             : 
     369             :         @param id The field name constant,
     370             :         which may not be @ref field::unknown.
     371             :     */
     372             :     BOOST_HTTP_PROTO_DECL
     373             :     std::size_t
     374             :     erase(field id) noexcept;
     375             : 
     376             :     /** Erase all matching fields
     377             : 
     378             :         This removes all headers with a matching
     379             :         name, using a case-insensitive comparison.
     380             :         <br>
     381             :         If any headers are erased, then all
     382             :         iterators equal to or that come after
     383             :         the first erased element are invalidated.
     384             :         Otherwise, no iterators are invalidated.
     385             : 
     386             :         @par Complexity
     387             :         Linear in `this->string().size()`.
     388             : 
     389             :         @par Exception Safety
     390             :         Throws nothing.
     391             : 
     392             :         @return The number of fields erased
     393             : 
     394             :         @param name The header name.
     395             :     */
     396             :     BOOST_HTTP_PROTO_DECL
     397             :     std::size_t
     398             :     erase(
     399             :         core::string_view name) noexcept;
     400             : 
     401             :     //--------------------------------------------
     402             : 
     403             :     /** Set a header value
     404             : 
     405             :         Uses the given value to overwrite the
     406             :         current one in the header field pointed to by the
     407             :         iterator. The value must be syntactically
     408             :         valid or else an error is returned.
     409             :         Any leading or trailing whitespace in the new value
     410             :         is ignored.
     411             : 
     412             :         @par Complexity
     413             : 
     414             :         @par Exception Safety
     415             :         Strong guarantee.
     416             :         Calls to allocate may throw.
     417             : 
     418             :         @return The error, if any occurred.
     419             : 
     420             :         @param it An iterator to the header.
     421             : 
     422             :         @param value A value, which must be semantically
     423             :         valid for the message.
     424             :     */
     425             :     BOOST_HTTP_PROTO_DECL
     426             :     system::result<void>
     427             :     set(
     428             :         iterator it,
     429             :         core::string_view value);
     430             : 
     431             :     /** Set a header value
     432             : 
     433             :         The container is modified to contain exactly
     434             :         one field with the specified id set to the given value,
     435             :         which must be syntactically valid or else an error is
     436             :         returned.
     437             :         Any leading or trailing whitespace in the new value
     438             :         is ignored.
     439             : 
     440             :         @par Postconditions
     441             :         @code
     442             :         this->count( id ) == 1 && this->at( id ) == value
     443             :         @endcode
     444             : 
     445             :         @par Complexity
     446             : 
     447             :         @return The error, if any occurred.
     448             : 
     449             :         @param id The field constant of the
     450             :         header to set.
     451             : 
     452             :         @param value A value, which must be semantically
     453             :         valid for the message.
     454             :     */
     455             :     BOOST_HTTP_PROTO_DECL
     456             :     system::result<void>
     457             :     set(
     458             :         field id,
     459             :         core::string_view value);
     460             : 
     461             :     /** Set a header value
     462             : 
     463             :         The container is modified to contain exactly
     464             :         one field with the specified name set to the given value,
     465             :         which must be syntactically valid or else an error is
     466             :         returned.
     467             :         Any leading or trailing whitespace in the new value
     468             :         is ignored.
     469             : 
     470             :         @par Postconditions
     471             :         @code
     472             :         this->count( name ) == 1 && this->at( name ) == value
     473             :         @endcode
     474             : 
     475             :         @return The error, if any occurred.
     476             : 
     477             :         @param name The field name.
     478             : 
     479             :         @param value A value, which must be semantically
     480             :         valid for the message.
     481             :     */
     482             :     BOOST_HTTP_PROTO_DECL
     483             :     system::result<void>
     484             :     set(
     485             :         core::string_view name,
     486             :         core::string_view value);
     487             : 
     488             :     //--------------------------------------------
     489             : 
     490             : private:
     491             :     BOOST_HTTP_PROTO_DECL
     492             :     void
     493             :     copy_impl(
     494             :         detail::header const&);
     495             : 
     496             :     void
     497             :     insert_impl_unchecked(
     498             :         field id,
     499             :         core::string_view name,
     500             :         core::string_view value,
     501             :         std::size_t before,
     502             :         bool has_obs_fold);
     503             : 
     504             :     BOOST_HTTP_PROTO_DECL
     505             :     system::result<void>
     506             :     insert_impl(
     507             :         field id,
     508             :         core::string_view name,
     509             :         core::string_view value,
     510             :         std::size_t before);
     511             : 
     512             :     BOOST_HTTP_PROTO_DECL
     513             :     void
     514             :     erase_impl(
     515             :         std::size_t i,
     516             :         field id) noexcept;
     517             : 
     518             :     void raw_erase(
     519             :         std::size_t) noexcept;
     520             : 
     521             :     std::size_t
     522             :     erase_all_impl(
     523             :         std::size_t i0,
     524             :         field id) noexcept;
     525             : 
     526             :     std::size_t
     527             :     offset(
     528             :         std::size_t i) const noexcept;
     529             : 
     530             :     std::size_t
     531             :     length(
     532             :         std::size_t i) const noexcept;
     533             : 
     534             :     void raw_erase_n(field, std::size_t) noexcept;
     535             : };
     536             : 
     537             : //------------------------------------------------
     538             : 
     539             : #ifndef BOOST_HTTP_PROTO_DOCS
     540             : namespace detail {
     541             : inline
     542             : header&
     543             : header::
     544             : get(fields_base& f) noexcept
     545             : {
     546             :     return f.h_;
     547             : }
     548             : } // detail
     549             : #endif
     550             : 
     551             : } // http_proto
     552             : } // boost
     553             : 
     554             : #endif

Generated by: LCOV version 1.15