mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 10:35:50 +00:00
Beast documentation work
This commit is contained in:
5
TODO.txt
5
TODO.txt
@@ -17,3 +17,8 @@
|
||||
* Remove or change http::headers alias
|
||||
* Do something about the methods.hpp and fields.hpp type headers
|
||||
* Fix index in docs
|
||||
* Fix integer warning in file_body.hpp
|
||||
* Use make_error_code in websocket to set the category right
|
||||
* Figure out why namespace rfc2616 is included in docs
|
||||
(currently disabled via GENERATING_DOCS macro)
|
||||
* Include Example program listings in the docs
|
||||
|
||||
@@ -51,13 +51,13 @@ LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = NO
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
340
doc/http.qbk
340
doc/http.qbk
@@ -41,64 +41,24 @@ both Boost.Asio and the HTTP protocol specification described in
|
||||
|
||||
|
||||
|
||||
[section:example Example]
|
||||
[section:usage Usage]
|
||||
|
||||
All examples and identifiers mentioned in this document are written as
|
||||
if the following declarations are in effect:
|
||||
```
|
||||
#include <boost/asio.hpp>
|
||||
#include <beast/http.hpp>
|
||||
using namespace beast;
|
||||
using namespace boost::asio;
|
||||
```
|
||||
|
||||
Create a HTTP request:
|
||||
```
|
||||
http::request<http::empty_body> req({http::method_t::http_get, "/", 11});
|
||||
req.headers.insert("Host", "127.0.0.1:80");
|
||||
req.headers.insert("User-Agent", "Beast.HTTP");
|
||||
|
||||
```
|
||||
|
||||
When sending a message, the Content-Length and Transfer-Encoding are set
|
||||
automatically based on the properties of the body. Depending on the HTTP
|
||||
version of the message and properties of the message body, the implementation
|
||||
will automaticaly chunk-encode the data sent on the wire:
|
||||
```
|
||||
ip::tcp::socket sock(ios);
|
||||
...
|
||||
http::response<http::string_body> resp({200, "OK", 11});
|
||||
resp.headers.insert("Server", "Beast.HTTP");
|
||||
resp.body = "The command was successful";
|
||||
|
||||
write(sock, resp);
|
||||
}
|
||||
```
|
||||
|
||||
Receiving a message is simple, declare a value of type message and call `read`.
|
||||
This example reads a message, builds a response, and sends it.
|
||||
```
|
||||
void handle_connection(ip::tcp::socket& sock)
|
||||
{
|
||||
request<string_body> req;
|
||||
read(sock, req);
|
||||
response<string_body> resp;
|
||||
...
|
||||
write(sock, resp);
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:message Message model]
|
||||
[note
|
||||
Sample code and identifiers mentioned in this section are written
|
||||
as if the following declarations are in effect:
|
||||
```
|
||||
#include <beast/http.hpp>
|
||||
using namespace beast;
|
||||
```
|
||||
]
|
||||
|
||||
A HTTP message (referred to hereafter as "message") contains a request or
|
||||
response line, a series of zero or more name/value pairs (collectively
|
||||
termed "headers"), and a series of octets called the message body which may
|
||||
be zero in length. Applications using HTTP often perform these operations
|
||||
on messages:
|
||||
be zero in length. The HTTP protocol defines the client and server roles:
|
||||
clients send messages called requests and servers send back messages called
|
||||
responses. `http::message` models both requests and responses. The library
|
||||
provides interfaces to perform these operations on messages:
|
||||
|
||||
* [*Parse] a new message from a series of octets.
|
||||
|
||||
@@ -112,6 +72,205 @@ operation; a network read, followed by a [*parse].
|
||||
* [*Write] a message to a stream. This can be thought of as a compound
|
||||
operation: a [*serialize] followed by a network write.
|
||||
|
||||
In the paragraphs that follow we describe simple interfaces that will serve
|
||||
the majority of users looking merely to interact with a HTTP server, or
|
||||
handle simple HTTP requests from clients. Subsequent sections cover the
|
||||
message model in more depth, for advanced applications.
|
||||
|
||||
[heading Declarations]
|
||||
|
||||
To do anything, a message must be declared. The message class template
|
||||
requires at mininum, a bool indicating whether the message is a request
|
||||
(versus a response), and a `Body` type. The choice of `Body` determines the
|
||||
kind of container used to represent the message body. Here we will
|
||||
declare a request that has a `std::string` for the body container:
|
||||
```
|
||||
http::message<true, http::string_body> req;
|
||||
```
|
||||
|
||||
Two type aliases are provided for notational convenience when declaring
|
||||
messages. These two statements declare a request and a response respectively:
|
||||
```
|
||||
http::request<http::string_body> req;
|
||||
http::response<http::string_body> resp;
|
||||
```
|
||||
|
||||
[heading Members]
|
||||
|
||||
Message objects are default constructible, with public access to data members.
|
||||
Request and response objects have some common members, and some members unique
|
||||
to the message type. These statements set all the members in each message:
|
||||
```
|
||||
http::request<http::string_body> req;
|
||||
req.method = http::method_t::http_get;
|
||||
req.url = "/index.html";
|
||||
req.version = 11; // HTTP/1.1
|
||||
req.headers.insert("User-Agent", "hello_world");
|
||||
req.body = "";
|
||||
|
||||
http::response<http::string_body> resp;
|
||||
resp.status = 404;
|
||||
resp.reason = "Not Found";
|
||||
resp.version = 10; // HTTP/1.0
|
||||
resp.headers.insert("Server", "Beast.HTTP");
|
||||
resp.body = "The requested resource was not found.";
|
||||
```
|
||||
|
||||
The following statements achieve the same effects as the statements above:
|
||||
```
|
||||
http::request<http::string_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
req.headers.insert("User-Agent", "hello_world");
|
||||
req.body = "";
|
||||
|
||||
http::response<http::string_body> resp({404, "Not Found", 10});
|
||||
resp.headers.insert("Server", "Beast.HTTP");
|
||||
resp.body = "The requested resource was not found.";
|
||||
```
|
||||
|
||||
[heading Headers]
|
||||
|
||||
The `message::headers` member is a container for setting the field/value
|
||||
pairs in the message. These statements change the values of the headers
|
||||
in the message passed:
|
||||
```
|
||||
template<class Body>
|
||||
void set_fields(http::request<Body>& req)
|
||||
{
|
||||
if(! req.exists("User-Agent"))
|
||||
req.insert("User-Agent", "myWebClient");
|
||||
|
||||
if(req.exists("Accept-Charset"))
|
||||
req.erase("Accept-Charset");
|
||||
|
||||
req.replace("Accept", "text/plain");
|
||||
}
|
||||
```
|
||||
|
||||
[heading Body]
|
||||
|
||||
The `message::body` member represents the message body. Depending on the
|
||||
`Body` template argument type, this could be a writable container. The
|
||||
following types, provided by the library, are suitable choices for the
|
||||
`Body` type:
|
||||
|
||||
* [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
|
||||
Used in GET requests where there is no message body. Example:
|
||||
```
|
||||
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
```
|
||||
|
||||
* [link beast.ref.http__string_body [*`string_body`:]] A body with a
|
||||
`value_type` as `std::string`. Useful for quickly putting together a request
|
||||
or response with simple text in the message body (such as an error message).
|
||||
Has the same insertion complexity of `std::string`. This is the type of body
|
||||
used in the examples:
|
||||
```
|
||||
http::response<http::string_body> resp;
|
||||
static_assert(std::is_same<decltype(resp.body), std::string>::value);
|
||||
resp.body = "Here is the data you requested";
|
||||
```
|
||||
|
||||
* [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a
|
||||
`value_type` of `streambuf`. A streambuf is an efficient storage object which
|
||||
uses multiple octet arrays of varying lengths to represent data. Here is
|
||||
a body that uses a `boost::asio::streambuf` as its container:
|
||||
```
|
||||
template<class ConstBufferSequence>
|
||||
http::response<http::basic_streambuf_body<boost::asio::streambuf>>
|
||||
make_response(ConstBufferSequence const& buffers)
|
||||
{
|
||||
http::response<http::streambuf_body<boost::asio::streambuf>> resp;
|
||||
resp.body.commit(boost::asio::buffer_copy(resp.body.prepare(
|
||||
boost::asio::buffer_size(buffers)), buffers));
|
||||
return resp;
|
||||
}
|
||||
```
|
||||
|
||||
[heading Sockets]
|
||||
|
||||
The library provides simple free functions modeled after Boost.Asio to
|
||||
send and receive messages on TCP/IP sockets, SSL streams, or any object
|
||||
which meets the Boost.Asio type requirements (SyncReadStream, SyncWriteStream,
|
||||
AsyncReadStream, and AsyncWriteStream depending on the types of operations
|
||||
performed). To send messages synchronously, use one of the `http:write`
|
||||
functions:
|
||||
```
|
||||
void send_request(boost::asio::ip::tcp::socket& sock)
|
||||
{
|
||||
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
|
||||
...
|
||||
http::write(sock, req); // Throws exception on error
|
||||
...
|
||||
// Alternatively
|
||||
boost::system::error:code ec;
|
||||
http::write(sock, req, ec);
|
||||
if(ec)
|
||||
std::cerr << "error writing http message: " << ec.message();
|
||||
}
|
||||
```
|
||||
|
||||
An asynchronous interface is available:
|
||||
```
|
||||
void handle_write(boost::system::error_code);
|
||||
...
|
||||
http::request<http::empty_body> req;
|
||||
...
|
||||
http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
|
||||
```
|
||||
|
||||
When the implementation reads messages from a socket, it can read bytes lying
|
||||
after the end of the message if they are present (the alternative is to read
|
||||
a single byte at a time which is unsuitable for performance reasons). To
|
||||
store and re-use these extra bytes on subsequent messages, the read interface
|
||||
requires an additional paramter: a [link beast.types.Streambuf [*`Streambuf`]]
|
||||
object. This example reads a message from the socket, with the extra bytes
|
||||
stored in the streambuf parameter for use in a subsequent call to read:
|
||||
```
|
||||
boost::asio::streambuf sb;
|
||||
...
|
||||
http::response<http::string_body> resp;
|
||||
http::read(sock, sb, resp); // Throws exception on error
|
||||
...
|
||||
// Alternatively
|
||||
boost::system::error:code ec;
|
||||
http::read(sock, sb, resp, ec);
|
||||
if(ec)
|
||||
std::cerr << "error reading http message: " << ec.message();
|
||||
```
|
||||
|
||||
As with the write function, an asynchronous interface is available. The
|
||||
stream buffer parameter must remain valid until the completion handler is
|
||||
called:
|
||||
```
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
boost::asio::streambuf sb;
|
||||
http::response<http::string_body> resp;
|
||||
...
|
||||
http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1));
|
||||
```
|
||||
|
||||
An alternative to using a `boost::asio::streambuf` is to use a
|
||||
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
|
||||
[*`Streambuf`] and is optimized for performance:
|
||||
```
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
beast::streambuf sb;
|
||||
http::response<http::string_body> resp;
|
||||
http::read(sock, sb, resp);
|
||||
```
|
||||
|
||||
The `read` implementation can use any object meeting the requirements of
|
||||
[link beast.types.Streambuf [*`Streambuf`]], allowing callers to define custom
|
||||
memory management strategies used by the implementation.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:advanced Advanced]
|
||||
|
||||
The spectrum of hardware and software platforms which perform these typical
|
||||
HTTP operations is vast, ranging from powerful servers in large datacenters
|
||||
to tiny resource-limited embedded devices. No single concrete implementation
|
||||
@@ -122,10 +281,15 @@ message body as a disk file may support sending but not parsing. Many efficient
|
||||
and correct models of messages exist, supporting some or all of the
|
||||
operations listed above.
|
||||
|
||||
To support a variety of implementation strategies, we introduce customization
|
||||
points for the header and body via class template arguments. This illustration
|
||||
shows the message class template (boilerplate present in the actual
|
||||
declaration has been removed for clarity):
|
||||
[heading Message model]
|
||||
|
||||
The message class template and provided Body types are suitable for casual
|
||||
library users. This section explains the message model for advanced users
|
||||
who wish to take control over aspects of the implementation. We introduce
|
||||
customization points for the header and body via class template arguments.
|
||||
This illustration shows more detail about the
|
||||
[link beast.ref.http__message [*`message`]] class template (boilerplate
|
||||
present in the actual declaration has been removed for clarity):
|
||||
|
||||
[$images/message.png [width 580px] [height 225px]]
|
||||
|
||||
@@ -143,45 +307,7 @@ overloaded on the type of message.
|
||||
|
||||
|
||||
|
||||
[section:body Body parameter]
|
||||
|
||||
The `Body` template argument in the `message` class must meet the
|
||||
[link beast.types.Body [*`Body`] requirements]. It provides customization
|
||||
of the data member in the message, the algorithm for parsing, and the
|
||||
algorithm for serialization:
|
||||
|
||||
[$images/body.png [width 510px] [height 210px]]
|
||||
|
||||
The following types, provided by the library, meet the `Body` requirements:
|
||||
|
||||
* [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
|
||||
Used in GET requests where there is no message body.
|
||||
|
||||
* [link beast.ref.http__string_body [*`string_body`:]] A body with a
|
||||
`value_type` of `std::string`. Useful for quickly putting together a request
|
||||
or response with simple text in the message body (such as an error message).
|
||||
Subject to the performance limit of strings if large amounts of data are
|
||||
inserted.
|
||||
|
||||
* [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a
|
||||
`value_type` of `streambuf`. A streambuf is an efficient storage object which
|
||||
uses multiple octet arrays of varying lengths to represent data.
|
||||
|
||||
Instances of the optional nested types `writer` and `reader` perform
|
||||
serialization and deserialization of the message body. If either or
|
||||
both of these types are present, the message becomes serializable, parsable,
|
||||
or both. They model [link beast.types.Reader [*`Reader`]] and
|
||||
[link beast.types.Writer [*`Writer`]] respectively.
|
||||
|
||||
For specialized applications, users may implement their own types which
|
||||
meet the requirements. The examples included with this library provide a
|
||||
Body implementation used to serve files in a HTTP server.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:headers Headers container]
|
||||
[section:headers Headers Type]
|
||||
|
||||
The `Headers` type represents the field/value pairs present in every HTTP
|
||||
message. These types implement the
|
||||
@@ -208,5 +334,27 @@ has_connect(FieldSequence const& fs)
|
||||
|
||||
|
||||
|
||||
[section:body Body Type]
|
||||
|
||||
The `Body` template argument in the `message` class must meet the
|
||||
[link beast.types.Body [*`Body`] requirements]. It provides customization
|
||||
of the data member in the message, the algorithm for parsing, and the
|
||||
algorithm for serialization:
|
||||
|
||||
[$images/body.png [width 510px] [height 210px]]
|
||||
|
||||
Instances of the optional nested types `writer` and `reader` perform
|
||||
serialization and deserialization of the message body. If either or
|
||||
both of these types are present, the message becomes serializable, parsable,
|
||||
or both. They model [link beast.types.Reader [*`Reader`]] and
|
||||
[link beast.types.Writer [*`Writer`]] respectively.
|
||||
|
||||
For specialized applications, users may implement their own types which
|
||||
meet the requirements. The examples included with this library provide a
|
||||
Body implementation used to serve files in a HTTP server.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -40,31 +40,22 @@
|
||||
<xsl:sort select="concat((. | ancestor::*)/compoundname, '::', name, ':x')"/>
|
||||
<xsl:sort select="name"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="@kind='class' or @kind='struct'">
|
||||
<xsl:call-template name="class"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="namespace-memberdef"/>
|
||||
</xsl:otherwise>
|
||||
<!--
|
||||
<xsl:when test="@kind='class' or @kind='struct'">
|
||||
<xsl:if test="
|
||||
contains(compoundname, 'beast::') and
|
||||
not(contains(compoundname, '::detail'))">
|
||||
not(contains(compoundname, '::detail')) and
|
||||
not(contains(compoundname, 'rfc2616')) and
|
||||
not(contains(@prot, 'private'))">
|
||||
<xsl:call-template name="class"/>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:if test="
|
||||
not(contains(ancestor::*/compoundname, '::detail')) and
|
||||
not(contains(ancestor::*/compoundname, '::service::key')) and
|
||||
not(contains(ancestor::*/compoundname, '_helper')) and
|
||||
not(contains(name, '_helper')) and
|
||||
not(contains(name, 'io_service_impl'))">
|
||||
not(contains(compoundname, 'rfc2616'))">
|
||||
<xsl:call-template name="namespace-memberdef"/>
|
||||
</xsl:if>
|
||||
</xsl:otherwise>
|
||||
-->
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
<xsl:text>
[endsect]</xsl:text>
|
||||
@@ -288,6 +279,14 @@
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="ulink" mode="markup">
|
||||
<xsl:text>[@</xsl:text>
|
||||
<xsl:value-of select="@url"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="."/>
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="programlisting" mode="markup">
|
||||
<xsl:value-of select="$newline"/>
|
||||
<xsl:value-of select="$newline"/>
|
||||
@@ -673,18 +672,16 @@
|
||||
<xsl:value-of select="$newline"/>
|
||||
<xsl:text>[heading Requirements]
</xsl:text>
|
||||
<xsl:text>['Header: ][^</xsl:text>
|
||||
<xsl:value-of select="substring-after($file, 'beast/')"/>
|
||||
<xsl:value-of select="substring-after($file, 'include/')"/>
|
||||
<xsl:text>] 

</xsl:text>
|
||||
<xsl:text>['Convenience header: ]</xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($file, 'beast/asio')">
|
||||
<xsl:text>[^beast/asio.h]</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="contains($file, 'beast/http')">
|
||||
<xsl:text>[^beast/http.h]</xsl:text>
|
||||
<xsl:text>['Convenience header: ][^beast/http.hpp]</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="contains($file, 'beast/wsproto')">
|
||||
<xsl:text>[^beast/wsproto.h]</xsl:text>
|
||||
<xsl:when test="contains($file, 'beast/websocket')">
|
||||
<xsl:text>['Convenience header: ][^beast/websocket.hpp]</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="contains($file, 'beast/')">
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$file"/>
|
||||
@@ -911,7 +908,7 @@
|
||||
</xsl:for-each>
|
||||
<xsl:text>]
</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="count(sectiondef[@kind='private-func' or @kind='protected-private-func']) > 0">
|
||||
<xsl:if test="count(sectiondef[@kind='private-func' or @kind='protected-private-func']) < 0">
|
||||
<xsl:text>[heading Private Member Functions]
</xsl:text>
|
||||
<xsl:text>[table
 [[Name][Description]]
</xsl:text>
|
||||
<xsl:for-each select="sectiondef[@kind='private-func']/memberdef" mode="class-table">
|
||||
@@ -988,7 +985,7 @@
|
||||
</xsl:for-each>
|
||||
<xsl:text>]
</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="count(sectiondef[@kind='private-attrib' or @kind='private-static-attrib']) > 0">
|
||||
<xsl:if test="count(sectiondef[@kind='private-attrib' or @kind='private-static-attrib']) < 0">
|
||||
<xsl:text>[heading Private Data Members]
</xsl:text>
|
||||
<xsl:text>[table
 [[Name][Description]]
</xsl:text>
|
||||
<xsl:for-each select="sectiondef[@kind='private-attrib' or @kind='private-static-attrib']/memberdef" mode="class-table">
|
||||
@@ -1274,7 +1271,7 @@
|
||||
<xsl:text>```
</xsl:text>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates select="detaileddescription"/>
|
||||
<xsl:apply-templates select="detaileddescription" mode="markup"/>
|
||||
<xsl:if test="@kind='typedef' or @kind='friend'">
|
||||
<xsl:call-template name="header-requirements">
|
||||
<xsl:with-param name="file" select="$class-file"/>
|
||||
@@ -1423,91 +1420,12 @@
|
||||
|
||||
<xsl:template match="param" mode="class-detail-template">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="type"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="declname = 'Allocator'">
|
||||
<xsl:value-of select="declname"/>
|
||||
<xsl:when test="type = 'class Body'">
|
||||
<xsl:text>class ``[link beast.types.Body [*Body]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Arg'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'BufferSequence'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'ByteType'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Clock'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'CompletionCondition'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'ConnectCondition'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Context_Service'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'DatagramSocketService1'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.DatagramSocketService ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'EndpointIterator'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Elem'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'ErrorEnum'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Function'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Iterator'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'MatchCondition'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'N'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'OtherAllocator'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'PasswordCallback'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'PodType'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'PointerToPodType'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Protocol1'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.Protocol ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'RawSocketService1'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.RawSocketService ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'SeqPacketSocketService1'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.SeqPacketSocketService ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Signature'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'SocketAcceptorService1' or declname = 'SocketAcceptorService2'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.SocketAcceptorService ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'SocketService1' or declname = 'SocketService2'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.SocketService ', declname, ']``')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Stream'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'StreamSocketService1'">
|
||||
<xsl:value-of select="concat('``[link beast.ref.StreamSocketService ', declname, ']``')"/>
|
||||
<xsl:when test="type = 'class Streambuf'">
|
||||
<xsl:text>class ``[link beast.types.Streambuf [*Streambuf]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'T'">
|
||||
<xsl:value-of select="declname"/>
|
||||
@@ -1518,22 +1436,14 @@
|
||||
<xsl:when test="declname = 'TN'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Time'">
|
||||
<xsl:when test="count(declname) > 0">
|
||||
<xsl:value-of select="type"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'TimeType'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Traits'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'VerifyCallback'">
|
||||
<xsl:value-of select="declname"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="count(declname) = 0">
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat(' ``[link beast.ref.', declname, ' ', declname, ']``')"/>
|
||||
<xsl:value-of select="type"/>
|
||||
<!--<xsl:value-of select="concat(' ``[link beast.ref.', declname, ' ', declname, ']``')"/>-->
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:if test="count(defval) > 0">
|
||||
@@ -1557,6 +1467,10 @@
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:choose>
|
||||
<xsl:when test="' &&' = substring(type, string-length(type) - 2)">
|
||||
<xsl:value-of select="substring(type, 1, string-length(type) - 3)"/>
|
||||
<xsl:text>&&</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="' &' = substring(type, string-length(type) - 1)">
|
||||
<xsl:value-of select="substring(type, 1, string-length(type) - 2)"/>
|
||||
<xsl:text>&</xsl:text>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Completion helper for implementing the extensible asynchronous model.
|
||||
/** Helper for customizing the return type of asynchronous initiation functions.
|
||||
|
||||
This class template is used to transform caller-provided
|
||||
completion tokens in calls to asynchronous initiation
|
||||
functions. The transformation allows customization of
|
||||
the return type of the initiating function, and the type
|
||||
of the final handler.
|
||||
This class template is used to transform caller-provided completion
|
||||
tokens in calls to asynchronous initiation functions. The transformation
|
||||
allows customization of the return type of the initiating function, and the
|
||||
function signature of the final handler.
|
||||
|
||||
@tparam CompletionToken A CompletionHandler, or a user defined type
|
||||
with specializations for customizing the return type (for example,
|
||||
@@ -30,14 +29,16 @@ namespace beast {
|
||||
|
||||
@tparam Signature The callable signature of the final completion handler.
|
||||
|
||||
Usage:
|
||||
Example:
|
||||
@code
|
||||
...
|
||||
template<class CompletionToken>
|
||||
typename async_completion<CompletionToken, Signature>::result_type
|
||||
typename async_completion<CompletionToken,
|
||||
void(boost::system::error_code)>::result_type
|
||||
async_initfn(..., CompletionToken&& token)
|
||||
{
|
||||
async_completion<CompletionToken, Signature> completion(token);
|
||||
async_completion<CompletionToken,
|
||||
void(boost::system::error_code)> completion(token);
|
||||
...
|
||||
return completion.result.get();
|
||||
}
|
||||
@@ -49,19 +50,19 @@ namespace beast {
|
||||
template <class CompletionToken, class Signature>
|
||||
struct async_completion
|
||||
{
|
||||
/** The type of the final handler.
|
||||
/** The type of the final handler called by the asynchronous initiation function.
|
||||
|
||||
Objects of this type will be callable with the
|
||||
specified signature.
|
||||
Objects of this type will be callable with the specified signature.
|
||||
*/
|
||||
using handler_type =
|
||||
typename boost::asio::handler_type<
|
||||
CompletionToken, Signature>::type;
|
||||
|
||||
/// The type of the value returned by the asynchronous initiation function.
|
||||
using result_type = typename
|
||||
boost::asio::async_result<handler_type>::type;
|
||||
|
||||
/** Construct the completion helper.
|
||||
/** Construct the helper.
|
||||
|
||||
@param token The completion token. Copies will be made as
|
||||
required. If `CompletionToken` is movable, it may also be moved.
|
||||
@@ -74,10 +75,10 @@ struct async_completion
|
||||
"Handler requirements not met");
|
||||
}
|
||||
|
||||
/** The final completion handler, callable with the specified signature. */
|
||||
/// The final completion handler, callable with the specified signature.
|
||||
handler_type handler;
|
||||
|
||||
/** The return value of the asynchronous initiation function. */
|
||||
/// The return value of the asynchronous initiation function.
|
||||
boost::asio::async_result<handler_type> result;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ class basic_streambuf
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// The type of allocator used.
|
||||
using allocator_type = typename
|
||||
std::allocator_traits<Allocator>::
|
||||
template rebind_alloc<std::uint8_t>;
|
||||
@@ -73,10 +74,20 @@ private:
|
||||
size_type out_end_ = 0; // output end offset in list_.back()
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
|
||||
class mutable_buffers_type;
|
||||
|
||||
#endif
|
||||
|
||||
/// Destructor.
|
||||
~basic_streambuf();
|
||||
|
||||
@@ -175,7 +186,7 @@ public:
|
||||
template<class OtherAlloc>
|
||||
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const& other);
|
||||
|
||||
/** Construct a stream buffer.
|
||||
/** Default constructor.
|
||||
|
||||
@param alloc_size The size of buffer to allocate. This is a soft
|
||||
limit, calls to prepare for buffers exceeding this size will allocate
|
||||
@@ -258,60 +269,6 @@ private:
|
||||
debug_check() const;
|
||||
};
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::const_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_ = nullptr;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
const_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::mutable_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
mutable_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
/** Format output to a stream buffer.
|
||||
|
||||
@param streambuf The streambuf to write to.
|
||||
@@ -322,7 +279,7 @@ public:
|
||||
*/
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& buf, T const& t);
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t);
|
||||
|
||||
/** Convert the entire basic_streambuf to a string.
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
|
||||
Example:
|
||||
@code
|
||||
template<class AsyncReadStream, ReadHandler>
|
||||
template<class AsyncReadStream, class ReadHandler>
|
||||
void
|
||||
do_cancel(AsyncReadStream& stream, ReadHandler&& handler)
|
||||
{
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
#define BEAST_BUFFERS_ADAPTER_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
@@ -70,19 +65,30 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
|
||||
class mutable_buffers_type;
|
||||
|
||||
// Move constructor.
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
buffers_adapter(buffers_adapter&& other);
|
||||
|
||||
// Copy constructor.
|
||||
/// Copy constructor.
|
||||
buffers_adapter(buffers_adapter const& other);
|
||||
|
||||
// Move assignment.
|
||||
/// Move assignment.
|
||||
buffers_adapter& operator=(buffers_adapter&& other);
|
||||
|
||||
// Copy assignment.
|
||||
/// Copy assignment.
|
||||
buffers_adapter& operator=(buffers_adapter const&);
|
||||
|
||||
/** Construct a buffers adapter.
|
||||
@@ -129,508 +135,8 @@ public:
|
||||
consume(std::size_t n);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
const_buffers_type(buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void const*>(*it_),
|
||||
(ba_->out_ == ba_->bs_.end() ||
|
||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->begin_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_ ==
|
||||
ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
mutable_buffers_type(
|
||||
buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void*>(*it_),
|
||||
it_ == std::prev(ba_->end_) ?
|
||||
ba_->out_end_ : buffer_size(*it_)} +
|
||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
, end_(bs_.begin())
|
||||
, max_size_(boost::asio::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
end_ = out_;
|
||||
if(end_ != bs_.end())
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ != bs_.end())
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
if(n < size)
|
||||
{
|
||||
out_end_ = n;
|
||||
n = 0;
|
||||
++end_;
|
||||
break;
|
||||
}
|
||||
n -= size;
|
||||
out_end_ = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++end_;
|
||||
out_end_ = out_pos_ + n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
if(n > 0)
|
||||
throw std::length_error(
|
||||
"no space in buffers_adapter");
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::commit(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
if(out_ == end_)
|
||||
return;
|
||||
auto const last = std::prev(end_);
|
||||
while(out_ != last)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*out_) - out_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
return;
|
||||
}
|
||||
++out_;
|
||||
n -= avail;
|
||||
out_pos_ = 0;
|
||||
in_size_ += avail;
|
||||
max_size_ -= avail;
|
||||
}
|
||||
|
||||
n = std::min(n, out_end_ - out_pos_);
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
if(out_pos_ == buffer_size(*out_))
|
||||
{
|
||||
++out_;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(begin_ != out_)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*begin_) - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
in_size_ -= avail;
|
||||
in_pos_ = 0;
|
||||
++begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const avail = out_pos_ - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_size_ -= avail;
|
||||
if(out_pos_ != out_end_||
|
||||
out_ != std::prev(bs_.end()))
|
||||
{
|
||||
in_pos_ = out_pos_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the whole buffer now.
|
||||
in_pos_ = 0;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/buffers_adapter.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
namespace beast {
|
||||
namespace debug {
|
||||
|
||||
/** Diagnostic utility to convert a `ConstBufferSequence` to a string.
|
||||
|
||||
@note Carriage returns and linefeeds will have additional escape
|
||||
representations printed for visibility.
|
||||
*/
|
||||
template<class Buffers>
|
||||
std::string
|
||||
buffers_to_string(Buffers const& bs)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_CONSUMING_BUFFERS_HPP
|
||||
#define BEAST_CONSUMING_BUFFERS_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -64,8 +63,15 @@ public:
|
||||
/// The type for each element in the list of buffers.
|
||||
using value_type = ValueType;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
using const_iterator = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_iterator;
|
||||
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
consuming_buffers(consuming_buffers&&);
|
||||
|
||||
@@ -104,194 +110,13 @@ public:
|
||||
consume(std::size_t n);
|
||||
};
|
||||
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
template<class Buffers, class ValueType>
|
||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
||||
{
|
||||
friend class consuming_buffers<Buffers, ValueType>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
consuming_buffers const* b_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->begin_)
|
||||
return *it_ + b_->skip_;
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(consuming_buffers const& b,
|
||||
iter_type it)
|
||||
: it_(it)
|
||||
, b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers&& other)
|
||||
: consuming_buffers(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers const& other)
|
||||
: consuming_buffers(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers&& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers const& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, begin_};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
void
|
||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||
{
|
||||
auto const len =
|
||||
buffer_size(*begin_) - skip_;
|
||||
if(n < len)
|
||||
{
|
||||
skip_ += n;
|
||||
break;
|
||||
}
|
||||
n -= len;
|
||||
skip_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a consumed buffer
|
||||
template<class Buffers>
|
||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
||||
{
|
||||
consuming_buffers<Buffers> cb(bs);
|
||||
cb.consume(n);
|
||||
return cb;
|
||||
}
|
||||
consumed_buffers(Buffers const& bs, std::size_t n);
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/consuming_buffers.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,12 +22,21 @@ namespace beast {
|
||||
/** An allocator that uses handler customizations.
|
||||
|
||||
This allocator uses the handler customizations `asio_handler_allocate`
|
||||
and `asio_handler_deallocate` to manage memory.
|
||||
and `asio_handler_deallocate` to manage memory. It meets the requirements
|
||||
of `Allocator` and can be used anywhere a `std::allocator` is
|
||||
accepted.
|
||||
|
||||
@tparam T The type of object
|
||||
@tparam T The type of objects allocated by the allocator.
|
||||
|
||||
@tparam Handler The type of handler.
|
||||
|
||||
@note Allocated memory is only valid until the handler is called. The
|
||||
caller is still responsible for freeing memory.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template <class T, class Handler>
|
||||
class handler_alloc;
|
||||
#else
|
||||
template <class T, class Handler>
|
||||
class handler_alloc
|
||||
{
|
||||
@@ -132,6 +141,7 @@ public:
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/http/streambuf_body.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,9 +22,16 @@ namespace http {
|
||||
*/
|
||||
struct empty_body
|
||||
{
|
||||
struct value_type
|
||||
{
|
||||
};
|
||||
#if GENERATING_DOCS
|
||||
/// The type of the `message::body` member
|
||||
using value_type = void;
|
||||
#else
|
||||
struct value_type {};
|
||||
#endif
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
struct reader
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define BEAST_HTTP_IMPL_MESSAGE_IPP
|
||||
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
@@ -26,16 +25,12 @@ template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message()
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(request_params params)
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(isRequest, "message is not a request");
|
||||
this->method = params.method;
|
||||
this->url = std::move(params.url);
|
||||
@@ -46,8 +41,6 @@ template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(response_params params)
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(! isRequest, "message is not a response");
|
||||
this->status = params.status;
|
||||
this->reason = std::move(params.reason);
|
||||
@@ -160,8 +153,6 @@ std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
error_code ec;
|
||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||
wp.init(ec);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <cassert>
|
||||
@@ -219,8 +218,6 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
static_assert(is_ReadableBody<Body>::value,
|
||||
"ReadableBody requirements not met");
|
||||
parser<isRequest, Body, Headers> p;
|
||||
for(;;)
|
||||
{
|
||||
@@ -268,8 +265,6 @@ async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
static_assert(is_ReadableBody<Body>::value,
|
||||
"ReadableBody requirements not met");
|
||||
beast::async_completion<ReadHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::read_op<AsyncReadStream, Streambuf,
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
@@ -265,9 +264,9 @@ operator()(error_code ec, std::size_t, bool again)
|
||||
|
||||
case 4:
|
||||
// VFALCO Unfortunately the current interface to the
|
||||
// Writer concept prevents us from using coalescing the
|
||||
// Writer concept prevents us from coalescing the
|
||||
// final body chunk with the final chunk delimiter.
|
||||
//
|
||||
//
|
||||
// write final chunk
|
||||
d.state = 5;
|
||||
boost::asio::async_write(d.s,
|
||||
@@ -359,8 +358,6 @@ write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||
wp.init(ec);
|
||||
if(ec)
|
||||
@@ -447,8 +444,6 @@ async_write(AsyncWriteStream& stream,
|
||||
static_assert(
|
||||
is_AsyncWriteStream<AsyncWriteStream>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
beast::async_completion<WriteHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::write_op<AsyncWriteStream, decltype(completion.handler),
|
||||
|
||||
@@ -35,6 +35,8 @@ struct response_fields
|
||||
|
||||
} // detail
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
struct request_params
|
||||
{
|
||||
http::method_t method;
|
||||
@@ -49,6 +51,8 @@ struct response_params
|
||||
int version;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** A HTTP message.
|
||||
|
||||
A message can be a request or response, depending on the `isRequest`
|
||||
@@ -110,7 +114,7 @@ struct message
|
||||
|
||||
/// Diagnostics only
|
||||
template<bool, class, class>
|
||||
friend
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message const& m);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/parser.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
/** Routines for performing RFC2616 compliance.
|
||||
RFC2616:
|
||||
Hypertext Transfer Protocol -- HTTP/1.1
|
||||
@@ -454,6 +456,8 @@ token_in_list(boost::string_ref const& value,
|
||||
|
||||
} // rfc2616
|
||||
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,13 @@ namespace http {
|
||||
template<class Streambuf>
|
||||
struct basic_streambuf_body
|
||||
{
|
||||
/// The type of the `message::body` member
|
||||
using value_type = Streambuf;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
class reader
|
||||
{
|
||||
value_type& sb_;
|
||||
|
||||
@@ -23,8 +23,13 @@ namespace http {
|
||||
*/
|
||||
struct string_body
|
||||
{
|
||||
/// The type of the `message::body` member
|
||||
using value_type = std::string;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
class reader
|
||||
{
|
||||
value_type& s_;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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_TYPE_CHECK_HPP
|
||||
#define BEAST_HTTP_TYPE_CHECK_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/// Evaluates to std::true_type if `T` models Body
|
||||
template<class T>
|
||||
struct is_Body : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a reader
|
||||
template<class T>
|
||||
struct is_ReadableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a writer
|
||||
template<class T>
|
||||
struct is_WritableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `T` models HTTPMessage
|
||||
template<class T>
|
||||
struct is_HTTPMessage : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `HTTPMessage` is a request
|
||||
template<class HTTPMessage>
|
||||
struct is_HTTPRequest : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -115,6 +115,59 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::const_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_ = nullptr;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
const_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
/// Why?
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::mutable_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
mutable_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Allocator>
|
||||
@@ -798,16 +851,16 @@ basic_streambuf<Allocator>::debug_check() const
|
||||
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& buf, T const& t)
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
auto const& s = ss.str();
|
||||
buf.commit(buffer_copy(buf.prepare(s.size()),
|
||||
boost::asio::buffer(s)));
|
||||
return buf;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()), buffer(s)));
|
||||
return streambuf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
520
include/beast/impl/buffers_adapter.ipp
Normal file
520
include/beast/impl/buffers_adapter.ipp
Normal file
@@ -0,0 +1,520 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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_IMPL_BUFFERS_ADAPTER_IPP
|
||||
#define BEAST_IMPL_BUFFERS_ADAPTER_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
const_buffers_type(buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void const*>(*it_),
|
||||
(ba_->out_ == ba_->bs_.end() ||
|
||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->begin_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_ ==
|
||||
ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
mutable_buffers_type(
|
||||
buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void*>(*it_),
|
||||
it_ == std::prev(ba_->end_) ?
|
||||
ba_->out_end_ : buffer_size(*it_)} +
|
||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
, end_(bs_.begin())
|
||||
, max_size_(boost::asio::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
end_ = out_;
|
||||
if(end_ != bs_.end())
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ != bs_.end())
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
if(n < size)
|
||||
{
|
||||
out_end_ = n;
|
||||
n = 0;
|
||||
++end_;
|
||||
break;
|
||||
}
|
||||
n -= size;
|
||||
out_end_ = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++end_;
|
||||
out_end_ = out_pos_ + n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
if(n > 0)
|
||||
throw std::length_error(
|
||||
"no space in buffers_adapter");
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::commit(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
if(out_ == end_)
|
||||
return;
|
||||
auto const last = std::prev(end_);
|
||||
while(out_ != last)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*out_) - out_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
return;
|
||||
}
|
||||
++out_;
|
||||
n -= avail;
|
||||
out_pos_ = 0;
|
||||
in_size_ += avail;
|
||||
max_size_ -= avail;
|
||||
}
|
||||
|
||||
n = std::min(n, out_end_ - out_pos_);
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
if(out_pos_ == buffer_size(*out_))
|
||||
{
|
||||
++out_;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(begin_ != out_)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*begin_) - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
in_size_ -= avail;
|
||||
in_pos_ = 0;
|
||||
++begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const avail = out_pos_ - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_size_ -= avail;
|
||||
if(out_pos_ != out_end_||
|
||||
out_ != std::prev(bs_.end()))
|
||||
{
|
||||
in_pos_ = out_pos_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the whole buffer now.
|
||||
in_pos_ = 0;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
211
include/beast/impl/consuming_buffers.ipp
Normal file
211
include/beast/impl/consuming_buffers.ipp
Normal file
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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_IMPL_CONSUMING_BUFFERS_IPP
|
||||
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
||||
{
|
||||
friend class consuming_buffers<Buffers, ValueType>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
consuming_buffers const* b_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->begin_)
|
||||
return *it_ + b_->skip_;
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(consuming_buffers const& b,
|
||||
iter_type it)
|
||||
: it_(it)
|
||||
, b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers&& other)
|
||||
: consuming_buffers(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers const& other)
|
||||
: consuming_buffers(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers&& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers const& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
{
|
||||
static_assert(is_BufferSequence<Buffers, ValueType>::value,
|
||||
"BufferSequence requirements not met");
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, begin_};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
void
|
||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||
{
|
||||
auto const len =
|
||||
buffer_size(*begin_) - skip_;
|
||||
if(n < len)
|
||||
{
|
||||
skip_ += n;
|
||||
break;
|
||||
}
|
||||
n -= len;
|
||||
skip_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
||||
{
|
||||
consuming_buffers<Buffers> cb(bs);
|
||||
cb.consume(n);
|
||||
return cb;
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
215
include/beast/impl/prepare_buffers.ipp
Normal file
215
include/beast/impl/prepare_buffers.ipp
Normal file
@@ -0,0 +1,215 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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_IMPL_PREPARE_BUFFERS_IPP
|
||||
#define BEAST_IMPL_PREPARE_BUFFERS_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class BufferSequence>
|
||||
void
|
||||
prepared_buffers<BufferSequence>::
|
||||
setup(std::size_t n)
|
||||
{
|
||||
for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
|
||||
{
|
||||
auto const len =
|
||||
boost::asio::buffer_size(*end_);
|
||||
if(n <= len)
|
||||
{
|
||||
size_ = n;
|
||||
back_ = end_++;
|
||||
return;
|
||||
}
|
||||
n -= len;
|
||||
}
|
||||
size_ = 0;
|
||||
back_ = end_;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
class prepared_buffers<BufferSequence>::const_iterator
|
||||
{
|
||||
friend class prepared_buffers<BufferSequence>;
|
||||
|
||||
using iter_type =
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
prepared_buffers const* b_;
|
||||
typename BufferSequence::const_iterator it_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->back_)
|
||||
return prepare_buffer(b_->size_, *it_);
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(prepared_buffers const& b,
|
||||
bool at_end)
|
||||
: b_(&b)
|
||||
, it_(at_end ? b.end_ : b.bs_.begin())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers&& other)
|
||||
: prepared_buffers(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers const& other)
|
||||
: prepared_buffers(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers&& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers const& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(std::size_t n, BufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
inline
|
||||
prepared_buffers<BufferSequence>
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers)
|
||||
{
|
||||
return prepared_buffers<BufferSequence>(n, buffers);
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
304
include/beast/impl/static_streambuf.ipp
Normal file
304
include/beast/impl/static_streambuf.ipp
Normal file
@@ -0,0 +1,304 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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_IMPL_STATIC_STREAMBUF_IPP
|
||||
#define BEAST_IMPL_STATIC_STREAMBUF_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class static_streambuf::const_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
const_buffers_type(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::const_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class static_streambuf::mutable_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
mutable_buffers_type(
|
||||
std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::mutable_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
if(n > static_cast<std::size_t>(end_ - out_))
|
||||
throw std::length_error("no space in streambuf");
|
||||
last_ = out_ + n;
|
||||
return mutable_buffers_type{out_, n};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{in_,
|
||||
static_cast<std::size_t>(out_ - in_)};
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -85,8 +85,15 @@ public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
using const_iterator = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_iterator;
|
||||
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
prepared_buffers(prepared_buffers&&);
|
||||
|
||||
@@ -120,190 +127,9 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
setup(std::size_t n)
|
||||
{
|
||||
for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
|
||||
{
|
||||
auto const len =
|
||||
boost::asio::buffer_size(*end_);
|
||||
if(n <= len)
|
||||
{
|
||||
size_ = n;
|
||||
back_ = end_++;
|
||||
return;
|
||||
}
|
||||
n -= len;
|
||||
}
|
||||
size_ = 0;
|
||||
back_ = end_;
|
||||
}
|
||||
setup(std::size_t n);
|
||||
};
|
||||
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
template<class BufferSequence>
|
||||
class prepared_buffers<BufferSequence>::const_iterator
|
||||
{
|
||||
friend class prepared_buffers<BufferSequence>;
|
||||
|
||||
using iter_type =
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
prepared_buffers const* b_;
|
||||
typename BufferSequence::const_iterator it_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->back_)
|
||||
return prepare_buffer(b_->size_, *it_);
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(prepared_buffers const& b,
|
||||
bool at_end)
|
||||
: b_(&b)
|
||||
, it_(at_end ? b.end_ : b.bs_.begin())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers&& other)
|
||||
: prepared_buffers(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers const& other)
|
||||
: prepared_buffers(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers&& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers const& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(std::size_t n, BufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Return a trimmed, wrapped buffer sequence.
|
||||
@@ -321,13 +147,11 @@ prepared_buffers<BufferSequence>::end() const ->
|
||||
will be made, but ownership of the underlying memory is not transferred.
|
||||
*/
|
||||
template<class BufferSequence>
|
||||
inline
|
||||
prepared_buffers<BufferSequence>
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers)
|
||||
{
|
||||
return prepared_buffers<BufferSequence>(n, buffers);
|
||||
}
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers);
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/prepare_buffers.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
#ifndef BEAST_STATIC_STREAMBUF_HPP
|
||||
#define BEAST_STATIC_STREAMBUF_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -40,18 +38,23 @@ protected:
|
||||
std::uint8_t* end_;
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
class mutable_buffers_type;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
static_streambuf(
|
||||
static_streambuf const& other) noexcept = delete;
|
||||
|
||||
static_streambuf& operator=(
|
||||
static_streambuf const&) noexcept = delete;
|
||||
#if GENERATING_DOCS
|
||||
public:
|
||||
|
||||
#endif
|
||||
|
||||
/// Returns the largest size output sequence possible.
|
||||
@@ -116,293 +119,6 @@ protected:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
class static_streambuf::const_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
const_buffers_type(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::const_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
class static_streambuf::mutable_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
mutable_buffers_type(
|
||||
std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::mutable_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
if(n > static_cast<std::size_t>(end_ - out_))
|
||||
throw std::length_error("no space in streambuf");
|
||||
last_ = out_ + n;
|
||||
return mutable_buffers_type{out_, n};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{in_,
|
||||
static_cast<std::size_t>(out_ - in_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A `Streambuf` with a fixed size internal buffer.
|
||||
|
||||
@tparam N The number of bytes in the internal buffer.
|
||||
@@ -456,4 +172,6 @@ public:
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/static_streambuf.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/// The type of error used by functions and completion handlers.
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
/// Error values
|
||||
|
||||
@@ -45,7 +45,6 @@ unit-test http_tests :
|
||||
http/rfc2616.cpp
|
||||
http/streambuf_body.cpp
|
||||
http/string_body.cpp
|
||||
http/type_check.cpp
|
||||
http/write.cpp
|
||||
;
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 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/type_check.hpp>
|
||||
Reference in New Issue
Block a user