Files
boost_beast/include/beast/http/fields.hpp

353 lines
8.4 KiB
C++
Raw Normal View History

2017-07-20 08:01:46 -07:00
//
2017-02-06 20:07:03 -05:00
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
2017-07-20 08:01:46 -07:00
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_FIELDS_HPP
#define BEAST_HTTP_FIELDS_HPP
2017-07-20 08:01:46 -07:00
#include <beast/config.hpp>
2017-05-05 14:45:15 -07:00
#include <beast/core/string_view.hpp>
#include <beast/core/detail/empty_base_optimization.hpp>
#include <beast/http/detail/fields.hpp>
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <cctype>
2017-07-20 08:01:46 -07:00
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
2017-07-20 08:01:46 -07:00
namespace beast {
namespace http {
/** A container for storing HTTP header fields.
This container is designed to store the field value pairs that make
up the fields and trailers in a HTTP message. Objects of this type
are iterable, with each element holding the field name and field
value.
Field names are stored as-is, but comparisons are case-insensitive.
When the container is iterated, the fields are presented in the order
of insertion. For fields with the same name, the container behaves
as a `std::multiset`; there will be a separate value for each occurrence
of the field name.
@note Meets the requirements of @b FieldSequence.
*/
template<class Allocator>
class basic_fields :
#if ! BEAST_DOXYGEN
private beast::detail::empty_base_optimization<
typename std::allocator_traits<Allocator>::
template rebind_alloc<
detail::basic_fields_base::element>>,
#endif
public detail::basic_fields_base
{
using alloc_type = typename
std::allocator_traits<Allocator>::
template rebind_alloc<
detail::basic_fields_base::element>;
using alloc_traits =
std::allocator_traits<alloc_type>;
using size_type =
typename std::allocator_traits<Allocator>::size_type;
void
delete_all();
void
move_assign(basic_fields&, std::false_type);
void
move_assign(basic_fields&, std::true_type);
void
copy_assign(basic_fields const&, std::false_type);
void
copy_assign(basic_fields const&, std::true_type);
template<class FieldSequence>
void
copy_from(FieldSequence const& fs)
{
for(auto const& e : fs)
insert(e.first, e.second);
}
public:
/// The type of allocator used.
using allocator_type = Allocator;
/** The value type of the field sequence.
Meets the requirements of @b Field.
*/
#if BEAST_DOXYGEN
using value_type = implementation_defined;
#endif
/// A const iterator to the field sequence
#if BEAST_DOXYGEN
using iterator = implementation_defined;
#endif
/// A const iterator to the field sequence
#if BEAST_DOXYGEN
using const_iterator = implementation_defined;
#endif
/// Default constructor.
basic_fields() = default;
/// Destructor
~basic_fields();
/** Construct the fields.
@param alloc The allocator to use.
*/
explicit
basic_fields(Allocator const& alloc);
/** Move constructor.
The moved-from object becomes an empty field sequence.
@param other The object to move from.
*/
basic_fields(basic_fields&& other);
/** Move assignment.
The moved-from object becomes an empty field sequence.
@param other The object to move from.
*/
basic_fields& operator=(basic_fields&& other);
/// Copy constructor.
basic_fields(basic_fields const&);
/// Copy assignment.
basic_fields& operator=(basic_fields const&);
/// Copy constructor.
template<class OtherAlloc>
basic_fields(basic_fields<OtherAlloc> const&);
/// Copy assignment.
template<class OtherAlloc>
basic_fields& operator=(basic_fields<OtherAlloc> const&);
/// Construct from a field sequence.
template<class FwdIt>
basic_fields(FwdIt first, FwdIt last);
/// Returns `true` if the field sequence contains no elements.
bool
empty() const
{
return set_.empty();
}
/// Returns the number of elements in the field sequence.
std::size_t
size() const
{
return set_.size();
}
/// Returns a const iterator to the beginning of the field sequence.
const_iterator
begin() const
{
return list_.cbegin();
}
/// Returns a const iterator to the end of the field sequence.
const_iterator
end() const
{
return list_.cend();
}
/// Returns a const iterator to the beginning of the field sequence.
const_iterator
cbegin() const
{
return list_.cbegin();
}
/// Returns a const iterator to the end of the field sequence.
const_iterator
cend() const
{
return list_.cend();
}
/// Returns `true` if the specified field exists.
bool
2017-05-05 14:45:15 -07:00
exists(string_view const& name) const
{
return set_.find(name, less{}) != set_.end();
}
/// Returns the number of values for the specified field.
std::size_t
2017-05-05 14:45:15 -07:00
count(string_view const& name) const;
/** Returns an iterator to the case-insensitive matching field name.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
iterator
2017-05-05 14:45:15 -07:00
find(string_view const& name) const;
/** Returns the value for a case-insensitive matching header, or `""`.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
2017-05-05 14:45:15 -07:00
string_view const
operator[](string_view const& name) const;
/// Clear the contents of the basic_fields.
void
clear() noexcept;
/** Remove a field.
If more than one field with the specified name exists, all
matching fields will be removed.
@param name The name of the field(s) to remove.
@return The number of fields removed.
*/
std::size_t
2017-05-05 14:45:15 -07:00
erase(string_view const& name);
/** Insert a field value.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field.
@param value A string holding the value of the field.
*/
void
2017-05-05 14:45:15 -07:00
insert(string_view const& name, string_view value);
/** Insert a field value.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<
2017-05-05 14:45:15 -07:00
! std::is_constructible<string_view, T>::value>::type
insert(string_view name, T const& value)
{
insert(name, boost::lexical_cast<std::string>(value));
}
/** Replace a field value.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field.
@param value A string holding the value of the field.
*/
void
2017-05-05 14:45:15 -07:00
replace(string_view const& name, string_view value);
/** Replace a field value.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<
2017-05-05 14:45:15 -07:00
! std::is_constructible<string_view, T>::value>::type
replace(string_view const& name, T const& value)
{
replace(name,
boost::lexical_cast<std::string>(value));
}
#if BEAST_DOXYGEN
private:
#endif
2017-05-05 14:45:15 -07:00
string_view
method() const
{
return (*this)[":method"];
}
void
2017-05-05 14:45:15 -07:00
method(string_view const& s)
{
return this->replace(":method", s);
}
2017-05-05 14:45:15 -07:00
string_view
target() const
{
return (*this)[":target"];
}
void
2017-05-05 14:45:15 -07:00
target(string_view const& s)
{
return this->replace(":target", s);
}
2017-05-05 14:45:15 -07:00
string_view
reason() const
{
return (*this)[":reason"];
}
void
2017-05-05 14:45:15 -07:00
reason(string_view const& s)
{
return this->replace(":reason", s);
}
};
/// A typical HTTP header fields container
using fields =
basic_fields<std::allocator<char>>;
2017-07-20 08:01:46 -07:00
} // http
} // beast
#include <beast/http/impl/fields.ipp>
2017-07-20 08:01:46 -07:00
#endif