mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Move everything in basic_fields.hpp to fields.hpp (API Change)
fix #320
This commit is contained in:
@ -13,6 +13,7 @@ API Changes:
|
||||
|
||||
* Provide websocket::stream accept() overloads
|
||||
* Refactor websocket decorators
|
||||
* Move everything in basic_fields.hpp to fields.hpp
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include <beast/config.hpp>
|
||||
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
#include <beast/http/basic_parser.hpp>
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/error.hpp>
|
||||
|
@ -1,307 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// 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_BASIC_FIELDS_HPP
|
||||
#define BEAST_HTTP_BASIC_FIELDS_HPP
|
||||
|
||||
#include <beast/config.hpp>
|
||||
#include <beast/core/detail/empty_base_optimization.hpp>
|
||||
#include <beast/http/detail/basic_fields.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
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
|
||||
exists(boost::string_ref const& name) const
|
||||
{
|
||||
return set_.find(name, less{}) != set_.end();
|
||||
}
|
||||
|
||||
/// Returns the number of values for the specified field.
|
||||
std::size_t
|
||||
count(boost::string_ref 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
|
||||
find(boost::string_ref 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.
|
||||
*/
|
||||
boost::string_ref
|
||||
operator[](boost::string_ref 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
|
||||
erase(boost::string_ref 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
|
||||
insert(boost::string_ref const& name, boost::string_ref 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<
|
||||
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||
insert(boost::string_ref 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
|
||||
replace(boost::string_ref const& name, boost::string_ref 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<
|
||||
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||
replace(boost::string_ref const& name, T const& value)
|
||||
{
|
||||
replace(name,
|
||||
boost::lexical_cast<std::string>(value));
|
||||
}
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#include <beast/http/impl/basic_fields.ipp>
|
||||
|
||||
#endif
|
@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_DETAIL_BASIC_FIELDS_HPP
|
||||
#define BEAST_HTTP_DETAIL_BASIC_FIELDS_HPP
|
||||
#ifndef BEAST_HTTP_DETAIL_FIELDS_HPP
|
||||
#define BEAST_HTTP_DETAIL_FIELDS_HPP
|
||||
|
||||
#include <beast/core/detail/ci_char_traits.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
@ -9,12 +9,296 @@
|
||||
#define BEAST_HTTP_FIELDS_HPP
|
||||
|
||||
#include <beast/config.hpp>
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
#include <beast/core/detail/empty_base_optimization.hpp>
|
||||
#include <beast/http/detail/fields.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
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
|
||||
exists(boost::string_ref const& name) const
|
||||
{
|
||||
return set_.find(name, less{}) != set_.end();
|
||||
}
|
||||
|
||||
/// Returns the number of values for the specified field.
|
||||
std::size_t
|
||||
count(boost::string_ref 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
|
||||
find(boost::string_ref 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.
|
||||
*/
|
||||
boost::string_ref
|
||||
operator[](boost::string_ref 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
|
||||
erase(boost::string_ref 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
|
||||
insert(boost::string_ref const& name, boost::string_ref 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<
|
||||
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||
insert(boost::string_ref 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
|
||||
replace(boost::string_ref const& name, boost::string_ref 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<
|
||||
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||
replace(boost::string_ref const& name, T const& value)
|
||||
{
|
||||
replace(name,
|
||||
boost::lexical_cast<std::string>(value));
|
||||
}
|
||||
};
|
||||
|
||||
/// A typical HTTP header fields container
|
||||
using fields =
|
||||
basic_fields<std::allocator<char>>;
|
||||
@ -22,4 +306,6 @@ using fields =
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#include <beast/http/impl/fields.ipp>
|
||||
|
||||
#endif
|
||||
|
@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_FIELDS_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_FIELDS_IPP
|
||||
#ifndef BEAST_HTTP_IMPL_FIELDS_IPP
|
||||
#define BEAST_HTTP_IMPL_FIELDS_IPP
|
||||
|
||||
#include <beast/http/detail/rfc7230.hpp>
|
||||
#include <algorithm>
|
@ -48,7 +48,6 @@ unit-test core-tests :
|
||||
unit-test http-tests :
|
||||
../extras/beast/unit_test/main.cpp
|
||||
http/basic_dynabuf_body.cpp
|
||||
http/basic_fields.cpp
|
||||
http/basic_parser.cpp
|
||||
http/concepts.cpp
|
||||
http/design.cpp
|
||||
|
@ -11,7 +11,6 @@ add_executable (http-tests
|
||||
test_parser.hpp
|
||||
../../extras/beast/unit_test/main.cpp
|
||||
basic_dynabuf_body.cpp
|
||||
basic_fields.cpp
|
||||
basic_parser.cpp
|
||||
concepts.cpp
|
||||
design.cpp
|
||||
|
@ -1,96 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class basic_fields_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class Allocator>
|
||||
using bha = basic_fields<Allocator>;
|
||||
|
||||
using bh = basic_fields<std::allocator<char>>;
|
||||
|
||||
template<class Allocator>
|
||||
static
|
||||
void
|
||||
fill(std::size_t n, basic_fields<Allocator>& h)
|
||||
{
|
||||
for(std::size_t i = 1; i<= n; ++i)
|
||||
h.insert(boost::lexical_cast<std::string>(i), i);
|
||||
}
|
||||
|
||||
template<class U, class V>
|
||||
static
|
||||
void
|
||||
self_assign(U& u, V&& v)
|
||||
{
|
||||
u = std::forward<V>(v);
|
||||
}
|
||||
|
||||
void testHeaders()
|
||||
{
|
||||
bh h1;
|
||||
BEAST_EXPECT(h1.empty());
|
||||
fill(1, h1);
|
||||
BEAST_EXPECT(h1.size() == 1);
|
||||
bh h2;
|
||||
h2 = h1;
|
||||
BEAST_EXPECT(h2.size() == 1);
|
||||
h2.insert("2", "2");
|
||||
BEAST_EXPECT(std::distance(h2.begin(), h2.end()) == 2);
|
||||
h1 = std::move(h2);
|
||||
BEAST_EXPECT(h1.size() == 2);
|
||||
BEAST_EXPECT(h2.size() == 0);
|
||||
bh h3(std::move(h1));
|
||||
BEAST_EXPECT(h3.size() == 2);
|
||||
BEAST_EXPECT(h1.size() == 0);
|
||||
self_assign(h3, std::move(h3));
|
||||
BEAST_EXPECT(h3.size() == 2);
|
||||
BEAST_EXPECT(h2.erase("Not-Present") == 0);
|
||||
}
|
||||
|
||||
void testRFC2616()
|
||||
{
|
||||
bh h;
|
||||
h.insert("a", "w");
|
||||
h.insert("a", "x");
|
||||
h.insert("aa", "y");
|
||||
h.insert("b", "z");
|
||||
BEAST_EXPECT(h.count("a") == 2);
|
||||
}
|
||||
|
||||
void testErase()
|
||||
{
|
||||
bh h;
|
||||
h.insert("a", "w");
|
||||
h.insert("a", "x");
|
||||
h.insert("aa", "y");
|
||||
h.insert("b", "z");
|
||||
BEAST_EXPECT(h.size() == 4);
|
||||
h.erase("a");
|
||||
BEAST_EXPECT(h.size() == 2);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testHeaders();
|
||||
testRFC2616();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_fields,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
@ -7,3 +7,90 @@
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/fields.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class basic_fields_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class Allocator>
|
||||
using bha = basic_fields<Allocator>;
|
||||
|
||||
using bh = basic_fields<std::allocator<char>>;
|
||||
|
||||
template<class Allocator>
|
||||
static
|
||||
void
|
||||
fill(std::size_t n, basic_fields<Allocator>& h)
|
||||
{
|
||||
for(std::size_t i = 1; i<= n; ++i)
|
||||
h.insert(boost::lexical_cast<std::string>(i), i);
|
||||
}
|
||||
|
||||
template<class U, class V>
|
||||
static
|
||||
void
|
||||
self_assign(U& u, V&& v)
|
||||
{
|
||||
u = std::forward<V>(v);
|
||||
}
|
||||
|
||||
void testHeaders()
|
||||
{
|
||||
bh h1;
|
||||
BEAST_EXPECT(h1.empty());
|
||||
fill(1, h1);
|
||||
BEAST_EXPECT(h1.size() == 1);
|
||||
bh h2;
|
||||
h2 = h1;
|
||||
BEAST_EXPECT(h2.size() == 1);
|
||||
h2.insert("2", "2");
|
||||
BEAST_EXPECT(std::distance(h2.begin(), h2.end()) == 2);
|
||||
h1 = std::move(h2);
|
||||
BEAST_EXPECT(h1.size() == 2);
|
||||
BEAST_EXPECT(h2.size() == 0);
|
||||
bh h3(std::move(h1));
|
||||
BEAST_EXPECT(h3.size() == 2);
|
||||
BEAST_EXPECT(h1.size() == 0);
|
||||
self_assign(h3, std::move(h3));
|
||||
BEAST_EXPECT(h3.size() == 2);
|
||||
BEAST_EXPECT(h2.erase("Not-Present") == 0);
|
||||
}
|
||||
|
||||
void testRFC2616()
|
||||
{
|
||||
bh h;
|
||||
h.insert("a", "w");
|
||||
h.insert("a", "x");
|
||||
h.insert("aa", "y");
|
||||
h.insert("b", "z");
|
||||
BEAST_EXPECT(h.count("a") == 2);
|
||||
}
|
||||
|
||||
void testErase()
|
||||
{
|
||||
bh h;
|
||||
h.insert("a", "w");
|
||||
h.insert("a", "x");
|
||||
h.insert("aa", "y");
|
||||
h.insert("b", "z");
|
||||
BEAST_EXPECT(h.size() == 4);
|
||||
h.erase("a");
|
||||
BEAST_EXPECT(h.size() == 2);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testHeaders();
|
||||
testRFC2616();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_fields,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
Reference in New Issue
Block a user