mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 14:35:52 +00:00
Merge subtree Beast 1.0.0-b3
Merge commit '47eb7fcc2f30df883b0036d97aac6a0fa90b0e9f'
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
sudo: false
|
|
||||||
language: cpp
|
language: cpp
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -8,55 +7,107 @@ env:
|
|||||||
# Note that for simplicity, BOOST_ROOT's final
|
# Note that for simplicity, BOOST_ROOT's final
|
||||||
# namepart must match the folder name internal
|
# namepart must match the folder name internal
|
||||||
# to boost's .tar.gz.
|
# to boost's .tar.gz.
|
||||||
|
- LCOV_ROOT=$HOME/lcov
|
||||||
|
- VALGRIND_ROOT=$HOME/valgrind-install
|
||||||
- BOOST_ROOT=$HOME/boost_1_60_0
|
- BOOST_ROOT=$HOME/boost_1_60_0
|
||||||
- BOOST_URL='http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.60.0%2Fboost_1_60_0.tar.gz&ts=1460417589&use_mirror=netix'
|
- BOOST_URL='http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.60.0%2Fboost_1_60_0.tar.gz&ts=1460417589&use_mirror=netix'
|
||||||
packages: &gcc5_pkgs
|
packages: &gcc5_pkgs
|
||||||
- gcc-5
|
- gcc-5
|
||||||
- g++-5
|
- g++-5
|
||||||
|
# - gcc-5-multilib
|
||||||
|
# - g++-5-multilib
|
||||||
|
# - gcc-multilib
|
||||||
|
# - g++-multilib
|
||||||
|
# - libgd2-xpm
|
||||||
|
# - ia32-libs
|
||||||
|
# - ia32-libs-multiarch
|
||||||
- python-software-properties
|
- python-software-properties
|
||||||
- protobuf-compiler
|
- libssl-dev
|
||||||
|
- libffi-dev
|
||||||
- libstdc++6
|
- libstdc++6
|
||||||
- binutils-gold
|
- binutils-gold
|
||||||
# Provides a backtrace if the unittests crash
|
# Provides a backtrace if the unittests crash
|
||||||
- gdb
|
- gdb
|
||||||
|
# Needed for installing valgrind
|
||||||
|
- subversion
|
||||||
|
- automake
|
||||||
|
- autotools-dev
|
||||||
|
- libc6-dbg
|
||||||
|
|
||||||
packages: &clang36_pkgs
|
packages: &clang36_pkgs
|
||||||
- clang-3.6
|
- clang-3.6
|
||||||
- g++-5
|
- g++-5
|
||||||
- python-software-properties
|
- python-software-properties
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
|
- libffi-dev
|
||||||
- libstdc++6
|
- libstdc++6
|
||||||
- binutils-gold
|
- binutils-gold
|
||||||
# Provides a backtrace if the unittests crash
|
# Provides a backtrace if the unittests crash
|
||||||
- gdb
|
- gdb
|
||||||
|
# Needed for installing valgrind
|
||||||
|
- subversion
|
||||||
|
- automake
|
||||||
|
- autotools-dev
|
||||||
|
- libc6-dbg
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
# GCC/Debug
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
env: GCC_VER=5 VARIANT=debug
|
env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64
|
||||||
addons: &ao_gcc5
|
addons: &ao_gcc5
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: *gcc5_pkgs
|
packages: *gcc5_pkgs
|
||||||
|
|
||||||
|
# - compiler: gcc
|
||||||
|
# env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=32
|
||||||
|
# addons: *ao_gcc5
|
||||||
|
|
||||||
|
# GCC/Release
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
env: GCC_VER=5 VARIANT=release
|
env: GCC_VER=5 VARIANT=release ADDRESS_MODEL=64
|
||||||
addons: *ao_gcc5
|
addons: *ao_gcc5
|
||||||
|
|
||||||
|
# # - compiler: gcc
|
||||||
|
# # env: GCC_VER=5 VARIANT=release ADDRESS_MODEL=32
|
||||||
|
# # addons: *ao_gcc5
|
||||||
|
|
||||||
|
# Clang/Debug
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
env: GCC_VER=5 VARIANT=debug CLANG_VER=3.6
|
env: GCC_VER=5 VARIANT=debug CLANG_VER=3.6 ADDRESS_MODEL=64
|
||||||
addons: &ao_clang36
|
addons: &ao_clang36
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
|
||||||
packages: *clang36_pkgs
|
packages: *clang36_pkgs
|
||||||
|
|
||||||
|
# # - compiler: clang
|
||||||
|
# # env: GCC_VER=5 VARIANT=debug CLANG_VER=3.6 ADDRESS_MODEL=32
|
||||||
|
# # addons: *ao_clang36
|
||||||
|
|
||||||
|
# Clang/Release
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
env: GCC_VER=5 VARIANT=release CLANG_VER=3.6
|
env: GCC_VER=5 VARIANT=release CLANG_VER=3.6 ADDRESS_MODEL=64
|
||||||
addons: *ao_clang36
|
addons: *ao_clang36
|
||||||
|
|
||||||
|
# # - compiler: clang
|
||||||
|
# # env: GCC_VER=5 VARIANT=release CLANG_VER=3.6 ADDRESS_MODEL=32
|
||||||
|
# # addons: *ao_clang36
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
- compiler: gcc
|
||||||
|
env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64
|
||||||
|
addons: *ao_gcc5
|
||||||
|
|
||||||
|
# ASAN
|
||||||
|
- compiler: gcc
|
||||||
|
env: GCC_VER=5 VARIANT=asan ADDRESS_MODEL=64
|
||||||
|
addons: *ao_gcc5
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $BOOST_ROOT
|
- $BOOST_ROOT
|
||||||
|
- $VALGRIND_ROOT
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- scripts/install-dependencies.sh
|
- scripts/install-dependencies.sh
|
||||||
@@ -64,6 +115,9 @@ before_install:
|
|||||||
script:
|
script:
|
||||||
- scripts/build-and-test.sh
|
- scripts/build-and-test.sh
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
- cat nohup.out || echo "nohup.out already deleted"
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
# Part of Beast
|
# Part of Beast
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 3.5)
|
cmake_minimum_required (VERSION 3.2)
|
||||||
|
|
||||||
project (Beast)
|
project (Beast)
|
||||||
|
|
||||||
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4100 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
|
||||||
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
|
||||||
else()
|
else()
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
|
find_package(Boost REQUIRED COMPONENTS filesystem program_options system)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
link_directories(${Boost_LIBRARY_DIR})
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS
|
||||||
|
"${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall /Wextra /Wpedantic /Wconversion -Wno-unused-variable")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
|
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
|
||||||
|
|||||||
@@ -45,48 +45,65 @@ else
|
|||||||
lib crypto ;
|
lib crypto ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variant coverage
|
||||||
|
:
|
||||||
|
debug
|
||||||
|
:
|
||||||
|
<cxxflags>"-fprofile-arcs -ftest-coverage"
|
||||||
|
<linkflags>"-lgcov"
|
||||||
|
;
|
||||||
|
|
||||||
|
variant asan
|
||||||
|
:
|
||||||
|
release
|
||||||
|
:
|
||||||
|
<cxxflags>"-fsanitize=address -fno-omit-frame-pointer"
|
||||||
|
<linkflags>"-fsanitize=address"
|
||||||
|
;
|
||||||
|
|
||||||
project beast
|
project beast
|
||||||
: requirements
|
: requirements
|
||||||
<include>.
|
<include>.
|
||||||
<include>./include
|
<include>./include
|
||||||
#<use>/boost//headers
|
#<use>/boost//headers
|
||||||
<library>/boost/system//boost_system
|
<library>/boost/system//boost_system
|
||||||
<library>/boost/filesystem//boost_filesystem
|
<library>/boost/coroutine//boost_coroutine
|
||||||
<library>/boost/program_options//boost_program_options
|
<library>/boost/filesystem//boost_filesystem
|
||||||
|
<library>/boost/program_options//boost_program_options
|
||||||
# <library>ssl
|
# <library>ssl
|
||||||
# <library>crypto
|
# <library>crypto
|
||||||
<define>BOOST_ALL_NO_LIB=1
|
<define>BOOST_ALL_NO_LIB=1
|
||||||
<define>BOOST_SYSTEM_NO_DEPRECATED=1
|
<define>BOOST_SYSTEM_NO_DEPRECATED=1
|
||||||
<threading>multi
|
<threading>multi
|
||||||
<link>static
|
<link>static
|
||||||
<runtime-link>shared
|
<runtime-link>shared
|
||||||
<debug-symbols>on
|
<debug-symbols>on
|
||||||
<toolset>gcc:<cxxflags>-std=c++11
|
<toolset>gcc:<cxxflags>-std=c++11
|
||||||
<toolset>gcc:<cxxflags>-Wno-unused-variable
|
<toolset>gcc:<cxxflags>-Wno-unused-variable
|
||||||
<toolset>clang:<cxxflags>-std=c++11
|
<toolset>clang:<cxxflags>-std=c++11
|
||||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||||
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
||||||
<os>LINUX:<define>_XOPEN_SOURCE=600
|
<os>LINUX:<define>_XOPEN_SOURCE=600
|
||||||
<os>LINUX:<define>_GNU_SOURCE=1
|
<os>LINUX:<define>_GNU_SOURCE=1
|
||||||
<os>SOLARIS:<define>_XOPEN_SOURCE=500
|
<os>SOLARIS:<define>_XOPEN_SOURCE=500
|
||||||
<os>SOLARIS:<define>__EXTENSIONS__
|
<os>SOLARIS:<define>__EXTENSIONS__
|
||||||
<os>SOLARIS:<library>socket
|
<os>SOLARIS:<library>socket
|
||||||
<os>SOLARIS:<library>nsl
|
<os>SOLARIS:<library>nsl
|
||||||
<os>NT:<define>_WIN32_WINNT=0x0501
|
<os>NT:<define>_WIN32_WINNT=0x0501
|
||||||
<os>NT,<toolset>cw:<library>ws2_32
|
<os>NT,<toolset>cw:<library>ws2_32
|
||||||
<os>NT,<toolset>cw:<library>mswsock
|
<os>NT,<toolset>cw:<library>mswsock
|
||||||
<os>NT,<toolset>gcc:<library>ws2_32
|
<os>NT,<toolset>gcc:<library>ws2_32
|
||||||
<os>NT,<toolset>gcc:<library>mswsock
|
<os>NT,<toolset>gcc:<library>mswsock
|
||||||
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
|
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
|
||||||
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
|
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
|
||||||
<os>HPUX:<library>ipv6
|
<os>HPUX:<library>ipv6
|
||||||
<os>QNXNTO:<library>socket
|
<os>QNXNTO:<library>socket
|
||||||
<os>HAIKU:<library>network
|
<os>HAIKU:<library>network
|
||||||
: usage-requirements
|
: usage-requirements
|
||||||
<include>.
|
<include>.
|
||||||
:
|
:
|
||||||
build-dir bin
|
build-dir bin
|
||||||
;
|
;
|
||||||
|
|
||||||
build-project test ;
|
build-project test ;
|
||||||
build-project examples ;
|
build-project examples ;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Beast [](https://travis-ci.org/vinniefalco/Beast)
|
# Beast [](https://travis-ci.org/vinniefalco/Beast) [](https://codecov.io/gh/sublimator/Beast)
|
||||||
|
|
||||||
Beast provides implementations of the HTTP and WebSocket protocols
|
Beast provides implementations of the HTTP and WebSocket protocols
|
||||||
built on top of Boost.Asio and other parts of boost.
|
built on top of Boost.Asio and other parts of boost.
|
||||||
|
|||||||
@@ -1,32 +1,45 @@
|
|||||||
* Change build options to C++11 only
|
* Add writer::prepare(msg&) interface to set Content-Type
|
||||||
* Replace Jamroot with Jamfile
|
|
||||||
* Fix failing test/message.cpp
|
General:
|
||||||
* Complete allocator testing in basic_streambuf, basic_headers
|
* Use SFINAE on return values (search for "class =")
|
||||||
* Tidy up type_checks
|
|
||||||
- Derive from std::integral_constant
|
Boost.Http
|
||||||
* Check DOXYGEN, GENERATIC_DOCS directives in source
|
* Use enum instead of bool in isRequest
|
||||||
- See if we can include them now that xsl is fixed
|
* move version to a subclass of message
|
||||||
* Go over each header and split header material into detail and impl files
|
|
||||||
* Make buffers_debug a detail
|
Docs:
|
||||||
* Roll header-only http parser
|
* Include Example program listings in the docs
|
||||||
* Define Parser concept in HTTP
|
|
||||||
* melpon sandbox?
|
|
||||||
* invokable unit test
|
|
||||||
* trim public interface of rfc2616.h to essentials only
|
|
||||||
* Use new http routines in JSONRPCClient
|
|
||||||
* Remove or change http::headers alias
|
|
||||||
* Do something about the methods.hpp and fields.hpp type headers
|
|
||||||
* Fix index in docs
|
* 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
|
* Figure out why namespace rfc2616 is included in docs
|
||||||
(currently disabled via GENERATING_DOCS macro)
|
(currently disabled via GENERATING_DOCS macro)
|
||||||
* Include Example program listings in the docs
|
* melpon sandbox?
|
||||||
* Update for rfc7230
|
* Check DOXYGEN, GENERATIC_DOCS directives in source
|
||||||
|
- See if we can include them now that xsl is fixed
|
||||||
|
* Implement cleanup-param to remove spaces around template arguments
|
||||||
|
e.g. in basic_streambuf move constructor members
|
||||||
|
|
||||||
|
Core:
|
||||||
|
* Replace Jamroot with Jamfile
|
||||||
|
* Fix bidirectional buffers iterators operator->()
|
||||||
|
* Complete allocator testing in basic_streambuf, basic_headers
|
||||||
|
|
||||||
|
WebSocket:
|
||||||
|
* optimized versions of key/masking, choose prepared_key size
|
||||||
|
* invokable unit test
|
||||||
|
* Finish up all of static_string including tests
|
||||||
|
* Don't rely on default constructible mutable buffers
|
||||||
|
type in read_frame_op (smb_type). To see the error, use
|
||||||
|
boost::asio::streambuf in websocket_async_echo_peer
|
||||||
|
|
||||||
|
HTTP:
|
||||||
|
* Define Parser concept in HTTP
|
||||||
|
* trim public interface of rfc2616.h to essentials only
|
||||||
|
* add bool should_close(message_v1 const&) to replace the use
|
||||||
|
of eof return value from write and async_write
|
||||||
|
* http type_check, e.g. is_WritableBody
|
||||||
|
* More fine grained parser errors
|
||||||
* HTTP parser size limit with test (configurable?)
|
* HTTP parser size limit with test (configurable?)
|
||||||
* HTTP parser trailers with test
|
* HTTP parser trailers with test
|
||||||
* URL parser, strong URL checking in HTTP parser
|
* URL parser, strong URL checking in HTTP parser
|
||||||
* Fix method, use string instead of enum
|
* Update for rfc7230
|
||||||
* More fine grained parser errors
|
* Consider rename to MessageBody concept
|
||||||
* Fix all the warnings in all projects/build configs
|
|
||||||
* Fix bidirectional buffers iterators operator->()
|
|
||||||
|
|||||||
@@ -103,12 +103,16 @@ WARN_LOGFILE =
|
|||||||
# Configuration options related to the input files
|
# Configuration options related to the input files
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
INPUT = \
|
INPUT = \
|
||||||
|
../include/beast/ \
|
||||||
|
../include/beast/http \
|
||||||
|
../include/beast/websocket \
|
||||||
|
../include/beast/doc_debug.hpp \
|
||||||
|
|
||||||
../include/beast/async_completion.hpp \
|
../include/beast/async_completion.hpp \
|
||||||
../include/beast/basic_streambuf.hpp \
|
../include/beast/basic_streambuf.hpp \
|
||||||
../include/beast/bind_handler.hpp \
|
../include/beast/bind_handler.hpp \
|
||||||
../include/beast/buffer_cat.hpp \
|
../include/beast/buffer_cat.hpp \
|
||||||
../include/beast/buffers_adapter.hpp \
|
../include/beast/buffers_adapter.hpp \
|
||||||
../include/beast/buffers_debug.hpp \
|
|
||||||
../include/beast/consuming_buffers.hpp \
|
../include/beast/consuming_buffers.hpp \
|
||||||
../include/beast/handler_alloc.hpp \
|
../include/beast/handler_alloc.hpp \
|
||||||
../include/beast/http.hpp \
|
../include/beast/http.hpp \
|
||||||
@@ -117,17 +121,20 @@ INPUT = \
|
|||||||
../include/beast/static_streambuf.hpp \
|
../include/beast/static_streambuf.hpp \
|
||||||
../include/beast/streambuf.hpp \
|
../include/beast/streambuf.hpp \
|
||||||
../include/beast/streambuf_readstream.hpp \
|
../include/beast/streambuf_readstream.hpp \
|
||||||
|
../include/beast/to_string.hpp \
|
||||||
../include/beast/type_check.hpp \
|
../include/beast/type_check.hpp \
|
||||||
../include/beast/websocket.hpp \
|
../include/beast/websocket.hpp \
|
||||||
../include/beast/write_streambuf.hpp \
|
../include/beast/write_streambuf.hpp \
|
||||||
../include/beast/http/basic_headers.hpp \
|
../include/beast/http/basic_headers.hpp \
|
||||||
../include/beast/http/basic_parser.hpp \
|
../include/beast/http/basic_parser_v1.hpp \
|
||||||
|
../include/beast/http/body_writer.hpp \
|
||||||
../include/beast/http/chunk_encode.hpp \
|
../include/beast/http/chunk_encode.hpp \
|
||||||
../include/beast/http/empty_body.hpp \
|
../include/beast/http/empty_body.hpp \
|
||||||
../include/beast/http/error.hpp \
|
../include/beast/http/error.hpp \
|
||||||
../include/beast/http/fields.hpp \
|
../include/beast/http/fields.hpp \
|
||||||
../include/beast/http/headers.hpp \
|
../include/beast/http/headers.hpp \
|
||||||
../include/beast/http/message.hpp \
|
../include/beast/http/message.hpp \
|
||||||
|
../include/beast/http/message_v1.hpp \
|
||||||
../include/beast/http/method.hpp \
|
../include/beast/http/method.hpp \
|
||||||
../include/beast/http/parse_error.hpp \
|
../include/beast/http/parse_error.hpp \
|
||||||
../include/beast/http/parser.hpp \
|
../include/beast/http/parser.hpp \
|
||||||
|
|||||||
@@ -115,9 +115,10 @@ int main()
|
|||||||
using namespace beast::http;
|
using namespace beast::http;
|
||||||
|
|
||||||
// Send HTTP request using beast
|
// Send HTTP request using beast
|
||||||
request<empty_body> req({method_t::http_get, "/", 11});
|
request<empty_body> req({"GET", "/", 11});
|
||||||
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
||||||
req.headers.replace("User-Agent", "Beast");
|
req.headers.replace("User-Agent", "Beast");
|
||||||
|
prepare(req);
|
||||||
write(sock, req);
|
write(sock, req);
|
||||||
|
|
||||||
// Receive and print HTTP response using beast
|
// Receive and print HTTP response using beast
|
||||||
@@ -130,8 +131,8 @@ int main()
|
|||||||
|
|
||||||
Establish a WebSocket connection, send a message and receive the reply:
|
Establish a WebSocket connection, send a message and receive the reply:
|
||||||
```
|
```
|
||||||
|
#include <beast/to_string.hpp>
|
||||||
#include <beast/websocket.hpp>
|
#include <beast/websocket.hpp>
|
||||||
#include <beast/buffers_debug.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -158,8 +159,7 @@ int main()
|
|||||||
opcode op;
|
opcode op;
|
||||||
ws.read(op, sb);
|
ws.read(op, sb);
|
||||||
ws.close(close_code::normal);
|
ws.close(close_code::normal);
|
||||||
std::cout <<
|
std::cout << to_string(sb.data()) << "\n";
|
||||||
beast::debug::buffers_to_string(sb.data()) << "\n";
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -186,7 +186,12 @@ documentation is based.
|
|||||||
|
|
||||||
[include http.qbk]
|
[include http.qbk]
|
||||||
[include websocket.qbk]
|
[include websocket.qbk]
|
||||||
[include types.qbk]
|
|
||||||
|
[section:types Type Requirements]
|
||||||
|
[include core_types.qbk]
|
||||||
|
[include http_types.qbk]
|
||||||
|
[endsect]
|
||||||
|
|
||||||
[include design.qbk]
|
[include design.qbk]
|
||||||
[section:quickref Quick Reference]
|
[section:quickref Quick Reference]
|
||||||
[xinclude quickref.xml]
|
[xinclude quickref.xml]
|
||||||
|
|||||||
118
src/beast/doc/core_types.qbk
Normal file
118
src/beast/doc/core_types.qbk
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
[/
|
||||||
|
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)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:BufferSequence BufferSequence]
|
||||||
|
|
||||||
|
A `BufferSequence` is a type meeting either of the following requirements:
|
||||||
|
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*`MutableBufferSequence`]]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:stream Streams]
|
||||||
|
|
||||||
|
Stream types represent objects capable of performing synchronous or
|
||||||
|
asynchronous I/O. They are based on concepts from `boost::asio`.
|
||||||
|
|
||||||
|
[heading:Stream Stream]
|
||||||
|
|
||||||
|
A type modeling [*`Stream`] meets either or both of the following requirements:
|
||||||
|
|
||||||
|
* [link beast.types.stream.AsyncStream [*`AsyncStream`]]
|
||||||
|
* [link beast.types.stream.SyncStream [*`SyncStream`]]
|
||||||
|
|
||||||
|
[heading:AsyncStream AsyncStream]
|
||||||
|
|
||||||
|
A type modeling [*`AsyncStream`] meets the following requirements:
|
||||||
|
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html [*`AsyncReadStream`]]
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*`AsyncWriteStream`]]
|
||||||
|
|
||||||
|
[heading:SyncStream SyncStream]
|
||||||
|
|
||||||
|
A type modeling [*`SyncStream`] meets the following requirements:
|
||||||
|
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html [*`SyncReadStream`]]
|
||||||
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*`SyncWriteStream`]]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[section:Streambuf Streambuf]
|
||||||
|
|
||||||
|
In the table below:
|
||||||
|
|
||||||
|
* `X` denotes a class
|
||||||
|
* `a` denotes a value of type `X`
|
||||||
|
* `n` denotes a value convertible to `std::size_t`
|
||||||
|
* `U`, `T` denote unspecified types.
|
||||||
|
|
||||||
|
[table Streambuf requirements
|
||||||
|
[[operation] [type] [semantics, pre/post-conditions]]
|
||||||
|
[
|
||||||
|
[`X::const_buffers_type`]
|
||||||
|
[`T`]
|
||||||
|
[`T` meets the requirements for `ConstBufferSequence`.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`X::mutable_buffers_type`]
|
||||||
|
[`U`]
|
||||||
|
[`U` meets the requirements for `MutableBufferSequence`.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.commit(n)`]
|
||||||
|
[`void`]
|
||||||
|
[Moves bytes from the output sequence to the input sequence.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.consume(n)`]
|
||||||
|
[`void`]
|
||||||
|
[Removes bytes from the input sequence.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.data()`]
|
||||||
|
[`T`]
|
||||||
|
[Returns a list of buffers that represents the input sequence.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.prepare(n)`]
|
||||||
|
[`U`]
|
||||||
|
[Returns a list of buffers that represents the output sequence, with
|
||||||
|
the given size.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.size()`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[Returns the size of the input sequence.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.max_size()`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[Returns the maximum size of the `Streambuf`.]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`read_size_helper(a, n)`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[
|
||||||
|
Returns the suggested number of bytes to read into the output
|
||||||
|
sequence where `n` is an upper limit on this value. One possible
|
||||||
|
implementation is to return the number of bytes that may be prepared
|
||||||
|
without causing a dynamic allocation or `n`, whichever is smaller.
|
||||||
|
Calls to `read_size_helper` will be made without namespace
|
||||||
|
qualification, to allow the rules for argument dependent lookup to
|
||||||
|
take effect.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
[section:design Design choices]
|
[section:design Design choices]
|
||||||
|
|
||||||
The implementations are driven by business needs of cryptocurrency server
|
The implementations are driven by business needs of cryptocurrency server
|
||||||
applications ([link https://ripple.com Ripple] written in C++. These
|
applications ([@https://ripple.com Ripple] written in C++. These
|
||||||
needs were not met by existing solutions so new code was written. The new
|
needs were not met by existing solutions so new code was written. The new
|
||||||
code tries to avoid design flaws encountered in the already-existing software
|
code tries to avoid design flaws encountered in the already-existing software
|
||||||
libraries:
|
libraries:
|
||||||
@@ -194,8 +194,8 @@ start. Other design goals:
|
|||||||
|
|
||||||
The WebSocket implementation [*does] provides support for shutting down
|
The WebSocket implementation [*does] provides support for shutting down
|
||||||
the TLS connection through the use of the ADL compile-time virtual functions
|
the TLS connection through the use of the ADL compile-time virtual functions
|
||||||
[link beast.ref.wsproto__teardown `teardown`] and
|
[link beast.ref.websocket__teardown `teardown`] and
|
||||||
[link beast.ref.wsproto__async_teardown `async_teardown`]. These will
|
[link beast.ref.websocket__async_teardown `async_teardown`]. These will
|
||||||
properly close the connection as per rfc6455 and overloads are available
|
properly close the connection as per rfc6455 and overloads are available
|
||||||
for TLS streams. Callers may provide their own overloads of these functions
|
for TLS streams. Callers may provide their own overloads of these functions
|
||||||
for user-defined next layer types.
|
for user-defined next layer types.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
Beast.HTTP offers programmers simple and performant models of HTTP messages and
|
Beast.HTTP offers programmers simple and performant models of HTTP messages and
|
||||||
their associated operations including synchronous and asynchronous reading and
|
their associated operations including synchronous and asynchronous reading and
|
||||||
writing using Boost.Asio.
|
writing of messages in the HTTP/1 wire format using Boost.Asio.
|
||||||
|
|
||||||
The HTTP protocol is described fully in
|
The HTTP protocol is described fully in
|
||||||
[@https://tools.ietf.org/html/rfc2616 rfc2616]
|
[@https://tools.ietf.org/html/rfc2616 rfc2616]
|
||||||
@@ -25,20 +25,43 @@ compliant with the Hypertext Transfer Protocol and the supplements that
|
|||||||
follow. Unfortunately reliable implementations or industry standards do not
|
follow. Unfortunately reliable implementations or industry standards do not
|
||||||
exist in C++.
|
exist in C++.
|
||||||
|
|
||||||
Beast.HTTP is built on Boost.Asio and uses HTTP parser from NodeJS, which is
|
Beast.HTTP is built on Boost.Asio and uses its own robust header-only HTTP/1
|
||||||
extensively field tested and exceptionally robust. A proposal to add networking
|
message parser modeled after the nodejs http-parser (written in C). A proposal
|
||||||
functionality to the C++ standard library, based on Boost.Asio, is under
|
to add networking functionality to the C++ standard library, based on
|
||||||
consideration by the standards committee. Since the final approved networking
|
Boost.Asio, is under consideration by the standards committee. Since the final
|
||||||
interface for the C++ standard library will likely closely resemble the current
|
approved networking interface for the C++ standard library will likely closely
|
||||||
interface of Boost.Asio, it is logical for Beast.HTTP to use Boost.Asio as its
|
resemble the current interface of Boost.Asio, it is logical for Beast.HTTP to
|
||||||
network transport.
|
use Boost.Asio as its network transport.
|
||||||
|
|
||||||
[heading Scope]
|
[endsect]
|
||||||
|
|
||||||
The scope of this library is meant to include only the functionality of
|
|
||||||
modeling the HTTP message, serializing and deserializing the message, and
|
|
||||||
sending and receiving messages on sockets or streams. It is designed to
|
[section:scope Scope]
|
||||||
be a building block for creating higher level abstractions.
|
|
||||||
|
This library is designed to be a building block for creating higher level
|
||||||
|
libraries. It is not designed to be end-user facing. There is no convenient
|
||||||
|
class that implements the core of a web server, nor is there a convenient
|
||||||
|
class to quickly perform common operations such as fetching a file or
|
||||||
|
connecting and retrieving a document from a secure connection. These
|
||||||
|
use-cases are important. But this library does not try to do that. Instead,
|
||||||
|
it offers primitives that can be used to build those user-facing algorithms.
|
||||||
|
|
||||||
|
A HTTP message (referred to hereafter as "message") contains request or
|
||||||
|
response specific attributes, 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. 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.
|
||||||
|
Beast aims to offer this functionality:
|
||||||
|
|
||||||
|
* [*Model]: Provide a universal HTTP message class model.
|
||||||
|
|
||||||
|
* [*Build]: Construct a new message and manipulate its contents.
|
||||||
|
|
||||||
|
* [*Parse]: Deserialize a message from a network or memory stream in HTTP/1 wire format.
|
||||||
|
|
||||||
|
* [*Serialize]: Serialize a message into a network or memory stream in HTTP/1 wire format.
|
||||||
|
|
||||||
[note The documentation which follows assumes familiarity with
|
[note The documentation which follows assumes familiarity with
|
||||||
both Boost.Asio and the HTTP protocol specification described in
|
both Boost.Asio and the HTTP protocol specification described in
|
||||||
@@ -59,35 +82,17 @@ both Boost.Asio and the HTTP protocol specification described in
|
|||||||
```
|
```
|
||||||
]
|
]
|
||||||
|
|
||||||
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. 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.
|
|
||||||
|
|
||||||
* [*Assemble] a new message from scratch or from an existing message.
|
In the paragraphs that follow we describe the available interfaces for
|
||||||
|
performing typical operations such as interacting with a HTTP server
|
||||||
* [*Serialize] a message into a series of octets.
|
or handling simple requests. Subsequent sections cover the message model
|
||||||
|
and its customization points in more depth, for advanced applications.
|
||||||
* [*Read] a message from a stream. This can be thought of as a compound
|
|
||||||
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]
|
[heading Declarations]
|
||||||
|
|
||||||
To do anything, a message must be declared. The message class template
|
To do anything, a message must be declared. The message class template
|
||||||
requires at mininum, a bool indicating whether the message is a request
|
requires at mininum, a value indicating whether the message is a request
|
||||||
(versus a response), and a `Body` type. The choice of `Body` determines the
|
(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
|
kind of container used to represent the message body. Here we will
|
||||||
declare a request that has a `std::string` for the body container:
|
declare a request that has a `std::string` for the body container:
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
]
|
]
|
||||||
|
|
||||||
[section:types Type Requirements]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:Body Body]
|
[section:Body Body]
|
||||||
@@ -57,10 +55,10 @@ In this table:
|
|||||||
|
|
||||||
[section:BufferSequence BufferSequence]
|
[section:BufferSequence BufferSequence]
|
||||||
|
|
||||||
A `BufferSequence` meets [*one of] the following requirements:
|
A `BufferSequence` is a type meeting either of the following requirements:
|
||||||
|
|
||||||
* `ConstBufferSequence`
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]
|
||||||
* `MutableBufferSequence`
|
* [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*`MutableBufferSequence`]]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ In this table:
|
|||||||
* `m` denotes a value of type `message const&` where
|
* `m` denotes a value of type `message const&` where
|
||||||
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
|
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
|
||||||
|
|
||||||
* `rc` is an object of type [link beast.reference.http__resume_context resume_context].
|
* `rc` is an object of type [link beast.ref.http__resume_context resume_context].
|
||||||
|
|
||||||
* `ec` is a value of type `error_code&`.
|
* `ec` is a value of type `error_code&`.
|
||||||
|
|
||||||
@@ -252,7 +250,7 @@ In this table:
|
|||||||
]
|
]
|
||||||
[
|
[
|
||||||
[`a.content_length()`]
|
[`a.content_length()`]
|
||||||
[`std::size_t`]
|
[`std::uint64_t`]
|
||||||
[
|
[
|
||||||
If this member is present, it is called after initialization
|
If this member is present, it is called after initialization
|
||||||
and before calls to provide buffers. The serialized message will
|
and before calls to provide buffers. The serialized message will
|
||||||
@@ -373,74 +371,3 @@ public:
|
|||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:Stream Stream]
|
|
||||||
|
|
||||||
A `Stream` meets the following requirements:
|
|
||||||
|
|
||||||
* `SyncReadStream`
|
|
||||||
* `SyncWriteStream`
|
|
||||||
* `AsyncReadStream`
|
|
||||||
* `AsyncWriteStream`
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[section:Streambuf Streambuf]
|
|
||||||
|
|
||||||
In the table below, `X` denotes a class, `a` denotes a value
|
|
||||||
of type `X`, `n` denotes a value convertible to `std::size_t`,
|
|
||||||
and `U` and `T` denote unspecified types.
|
|
||||||
|
|
||||||
[table Streambuf requirements
|
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
|
||||||
[
|
|
||||||
[`X::const_buffers_type`]
|
|
||||||
[`T`]
|
|
||||||
[`T` meets the requirements for `ConstBufferSequence`.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`X::mutable_buffers_type`]
|
|
||||||
[`U`]
|
|
||||||
[`U` meets the requirements for `MutableBufferSequence`.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.commit(n)`]
|
|
||||||
[`void`]
|
|
||||||
[Moves bytes from the output sequence to the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.consume(n)`]
|
|
||||||
[`void`]
|
|
||||||
[Removes bytes from the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.data()`]
|
|
||||||
[`T`]
|
|
||||||
[Returns a list of buffers that represents the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.prepare(n)`]
|
|
||||||
[`U`]
|
|
||||||
[Returns a list of buffers that represents the output sequence, with
|
|
||||||
the given size.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.size()`]
|
|
||||||
[`std::size_t`]
|
|
||||||
[Returns the size of the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.max_size()`]
|
|
||||||
[`std::size_t`]
|
|
||||||
[Returns the maximum size of the `Streambuf`.]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
@@ -30,10 +30,11 @@
|
|||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
|
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_parser">basic_parser</link></member>
|
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_streambuf_body">basic_streambuf_body</link></member>
|
<member><link linkend="beast.ref.http__basic_streambuf_body">basic_streambuf_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
|
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__error_code">error_code</link></member>
|
<member><link linkend="beast.ref.http__error_code">error_code</link></member>
|
||||||
|
<member><link linkend="beast.ref.http__headers">headers</link></member>
|
||||||
<member><link linkend="beast.ref.http__message">message</link></member>
|
<member><link linkend="beast.ref.http__message">message</link></member>
|
||||||
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
|
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
|
||||||
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
|
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
|
||||||
@@ -41,7 +42,7 @@
|
|||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
|
<member><link linkend="beast.ref.http__is_Parser">is_Parser</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
@@ -49,11 +50,14 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__async_read">async_read</link></member>
|
<member><link linkend="beast.ref.http__async_read">async_read</link></member>
|
||||||
<member><link linkend="beast.ref.http__async_write">async_write</link></member>
|
<member><link linkend="beast.ref.http__async_write">async_write</link></member>
|
||||||
<member><link linkend="beast.ref.http__chunk_encode">chunk_encode</link></member>
|
<member><link linkend="beast.ref.http__prepare">prepare</link></member>
|
||||||
<member><link linkend="beast.ref.http__chunk_encode_final">chunk_encode_final</link></member>
|
|
||||||
<member><link linkend="beast.ref.http__read">read</link></member>
|
<member><link linkend="beast.ref.http__read">read</link></member>
|
||||||
<member><link linkend="beast.ref.http__write">write</link></member>
|
<member><link linkend="beast.ref.http__write">write</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
|
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.http__connection">connection</link></member>
|
||||||
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.types.Body">Body</link></member>
|
<member><link linkend="beast.types.Body">Body</link></member>
|
||||||
@@ -67,7 +71,6 @@
|
|||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.websocket__close_reason">close_reason</link></member>
|
<member><link linkend="beast.ref.websocket__close_reason">close_reason</link></member>
|
||||||
<member><link linkend="beast.ref.websocket__static_string">static_string</link></member>
|
|
||||||
<member><link linkend="beast.ref.websocket__stream">stream</link></member>
|
<member><link linkend="beast.ref.websocket__stream">stream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Options</bridgehead>
|
<bridgehead renderas="sect3">Options</bridgehead>
|
||||||
@@ -120,6 +123,7 @@
|
|||||||
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
|
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
|
||||||
<member><link linkend="beast.ref.static_streambuf">static_streambuf</link></member>
|
<member><link linkend="beast.ref.static_streambuf">static_streambuf</link></member>
|
||||||
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
|
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
|
||||||
|
<member><link linkend="beast.ref.static_string">static_string</link></member>
|
||||||
<member><link linkend="beast.ref.streambuf">streambuf</link></member>
|
<member><link linkend="beast.ref.streambuf">streambuf</link></member>
|
||||||
<member><link linkend="beast.ref.streambuf_readstream">streambuf_readstream</link></member>
|
<member><link linkend="beast.ref.streambuf_readstream">streambuf_readstream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
@@ -129,23 +133,28 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.bind_handler">bind_handler</link></member>
|
<member><link linkend="beast.ref.bind_handler">bind_handler</link></member>
|
||||||
<member><link linkend="beast.ref.buffer_cat">buffer_cat</link></member>
|
<member><link linkend="beast.ref.buffer_cat">buffer_cat</link></member>
|
||||||
|
<member><link linkend="beast.ref.consumed_buffers">consumed_buffers</link></member>
|
||||||
<member><link linkend="beast.ref.prepare_buffer">prepare_buffer</link></member>
|
<member><link linkend="beast.ref.prepare_buffer">prepare_buffer</link></member>
|
||||||
<member><link linkend="beast.ref.prepare_buffers">prepare_buffers</link></member>
|
<member><link linkend="beast.ref.prepare_buffers">prepare_buffers</link></member>
|
||||||
|
<member><link linkend="beast.ref.to_string">to_string</link></member>
|
||||||
|
|
||||||
<member><link linkend="beast.ref.write">write</link></member>
|
<member><link linkend="beast.ref.write">write</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
|
|
||||||
<member><link linkend="beast.ref.is_AsyncReadStream">is_AsyncReadStream</link></member>
|
<member><link linkend="beast.ref.is_AsyncReadStream">is_AsyncReadStream</link></member>
|
||||||
<member><link linkend="beast.ref.is_AsyncWriteStream">is_AsyncWriteStream</link></member>
|
<member><link linkend="beast.ref.is_AsyncWriteStream">is_AsyncWriteStream</link></member>
|
||||||
|
<member><link linkend="beast.ref.is_AsyncStream">is_AsyncStream</link></member>
|
||||||
<member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member>
|
<member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member>
|
||||||
|
<member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member>
|
||||||
<member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member>
|
<member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_Handler">is_Handler</link></member>
|
|
||||||
<member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member>
|
<member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_Stream">is_Stream</link></member>
|
|
||||||
<member><link linkend="beast.ref.is_Streambuf">is_Streambuf</link></member>
|
<member><link linkend="beast.ref.is_Streambuf">is_Streambuf</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
|
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
|
||||||
|
<member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
|
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -153,8 +162,30 @@
|
|||||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
|
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
|
||||||
<member><link linkend="beast.types.Stream">Stream</link></member>
|
<member><link linkend="beast.types.stream.AsyncStream">AsyncStream</link></member>
|
||||||
|
<member><link linkend="beast.types.stream.Stream">Stream</link></member>
|
||||||
<member><link linkend="beast.types.Streambuf">Streambuf</link></member>
|
<member><link linkend="beast.types.Streambuf">Streambuf</link></member>
|
||||||
|
<member><link linkend="beast.types.stream.SyncStream">SyncStream</link></member>
|
||||||
|
</simplelist>
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
<tgroup cols="1">
|
||||||
|
<colspec colname="a"/>
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry valign="center" namest="a" nameend="a">
|
||||||
|
<bridgehead renderas="sect2">Diagnostic</bridgehead>
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry valign="top">
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.doc_debug">doc_debug</link></member>
|
||||||
|
<member><link linkend="beast.ref.nested__nested_doc_debug">nested_doc_debug</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<xsl:when test="@kind='class' or @kind='struct'">
|
<xsl:when test="@kind='class' or @kind='struct'">
|
||||||
<xsl:if test="
|
<xsl:if test="
|
||||||
contains(compoundname, 'beast::') and
|
contains(compoundname, 'beast::') and
|
||||||
|
not(contains(compoundname, 'boost::')) and
|
||||||
not(contains(compoundname, '::detail')) and
|
not(contains(compoundname, '::detail')) and
|
||||||
not(contains(compoundname, 'rfc2616')) and
|
not(contains(compoundname, 'rfc2616')) and
|
||||||
not(contains(@prot, 'private'))">
|
not(contains(@prot, 'private'))">
|
||||||
@@ -61,7 +62,6 @@
|
|||||||
<xsl:text>
[endsect]</xsl:text>
|
<xsl:text>
[endsect]</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
<!--========== Utilities ==========-->
|
<!--========== Utilities ==========-->
|
||||||
|
|
||||||
<xsl:template name="strip-beast-ns">
|
<xsl:template name="strip-beast-ns">
|
||||||
@@ -73,6 +73,9 @@
|
|||||||
<xsl:when test="contains($name, 'beast::')">
|
<xsl:when test="contains($name, 'beast::')">
|
||||||
<xsl:value-of select="substring-after($name, 'beast::')"/>
|
<xsl:value-of select="substring-after($name, 'beast::')"/>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
<xsl:when test="$name = 'beast'">
|
||||||
|
<xsl:text></xsl:text>
|
||||||
|
</xsl:when>
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:value-of select="$name"/>
|
<xsl:value-of select="$name"/>
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
@@ -108,6 +111,38 @@
|
|||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="cleanup-param">
|
||||||
|
<xsl:param name="name"/>
|
||||||
|
<xsl:variable name="clean">
|
||||||
|
<xsl:value-of select="$name"/>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="' *' = substring($clean, string-length($clean) - 1)">
|
||||||
|
<xsl:value-of select="substring($clean, 1, string-length($clean) - 2)"/>
|
||||||
|
<xsl:text>*</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="' &' = substring($clean, string-length($clean) - 1)">
|
||||||
|
<xsl:value-of select="substring($clean, 1, string-length($clean) - 2)"/>
|
||||||
|
<xsl:text>&</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="' &...' = substring($clean, string-length($clean) - 4)">
|
||||||
|
<xsl:value-of select="substring($clean, 1, string-length($clean) - 5)"/>
|
||||||
|
<xsl:text>&...</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="' &&' = substring($clean, string-length($clean) - 2)">
|
||||||
|
<xsl:value-of select="substring($clean, 1, string-length($clean) - 3)"/>
|
||||||
|
<xsl:text>&&</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="' &&...' = substring($clean, string-length($clean) - 5)">
|
||||||
|
<xsl:value-of select="substring($clean, 1, string-length($clean) - 6)"/>
|
||||||
|
<xsl:text>&&...</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="$clean"/>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="cleanup-type">
|
<xsl:template name="cleanup-type">
|
||||||
<xsl:param name="name"/>
|
<xsl:param name="name"/>
|
||||||
<xsl:variable name="type">
|
<xsl:variable name="type">
|
||||||
@@ -124,20 +159,22 @@
|
|||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:choose>
|
<xsl:variable name="cleaned">
|
||||||
<xsl:when test="$type='ConstBufferSequence'">
|
<xsl:choose>
|
||||||
<xsl:text>``[link beast.ref.ConstBufferSequence ['ConstBufferSequence]]``</xsl:text>
|
<xsl:when test="$type='implementation_defined'">
|
||||||
</xsl:when>
|
<xsl:text>``['implementation-defined]``</xsl:text>
|
||||||
<xsl:when test="$type='implementation_defined'">
|
</xsl:when>
|
||||||
<xsl:text>``['implementation-defined]``</xsl:text>
|
<xsl:when test="$type='void_or_deduced'">
|
||||||
</xsl:when>
|
<xsl:text>``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]``</xsl:text>
|
||||||
<xsl:when test="$type='void_or_deduced'">
|
</xsl:when>
|
||||||
<xsl:text>``[link beast.ref.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]``</xsl:text>
|
<xsl:otherwise>
|
||||||
</xsl:when>
|
<xsl:value-of select="$type"/>
|
||||||
<xsl:otherwise>
|
</xsl:otherwise>
|
||||||
<xsl:value-of select="$type"/>
|
</xsl:choose>
|
||||||
</xsl:otherwise>
|
</xsl:variable>
|
||||||
</xsl:choose>
|
<xsl:call-template name="cleanup-param">
|
||||||
|
<xsl:with-param name="name" select="$cleaned"/>
|
||||||
|
</xsl:call-template>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="make-id">
|
<xsl:template name="make-id">
|
||||||
@@ -260,8 +297,9 @@
|
|||||||
<!--========== Markup ==========-->
|
<!--========== Markup ==========-->
|
||||||
|
|
||||||
<xsl:template match="para" mode="markup">
|
<xsl:template match="para" mode="markup">
|
||||||
<xsl:apply-templates mode="markup"/>
|
<xsl:value-of select="$newline"/>
|
||||||
<xsl:text>
</xsl:text>
|
<xsl:apply-templates mode="markup"/>
|
||||||
|
<xsl:value-of select="$newline"/>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="para" mode="markup-nested">
|
<xsl:template match="para" mode="markup-nested">
|
||||||
@@ -391,6 +429,8 @@
|
|||||||
<xsl:apply-templates mode="markup"/>
|
<xsl:apply-templates mode="markup"/>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="@kind='see'">
|
<xsl:when test="@kind='see'">
|
||||||
|
<xsl:text>[heading See Also]
</xsl:text>
|
||||||
|
<xsl:apply-templates mode="markup"/>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="@kind='note'">
|
<xsl:when test="@kind='note'">
|
||||||
<xsl:text>[heading Remarks]
</xsl:text>
|
<xsl:text>[heading Remarks]
</xsl:text>
|
||||||
@@ -536,12 +576,13 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="ref[@kindref='compound']" mode="markup">
|
<xsl:template match="ref[@kindref='compound']" mode="markup">
|
||||||
<xsl:variable name="name">
|
<xsl:variable name="name">
|
||||||
<xsl:value-of select="."/>
|
<xsl:value-of select="."/>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="contains(@refid, 'asio') or contains($name, 'asio::')">
|
<xsl:when test="contains(@refid, 'beast')">
|
||||||
<xsl:variable name="dox-ref-id" select="@refid"/>
|
<xsl:variable name="dox-ref-id" select="@refid"/>
|
||||||
<xsl:variable name="ref-name">
|
<xsl:variable name="ref-name">
|
||||||
<xsl:call-template name="strip-beast-ns">
|
<xsl:call-template name="strip-beast-ns">
|
||||||
@@ -554,6 +595,14 @@
|
|||||||
<xsl:with-param name="name" select="$ref-name"/>
|
<xsl:with-param name="name" select="$ref-name"/>
|
||||||
</xsl:call-template>
|
</xsl:call-template>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
|
<!--<xsl:text>|1|</xsl:text>-->
|
||||||
|
<!--
|
||||||
|
<xsl:text>[role red ref-name='</xsl:text>
|
||||||
|
<xsl:value-of select="$ref-name"/>
|
||||||
|
<xsl:text>'|ref-id='</xsl:text>
|
||||||
|
<xsl:value-of select="$ref-id"/>
|
||||||
|
<xsl:text>']|</xsl:text>
|
||||||
|
-->
|
||||||
<xsl:text>[link beast.ref.</xsl:text>
|
<xsl:text>[link beast.ref.</xsl:text>
|
||||||
<xsl:value-of select="$ref-id"/>
|
<xsl:value-of select="$ref-id"/>
|
||||||
<xsl:text> `</xsl:text>
|
<xsl:text> `</xsl:text>
|
||||||
@@ -561,89 +610,106 @@
|
|||||||
<xsl:text>`]</xsl:text>
|
<xsl:text>`]</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:text>`</xsl:text>
|
<xsl:text>[role red |1|</xsl:text>
|
||||||
<xsl:value-of select="."/>
|
<xsl:value-of select="."/>
|
||||||
<xsl:text>`</xsl:text>
|
<xsl:text>]</xsl:text>
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="ref[@kindref='member']" mode="markup">
|
||||||
|
<xsl:variable name="name">
|
||||||
|
<xsl:value-of select="."/>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:variable name="dox-ref-id" select="@refid"/>
|
||||||
|
<xsl:variable name="memberdefs" select="/doxygen//compounddef/sectiondef/memberdef[@id=$dox-ref-id]"/>
|
||||||
|
<xsl:variable name="def-kind" select="($memberdefs)/../../@kind"/>
|
||||||
|
<xsl:variable name="sec-kind" select="($memberdefs)/../@kind"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="contains(@refid, 'beast') and count($memberdefs) > 0">
|
||||||
|
<xsl:variable name="dox-compound-name" select="($memberdefs)[1]/../../compoundname"/>
|
||||||
|
<xsl:variable name="dox-name" select="($memberdefs)[1]/name"/>
|
||||||
|
<xsl:variable name="ref-name">
|
||||||
|
<xsl:call-template name="strip-beast-ns">
|
||||||
|
<xsl:with-param name="name" select="$dox-compound-name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:variable name="ref-id">
|
||||||
|
<xsl:call-template name="make-id">
|
||||||
|
<xsl:with-param name="name" select="$ref-name"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:variable>
|
||||||
|
<!--<xsl:text>|2|</xsl:text>-->
|
||||||
|
<!--
|
||||||
|
<xsl:text>[role red def-kind='</xsl:text>
|
||||||
|
<xsl:value-of select="$def-kind"/>
|
||||||
|
<xsl:text>', sec-kind='</xsl:text>
|
||||||
|
<xsl:value-of select="$sec-kind"/>
|
||||||
|
<xsl:text>', ref-id='</xsl:text>
|
||||||
|
<xsl:value-of select="$ref-id"/>
|
||||||
|
<xsl:text>'] </xsl:text>
|
||||||
|
-->
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="$def-kind = 'namespace'">
|
||||||
|
<xsl:text>[link beast.ref.</xsl:text>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="string-length($ref-id) > 0">
|
||||||
|
<xsl:value-of select="concat($ref-id,'__',$dox-name)"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="$dox-name"/>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
<xsl:text> `</xsl:text>
|
||||||
|
<xsl:value-of name="text" select="$dox-name"/>
|
||||||
|
<xsl:text>`]</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="$def-kind = 'class' or $def-kind = 'struct'">
|
||||||
|
<xsl:text>[link beast.ref.</xsl:text>
|
||||||
|
<xsl:value-of select="concat($ref-id,'.',$dox-name)"/>
|
||||||
|
<xsl:text> `</xsl:text>
|
||||||
|
<xsl:value-of name="text" select="$name"/>
|
||||||
|
<xsl:text>`]</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:text>[role red </xsl:text>
|
||||||
|
<xsl:value-of select="$name"/>
|
||||||
|
<xsl:text>]</xsl:text>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:text>[role red </xsl:text>
|
||||||
|
<xsl:value-of select="$name"/>
|
||||||
|
<xsl:text>]</xsl:text>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="ref[@kindref='compound']" mode="markup-nested">
|
<xsl:template match="ref[@kindref='compound']" mode="markup-nested">
|
||||||
<xsl:variable name="name">
|
<xsl:variable name="name">
|
||||||
<xsl:value-of select="."/>
|
<xsl:value-of select="."/>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:choose>
|
<xsl:text>[role red |3|</xsl:text>
|
||||||
<xsl:when test="contains(@refid, 'asio') or contains($name, 'asio::')">
|
<xsl:value-of select="."/>
|
||||||
<xsl:variable name="dox-ref-id" select="@refid"/>
|
<xsl:text>]</xsl:text>
|
||||||
<xsl:variable name="ref-name">
|
|
||||||
<xsl:call-template name="strip-beast-ns">
|
|
||||||
<xsl:with-param name="name"
|
|
||||||
select="(/doxygen//compounddef[@id=$dox-ref-id])[1]/compoundname"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
<xsl:variable name="ref-id">
|
|
||||||
<xsl:call-template name="make-id">
|
|
||||||
<xsl:with-param name="name" select="$ref-name"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
<xsl:text>[link beast.ref.</xsl:text>
|
|
||||||
<xsl:value-of select="$ref-id"/>
|
|
||||||
<xsl:text> `</xsl:text>
|
|
||||||
<xsl:value-of name="text" select="$ref-name"/>
|
|
||||||
<xsl:text>`]</xsl:text>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<xsl:text>`</xsl:text>
|
|
||||||
<xsl:value-of select="."/>
|
|
||||||
<xsl:text>`</xsl:text>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="ref[@kindref='member']" mode="markup">
|
|
||||||
<xsl:variable name="dox-ref-id" select="@refid"/>
|
|
||||||
<xsl:variable name="memberdefs" select="/doxygen//compounddef/sectiondef/memberdef[@id=$dox-ref-id]"/>
|
|
||||||
<xsl:choose>
|
|
||||||
<xsl:when test="contains(@refid, 'namespaceboost_1_1asio') and count($memberdefs) > 0">
|
|
||||||
<xsl:variable name="dox-compound-name" select="($memberdefs)[1]/../../compoundname"/>
|
|
||||||
<xsl:variable name="dox-name" select="($memberdefs)[1]/name"/>
|
|
||||||
<xsl:variable name="ref-name">
|
|
||||||
<xsl:call-template name="strip-beast-ns">
|
|
||||||
<xsl:with-param name="name" select="concat($dox-compound-name,'::',$dox-name)"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
<xsl:variable name="ref-id">
|
|
||||||
<xsl:call-template name="make-id">
|
|
||||||
<xsl:with-param name="name" select="$ref-name"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:variable>
|
|
||||||
<xsl:text>[link beast.ref.</xsl:text>
|
|
||||||
<xsl:value-of select="$ref-id"/>
|
|
||||||
<xsl:text> `</xsl:text>
|
|
||||||
<xsl:value-of name="text" select="$ref-name"/>
|
|
||||||
<xsl:text>`]</xsl:text>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<xsl:text>`</xsl:text>
|
|
||||||
<xsl:value-of select="."/>
|
|
||||||
<xsl:text>`</xsl:text>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
</xsl:template>
|
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="ref[@kindref='member']" mode="markup-nested">
|
<xsl:template match="ref[@kindref='member']" mode="markup-nested">
|
||||||
|
<xsl:variable name="name">
|
||||||
|
<xsl:value-of select="."/>
|
||||||
|
</xsl:variable>
|
||||||
<xsl:variable name="dox-ref-id" select="@refid"/>
|
<xsl:variable name="dox-ref-id" select="@refid"/>
|
||||||
<xsl:variable name="memberdefs" select="/doxygen//compounddef/sectiondef/memberdef[@id=$dox-ref-id]"/>
|
<xsl:variable name="memberdefs" select="/doxygen//compounddef/sectiondef/memberdef[@id=$dox-ref-id]"/>
|
||||||
|
<xsl:variable name="def-kind" select="($memberdefs)/../../@kind"/>
|
||||||
|
<xsl:variable name="sec-kind" select="($memberdefs)/../@kind"/>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="contains(@refid, 'namespaceboost_1_1asio') and count($memberdefs) > 0">
|
<xsl:when test="contains(@refid, 'beast') and count($memberdefs) > 0">
|
||||||
<xsl:variable name="dox-compound-name" select="($memberdefs)[1]/../../compoundname"/>
|
<xsl:variable name="dox-compound-name" select="($memberdefs)[1]/../../compoundname"/>
|
||||||
<xsl:variable name="dox-name" select="($memberdefs)[1]/name"/>
|
<xsl:variable name="dox-name" select="($memberdefs)[1]/name"/>
|
||||||
<xsl:variable name="ref-name">
|
<xsl:variable name="ref-name">
|
||||||
<xsl:call-template name="strip-beast-ns">
|
<xsl:call-template name="strip-beast-ns">
|
||||||
<xsl:with-param name="name" select="concat($dox-compound-name,'::',$dox-name)"/>
|
<xsl:with-param name="name" select="$dox-compound-name"/>
|
||||||
</xsl:call-template>
|
</xsl:call-template>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:variable name="ref-id">
|
<xsl:variable name="ref-id">
|
||||||
@@ -651,16 +717,49 @@
|
|||||||
<xsl:with-param name="name" select="$ref-name"/>
|
<xsl:with-param name="name" select="$ref-name"/>
|
||||||
</xsl:call-template>
|
</xsl:call-template>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:text>[link beast.ref.</xsl:text>
|
<!--<xsl:text>|2|</xsl:text>-->
|
||||||
|
<!--
|
||||||
|
<xsl:text>[role red def-kind='</xsl:text>
|
||||||
|
<xsl:value-of select="$def-kind"/>
|
||||||
|
<xsl:text>', sec-kind='</xsl:text>
|
||||||
|
<xsl:value-of select="$sec-kind"/>
|
||||||
|
<xsl:text>', ref-id='</xsl:text>
|
||||||
<xsl:value-of select="$ref-id"/>
|
<xsl:value-of select="$ref-id"/>
|
||||||
<xsl:text> `</xsl:text>
|
<xsl:text>'] </xsl:text>
|
||||||
<xsl:value-of name="text" select="$ref-name"/>
|
-->
|
||||||
<xsl:text>`]</xsl:text>
|
<xsl:choose>
|
||||||
|
<xsl:when test="$def-kind = 'namespace'">
|
||||||
|
<xsl:text>[link beast.ref.</xsl:text>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="string-length($ref-id) > 0">
|
||||||
|
<xsl:value-of select="concat($ref-id,'__',$dox-name)"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="$dox-name"/>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
<xsl:text> `</xsl:text>
|
||||||
|
<xsl:value-of name="text" select="$dox-name"/>
|
||||||
|
<xsl:text>`]</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="$def-kind = 'class' or $def-kind = 'struct'">
|
||||||
|
<xsl:text>[link beast.ref.</xsl:text>
|
||||||
|
<xsl:value-of select="concat($ref-id,'.',$dox-name)"/>
|
||||||
|
<xsl:text> `</xsl:text>
|
||||||
|
<xsl:value-of name="text" select="$name"/>
|
||||||
|
<xsl:text>`]</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:text>[role red </xsl:text>
|
||||||
|
<xsl:value-of select="$name"/>
|
||||||
|
<xsl:text>]</xsl:text>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:text>`</xsl:text>
|
<xsl:text>[role red </xsl:text>
|
||||||
<xsl:value-of select="."/>
|
<xsl:value-of select="$name"/>
|
||||||
<xsl:text>`</xsl:text>
|
<xsl:text>]</xsl:text>
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
@@ -1185,7 +1284,8 @@
|
|||||||
</xsl:call-template>
|
</xsl:call-template>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:if test="string-length($stripped-type) > 0">
|
<xsl:if test="string-length($stripped-type) > 0">
|
||||||
<xsl:value-of select="$stripped-type"/><xsl:text> </xsl:text>
|
<xsl:value-of select="$stripped-type"/>
|
||||||
|
<xsl:text>
</xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:text>``[link beast.ref.</xsl:text>
|
<xsl:text>``[link beast.ref.</xsl:text>
|
||||||
<xsl:value-of select="$class-id"/>
|
<xsl:value-of select="$class-id"/>
|
||||||
@@ -1412,21 +1512,62 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="templateparamlist" mode="class-detail">
|
<xsl:template match="templateparamlist" mode="class-detail">
|
||||||
<xsl:text>template<
</xsl:text>
|
<xsl:text>template<
</xsl:text>
|
||||||
<xsl:apply-templates select="param" mode="class-detail-template"/>
|
<xsl:apply-templates select="param" mode="class-detail-template"/>
|
||||||
<xsl:text>>
</xsl:text>
|
<xsl:text>>
</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="param" mode="class-detail-template">
|
<xsl:template match="param" mode="class-detail-template">
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
|
<xsl:when test="type = 'class AsyncStream'">
|
||||||
|
<xsl:text>class ``[link beast.types.stream.AsyncStream [*AsyncStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="type = 'class AsyncReadStream'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="type = 'class AsyncWriteStream'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
<xsl:when test="type = 'class Body'">
|
<xsl:when test="type = 'class Body'">
|
||||||
<xsl:text>class ``[link beast.types.Body [*Body]]``</xsl:text>
|
<xsl:text>class ``[link beast.types.Body [*Body]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="type = 'class Streambuf'">
|
<xsl:when test="type = 'class BufferSequence'">
|
||||||
|
<xsl:text>class ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="(type = 'class' or type = 'class...') and declname = 'BufferSequence'">
|
||||||
|
<xsl:value-of select="type"/>
|
||||||
|
<xsl:text> ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'CompletionHandler' or type = 'class CompletionHandler'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'Stream' or type = 'class Stream'">
|
||||||
|
<xsl:text>class ``[link beast.types.stream.Stream [*Stream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'Streambuf' or type = 'class Streambuf'">
|
||||||
<xsl:text>class ``[link beast.types.Streambuf [*Streambuf]]``</xsl:text>
|
<xsl:text>class ``[link beast.types.Streambuf [*Streambuf]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
<xsl:when test="type = 'class SyncStream'">
|
||||||
|
<xsl:text>class ``[link beast.types.stream.SyncStream [*SyncStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'SyncReadStream' or type = 'class SyncReadStream'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'SyncWriteStream' or type = 'class SyncWriteStream'">
|
||||||
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
|
||||||
<xsl:when test="declname = 'T'">
|
<xsl:when test="declname = 'T'">
|
||||||
<xsl:value-of select="declname"/>
|
<xsl:value-of select="declname"/>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
@@ -1466,28 +1607,19 @@
|
|||||||
<xsl:value-of select="array"/>
|
<xsl:value-of select="array"/>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:otherwise>
|
<xsl:otherwise>
|
||||||
<xsl:choose>
|
<xsl:call-template name="cleanup-param">
|
||||||
<xsl:when test="' &&' = substring(type, string-length(type) - 2)">
|
<xsl:with-param name="name" select="type"/>
|
||||||
<xsl:value-of select="substring(type, 1, string-length(type) - 3)"/>
|
</xsl:call-template>
|
||||||
<xsl:text>&&</xsl:text>
|
<xsl:if test="count(declname) > 0">
|
||||||
</xsl:when>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:when test="' &' = substring(type, string-length(type) - 1)">
|
<xsl:value-of select="declname"/>
|
||||||
<xsl:value-of select="substring(type, 1, string-length(type) - 2)"/>
|
</xsl:if>
|
||||||
<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>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<xsl:value-of select="type"/>
|
|
||||||
</xsl:otherwise>
|
|
||||||
</xsl:choose>
|
|
||||||
<xsl:text> </xsl:text>
|
|
||||||
<xsl:value-of select="declname"/>
|
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
<xsl:if test="count(defval) > 0"> = <xsl:value-of select="defval"/></xsl:if>
|
<xsl:if test="count(defval) > 0">
|
||||||
|
<xsl:text> = </xsl:text>
|
||||||
|
<xsl:value-of select="defval"/>
|
||||||
|
</xsl:if>
|
||||||
<xsl:if test="not(position() = last())">
|
<xsl:if test="not(position() = last())">
|
||||||
<xsl:text>,</xsl:text>
|
<xsl:text>,</xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
|||||||
@@ -2,29 +2,48 @@
|
|||||||
|
|
||||||
GroupSources(include/beast)
|
GroupSources(include/beast)
|
||||||
GroupSources(examples)
|
GroupSources(examples)
|
||||||
|
GroupSources(test)
|
||||||
|
|
||||||
add_executable (http-crawl
|
add_executable (http-crawl
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
http_crawl.cpp
|
urls_large_data.hpp
|
||||||
urls_large_data.cpp
|
urls_large_data.cpp
|
||||||
|
http_crawl.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(http-crawl ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable (http-server
|
add_executable (http-server
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
|
file_body.hpp
|
||||||
|
http_async_server.hpp
|
||||||
|
http_stream.hpp
|
||||||
|
http_stream.ipp
|
||||||
|
http_sync_server.hpp
|
||||||
|
../test/sig_wait.hpp
|
||||||
http_server.cpp
|
http_server.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(http-server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable (http-example
|
add_executable (http-example
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
http_example.cpp
|
http_example.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable (websocket-echo
|
if (NOT WIN32)
|
||||||
${BEAST_INCLUDES}
|
target_link_libraries(http-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
websocket_echo.cpp
|
endif()
|
||||||
)
|
|
||||||
|
|
||||||
add_executable (websocket-example
|
add_executable (websocket-example
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
websocket_example.cpp
|
websocket_example.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
target_link_libraries(websocket-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -7,24 +7,20 @@
|
|||||||
|
|
||||||
import os ;
|
import os ;
|
||||||
|
|
||||||
exe http_crawl :
|
exe http-crawl :
|
||||||
http_crawl.cpp
|
http_crawl.cpp
|
||||||
urls_large_data.cpp
|
urls_large_data.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe http_server :
|
exe http-server :
|
||||||
http_server.cpp
|
http_server.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe http_example :
|
exe http-example :
|
||||||
http_example.cpp
|
http_example.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe websocket_echo :
|
exe websocket-example :
|
||||||
websocket_echo.cpp
|
|
||||||
;
|
|
||||||
|
|
||||||
exe websocket_example :
|
|
||||||
websocket_example.cpp
|
websocket_example.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@@ -36,15 +35,16 @@ struct file_body
|
|||||||
|
|
||||||
class writer
|
class writer
|
||||||
{
|
{
|
||||||
std::size_t size_;
|
std::uint64_t size_;
|
||||||
std::size_t offset_ = 0;
|
std::uint64_t offset_ = 0;
|
||||||
std::string const& path_;
|
std::string const& path_;
|
||||||
FILE* file_ = nullptr;
|
FILE* file_ = nullptr;
|
||||||
char buf_[4096];
|
char buf_[4096];
|
||||||
std::size_t buf_len_;
|
std::size_t buf_len_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool constexpr is_single_pass = false;
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
template<bool isRequest, class Headers>
|
template<bool isRequest, class Headers>
|
||||||
writer(message<isRequest, file_body, Headers> const& m) noexcept
|
writer(message<isRequest, file_body, Headers> const& m) noexcept
|
||||||
@@ -69,7 +69,7 @@ struct file_body
|
|||||||
size_ = boost::filesystem::file_size(path_);
|
size_ = boost::filesystem::file_size(path_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::uint64_t
|
||||||
content_length() const
|
content_length() const
|
||||||
{
|
{
|
||||||
return size_;
|
return size_;
|
||||||
@@ -79,7 +79,11 @@ struct file_body
|
|||||||
boost::tribool
|
boost::tribool
|
||||||
operator()(resume_context&&, error_code&, Write&& write)
|
operator()(resume_context&&, error_code&, Write&& write)
|
||||||
{
|
{
|
||||||
buf_len_ = std::min(size_ - offset_, sizeof(buf_));
|
if(size_ - offset_ < sizeof(buf_))
|
||||||
|
buf_len_ = static_cast<std::size_t>(
|
||||||
|
size_ - offset_);
|
||||||
|
else
|
||||||
|
buf_len_ = sizeof(buf_);
|
||||||
auto const nread = fread(buf_, 1, sizeof(buf_), file_);
|
auto const nread = fread(buf_, 1, sizeof(buf_), file_);
|
||||||
(void)nread;
|
(void)nread;
|
||||||
offset_ += buf_len_;
|
offset_ += buf_len_;
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#ifndef BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
|
#ifndef BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
|
||||||
#define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
|
#define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
|
||||||
|
|
||||||
#include "file_body.h"
|
#include "file_body.hpp"
|
||||||
#include "http_stream.h"
|
#include "http_stream.hpp"
|
||||||
|
|
||||||
#include <beast/placeholders.hpp>
|
#include <beast/placeholders.hpp>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
@@ -41,8 +41,8 @@ class http_async_server
|
|||||||
using address_type = boost::asio::ip::address;
|
using address_type = boost::asio::ip::address;
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
using req_type = request<string_body>;
|
using req_type = request_v1<string_body>;
|
||||||
using resp_type = response<file_body>;
|
using resp_type = response_v1<file_body>;
|
||||||
|
|
||||||
boost::asio::io_service ios_;
|
boost::asio::io_service ios_;
|
||||||
socket_type sock_;
|
socket_type sock_;
|
||||||
@@ -127,20 +127,22 @@ private:
|
|||||||
path = root_ + path;
|
path = root_ + path;
|
||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> resp(
|
response_v1<string_body> resp(
|
||||||
{404, "Not Found", req_.version});
|
{404, "Not Found", req_.version});
|
||||||
resp.headers.replace("Server", "http_async_server");
|
resp.headers.replace("Server", "http_async_server");
|
||||||
resp.body = "The file '" + path + "' was not found";
|
resp.body = "The file '" + path + "' was not found";
|
||||||
|
prepare(resp);
|
||||||
stream_.async_write(std::move(resp),
|
stream_.async_write(std::move(resp),
|
||||||
std::bind(&peer::on_write, shared_from_this(),
|
std::bind(&peer::on_write, shared_from_this(),
|
||||||
asio::placeholders::error));
|
asio::placeholders::error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
response<file_body> resp(
|
resp_type resp(
|
||||||
{200, "OK", req_.version});
|
{200, "OK", req_.version});
|
||||||
resp.headers.replace("Server", "http_async_server");
|
resp.headers.replace("Server", "http_async_server");
|
||||||
resp.headers.replace("Content-Type", "text/html");
|
resp.headers.replace("Content-Type", "text/html");
|
||||||
resp.body = path;
|
resp.body = path;
|
||||||
|
prepare(resp);
|
||||||
stream_.async_write(std::move(resp),
|
stream_.async_write(std::move(resp),
|
||||||
std::bind(&peer::on_write, shared_from_this(),
|
std::bind(&peer::on_write, shared_from_this(),
|
||||||
asio::placeholders::error));
|
asio::placeholders::error));
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "http_stream.h"
|
#include "http_stream.hpp"
|
||||||
#include "urls_large_data.h"
|
#include "urls_large_data.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -46,12 +46,13 @@ int main(int, char const*[])
|
|||||||
stream<ip::tcp::socket> hs(ios);
|
stream<ip::tcp::socket> hs(ios);
|
||||||
connect(hs.lowest_layer(), it);
|
connect(hs.lowest_layer(), it);
|
||||||
auto ep = hs.lowest_layer().remote_endpoint();
|
auto ep = hs.lowest_layer().remote_endpoint();
|
||||||
request<empty_body> req({method_t::http_get, "/", 11});
|
request_v1<empty_body> req({"GET", "/", 11});
|
||||||
req.headers.insert("Host", host +
|
req.headers.insert("Host", host +
|
||||||
std::string(":") + std::to_string(ep.port()));
|
std::string(":") + std::to_string(ep.port()));
|
||||||
req.headers.insert("User-Agent", "beast/http");
|
req.headers.insert("User-Agent", "beast/http");
|
||||||
|
prepare(req);
|
||||||
hs.write(req);
|
hs.write(req);
|
||||||
response<string_body> resp;
|
response_v1<string_body> resp;
|
||||||
hs.read(resp);
|
hs.read(resp);
|
||||||
std::cout << resp;
|
std::cout << resp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,15 @@ int main()
|
|||||||
using namespace beast::http;
|
using namespace beast::http;
|
||||||
|
|
||||||
// Send HTTP request using beast
|
// Send HTTP request using beast
|
||||||
request<empty_body> req({method_t::http_get, "/", 11});
|
request_v1<empty_body> req({"GET", "/", 11});
|
||||||
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
||||||
req.headers.replace("User-Agent", "Beast");
|
req.headers.replace("User-Agent", "Beast");
|
||||||
|
prepare(req);
|
||||||
write(sock, req);
|
write(sock, req);
|
||||||
|
|
||||||
// Receive and print HTTP response using beast
|
// Receive and print HTTP response using beast
|
||||||
beast::streambuf sb;
|
beast::streambuf sb;
|
||||||
response<streambuf_body> resp;
|
response_v1<streambuf_body> resp;
|
||||||
read(sock, sb, resp);
|
read(sock, sb, resp);
|
||||||
std::cout << resp;
|
std::cout << resp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "http_async_server.h"
|
#include "http_async_server.hpp"
|
||||||
#include "http_sync_server.h"
|
#include "http_sync_server.hpp"
|
||||||
#include "sig_wait.h"
|
#include "../test/sig_wait.hpp"
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
@@ -69,13 +69,8 @@ int main(int ac, char const* av[])
|
|||||||
endpoint_type ep{address_type::from_string(ip), port};
|
endpoint_type ep{address_type::from_string(ip), port};
|
||||||
|
|
||||||
if(sync)
|
if(sync)
|
||||||
{
|
|
||||||
http_sync_server server(ep, root);
|
http_sync_server server(ep, root);
|
||||||
sig_wait();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
http_async_server server(ep, threads, root);
|
http_async_server server(ep, threads, root);
|
||||||
sig_wait();
|
sig_wait();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(message<isRequest, Body, Headers>& msg)
|
read(message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(msg, ec);
|
read(msg, ec);
|
||||||
@@ -295,7 +295,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(message<isRequest, Body, Headers>& msg,
|
read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start reading a HTTP message from the stream asynchronously.
|
/** Start reading a HTTP message from the stream asynchronously.
|
||||||
@@ -339,7 +339,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(message<isRequest, Body, Headers>& msg,
|
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
/** Write a HTTP message to the stream.
|
/** Write a HTTP message to the stream.
|
||||||
@@ -365,7 +365,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(message<isRequest, Body, Headers> const& msg)
|
write(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(msg, ec);
|
write(msg, ec);
|
||||||
@@ -396,7 +396,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(message<isRequest, Body, Headers> const& msg,
|
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||||
@@ -434,7 +434,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(message<isRequest, Body, Headers> const& msg,
|
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||||
@@ -473,7 +473,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(message<isRequest, Body, Headers>&& msg,
|
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -20,10 +20,11 @@
|
|||||||
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||||
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||||
|
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
|
#include <beast/bind_handler.hpp>
|
||||||
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -40,14 +41,14 @@ class stream<NextLayer, Allocator>::read_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& s;
|
stream<NextLayer>& s;
|
||||||
message<isRequest, Body, Headers>& m;
|
message_v1<isRequest, Body, Headers>& m;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers>& m_)
|
message_v1<isRequest, Body, Headers>& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
@@ -142,14 +143,14 @@ class stream<NextLayer, Allocator>::write_op : public op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& s;
|
stream<NextLayer>& s;
|
||||||
message<isRequest, Body, Headers> m;
|
message_v1<isRequest, Body, Headers> m;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers> const& m_,
|
message_v1<isRequest, Body, Headers> const& m_,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
@@ -160,7 +161,7 @@ class stream<NextLayer, Allocator>::write_op : public op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers>&& m_,
|
message_v1<isRequest, Body, Headers>&& m_,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(std::move(m_))
|
, m(std::move(m_))
|
||||||
@@ -305,7 +306,7 @@ template<class NextLayer, class Allocator>
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
read(message<isRequest, Body, Headers>& msg,
|
read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
||||||
@@ -316,7 +317,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_read(message<isRequest, Body, Headers>& msg,
|
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler) ->
|
ReadHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
@@ -334,7 +335,7 @@ template<class NextLayer, class Allocator>
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
write(message<isRequest, Body, Headers> const& msg,
|
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
beast::http::write(next_layer_, msg, ec);
|
beast::http::write(next_layer_, msg, ec);
|
||||||
@@ -345,7 +346,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_write(message<isRequest, Body, Headers> const& msg,
|
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
@@ -376,7 +377,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_write(message<isRequest, Body, Headers>&& msg,
|
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#ifndef BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
|
#ifndef BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
|
||||||
#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
|
#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
|
||||||
|
|
||||||
#include "file_body.h"
|
#include "file_body.hpp"
|
||||||
#include "http_stream.h"
|
#include "http_stream.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -43,8 +43,8 @@ class http_sync_server
|
|||||||
using address_type = boost::asio::ip::address;
|
using address_type = boost::asio::ip::address;
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
using req_type = request<string_body>;
|
using req_type = request_v1<string_body>;
|
||||||
using resp_type = response<file_body>;
|
using resp_type = response_v1<file_body>;
|
||||||
|
|
||||||
boost::asio::io_service ios_;
|
boost::asio::io_service ios_;
|
||||||
socket_type sock_;
|
socket_type sock_;
|
||||||
@@ -155,19 +155,21 @@ public:
|
|||||||
path = root_ + path;
|
path = root_ + path;
|
||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> resp(
|
response_v1<string_body> resp(
|
||||||
{404, "Not Found", req.version});
|
{404, "Not Found", req.version});
|
||||||
resp.headers.replace("Server", "http_sync_server");
|
resp.headers.replace("Server", "http_sync_server");
|
||||||
resp.body = "The file '" + path + "' was not found";
|
resp.body = "The file '" + path + "' was not found";
|
||||||
|
prepare(resp);
|
||||||
hs.write(resp, ec);
|
hs.write(resp, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
response<file_body> resp(
|
resp_type resp(
|
||||||
{200, "OK", req.version});
|
{200, "OK", req.version});
|
||||||
resp.headers.replace("Server", "http_sync_server");
|
resp.headers.replace("Server", "http_sync_server");
|
||||||
resp.headers.replace("Content-Type", "text/html");
|
resp.headers.replace("Content-Type", "text/html");
|
||||||
resp.body = path;
|
resp.body = path;
|
||||||
|
prepare(resp);
|
||||||
hs.write(resp, ec);
|
hs.write(resp, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
break;
|
break;
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "urls_large_data.h"
|
#include "urls_large_data.hpp"
|
||||||
|
|
||||||
// Data from Alexa top 1 million sites
|
// Data from Alexa top 1 million sites
|
||||||
// http://s3.amazonaws.com/alexa-static/top-1m.csv.zip
|
// http://s3.amazonaws.com/alexa-static/top-1m.csv.zip
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <beast/to_string.hpp>
|
||||||
#include <beast/websocket.hpp>
|
#include <beast/websocket.hpp>
|
||||||
#include <beast/buffers_debug.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -33,6 +33,5 @@ int main()
|
|||||||
opcode op;
|
opcode op;
|
||||||
ws.read(op, sb);
|
ws.read(op, sb);
|
||||||
ws.close(close_code::normal);
|
ws.close(close_code::normal);
|
||||||
std::cout <<
|
std::cout << to_string(sb.data()) << "\n";
|
||||||
beast::debug::buffers_to_string(sb.data()) << "\n";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_ASYNC_COMPLETION_HPP
|
#ifndef BEAST_ASYNC_COMPLETION_HPP
|
||||||
#define BEAST_ASYNC_COMPLETION_HPP
|
#define BEAST_ASYNC_COMPLETION_HPP
|
||||||
|
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/handler_concepts.hpp>
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/handler_type.hpp>
|
#include <boost/asio/handler_type.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -19,11 +19,11 @@ namespace beast {
|
|||||||
/** Helper for customizing the return type of asynchronous initiation functions.
|
/** Helper for customizing the return type of asynchronous initiation functions.
|
||||||
|
|
||||||
This class template is used to transform caller-provided completion
|
This class template is used to transform caller-provided completion
|
||||||
tokens in calls to asynchronous initiation functions. The transformation
|
handlers in calls to asynchronous initiation functions. The transformation
|
||||||
allows customization of the return type of the initiating function, and the
|
allows customization of the return type of the initiating function, and the
|
||||||
function signature of the final handler.
|
function signature of the final handler.
|
||||||
|
|
||||||
@tparam CompletionToken A CompletionHandler, or a user defined type
|
@tparam CompletionHandler A completion handler, or a user defined type
|
||||||
with specializations for customizing the return type (for example,
|
with specializations for customizing the return type (for example,
|
||||||
`boost::asio::use_future` or `boost::asio::yield_context`).
|
`boost::asio::use_future` or `boost::asio::yield_context`).
|
||||||
|
|
||||||
@@ -32,22 +32,22 @@ namespace beast {
|
|||||||
Example:
|
Example:
|
||||||
@code
|
@code
|
||||||
...
|
...
|
||||||
template<class CompletionToken>
|
template<class CompletionHandler>
|
||||||
typename async_completion<CompletionToken,
|
typename async_completion<CompletionHandler,
|
||||||
void(boost::system::error_code)>::result_type
|
void(boost::system::error_code)>::result_type
|
||||||
async_initfn(..., CompletionToken&& token)
|
async_initfn(..., CompletionHandler&& handler)
|
||||||
{
|
{
|
||||||
async_completion<CompletionToken,
|
async_completion<CompletionHandler,
|
||||||
void(boost::system::error_code)> completion(token);
|
void(boost::system::error_code)> completion(handler);
|
||||||
...
|
...
|
||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
|
@note See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
|
||||||
Library Foundations For Asynchronous Operations</a>
|
Library Foundations For Asynchronous Operations</a>
|
||||||
*/
|
*/
|
||||||
template <class CompletionToken, class Signature>
|
template <class CompletionHandler, class Signature>
|
||||||
struct async_completion
|
struct async_completion
|
||||||
{
|
{
|
||||||
/** The type of the final handler called by the asynchronous initiation function.
|
/** The type of the final handler called by the asynchronous initiation function.
|
||||||
@@ -56,7 +56,7 @@ struct async_completion
|
|||||||
*/
|
*/
|
||||||
using handler_type =
|
using handler_type =
|
||||||
typename boost::asio::handler_type<
|
typename boost::asio::handler_type<
|
||||||
CompletionToken, Signature>::type;
|
CompletionHandler, Signature>::type;
|
||||||
|
|
||||||
/// The type of the value returned by the asynchronous initiation function.
|
/// The type of the value returned by the asynchronous initiation function.
|
||||||
using result_type = typename
|
using result_type = typename
|
||||||
@@ -64,14 +64,14 @@ struct async_completion
|
|||||||
|
|
||||||
/** Construct the helper.
|
/** Construct the helper.
|
||||||
|
|
||||||
@param token The completion token. Copies will be made as
|
@param token The completion handler. Copies will be made as
|
||||||
required. If `CompletionToken` is movable, it may also be moved.
|
required. If `CompletionHandler` is movable, it may also be moved.
|
||||||
*/
|
*/
|
||||||
async_completion(typename std::remove_reference<CompletionToken>::type& token)
|
async_completion(typename std::remove_reference<CompletionHandler>::type& token)
|
||||||
: handler(std::forward<CompletionToken>(token))
|
: handler(std::forward<CompletionHandler>(token))
|
||||||
, result(handler)
|
, result(handler)
|
||||||
{
|
{
|
||||||
static_assert(is_Handler<handler_type, Signature>::value,
|
static_assert(is_CompletionHandler<handler_type, Signature>::value,
|
||||||
"Handler requirements not met");
|
"Handler requirements not met");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,15 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A `Streambuf` that uses multiple buffers internally.
|
/** A @b `Streambuf` that uses multiple buffers internally.
|
||||||
|
|
||||||
The implementation uses a sequence of one or more character arrays
|
The implementation uses a sequence of one or more character arrays
|
||||||
of varying sizes. Additional character array objects are appended to
|
of varying sizes. Additional character array objects are appended to
|
||||||
the sequence to accommodate changes in the size of the character
|
the sequence to accommodate changes in the size of the character
|
||||||
sequence.
|
sequence.
|
||||||
|
|
||||||
|
@note Meets the requirements of @b Streambuf.
|
||||||
|
|
||||||
@tparam Allocator The allocator to use for managing memory.
|
@tparam Allocator The allocator to use for managing memory.
|
||||||
*/
|
*/
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@@ -36,10 +38,14 @@ class basic_streambuf
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#if GENERATING_DOCS
|
||||||
/// The type of allocator used.
|
/// The type of allocator used.
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
#else
|
||||||
using allocator_type = typename
|
using allocator_type = typename
|
||||||
std::allocator_traits<Allocator>::
|
std::allocator_traits<Allocator>::
|
||||||
template rebind_alloc<std::uint8_t>;
|
template rebind_alloc<std::uint8_t>;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Storage for the list of buffers representing the input
|
// Storage for the list of buffers representing the input
|
||||||
@@ -93,106 +99,104 @@ public:
|
|||||||
|
|
||||||
/** Move constructor.
|
/** Move constructor.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
The new object will have the input sequence of
|
||||||
|
the other stream buffer, and an empty output sequence.
|
||||||
|
|
||||||
After the move, the moved-from object will have an
|
@note After the move, the moved-from object will have
|
||||||
empty input and output sequence, with no internal
|
an empty input and output sequence, with no internal
|
||||||
buffers allocated.
|
buffers allocated.
|
||||||
|
|
||||||
@param other The stream buffer to move from.
|
|
||||||
*/
|
*/
|
||||||
basic_streambuf(basic_streambuf&& other);
|
basic_streambuf(basic_streambuf&&);
|
||||||
|
|
||||||
/** Move constructor.
|
/** Move constructor.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
The new object will have the input sequence of
|
||||||
|
the other stream buffer, and an empty output sequence.
|
||||||
|
|
||||||
After the move, the moved-from object will have an
|
@note After the move, the moved-from object will have
|
||||||
empty input and output sequence, with no internal
|
an empty input and output sequence, with no internal
|
||||||
buffers allocated.
|
buffers allocated.
|
||||||
|
|
||||||
@param other The stream buffer to move from.
|
|
||||||
|
|
||||||
@param alloc The allocator to associate with the
|
@param alloc The allocator to associate with the
|
||||||
stream buffer.
|
stream buffer.
|
||||||
*/
|
*/
|
||||||
basic_streambuf(basic_streambuf&& other,
|
basic_streambuf(basic_streambuf&&,
|
||||||
allocator_type const& alloc);
|
allocator_type const& alloc);
|
||||||
|
|
||||||
/** Move assignment.
|
/** Move assignment.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have the input sequence of
|
||||||
|
the other stream buffer, and an empty output sequence.
|
||||||
|
|
||||||
After the move, the moved-from object will have an
|
@note After the move, the moved-from object will have
|
||||||
empty input and output sequence, with no internal
|
an empty input and output sequence, with no internal
|
||||||
buffers allocated.
|
buffers allocated.
|
||||||
|
|
||||||
@param other The stream buffer to move from.
|
|
||||||
*/
|
*/
|
||||||
basic_streambuf&
|
basic_streambuf&
|
||||||
operator=(basic_streambuf&& other);
|
operator=(basic_streambuf&&);
|
||||||
|
|
||||||
/// Copy constructor.
|
|
||||||
basic_streambuf(basic_streambuf const& other);
|
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy constructor.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
|
*/
|
||||||
|
basic_streambuf(basic_streambuf const&);
|
||||||
|
|
||||||
@param other The stream buffer to copy.
|
/** Copy constructor.
|
||||||
|
|
||||||
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
|
|
||||||
@param alloc The allocator to associate with the
|
@param alloc The allocator to associate with the
|
||||||
stream buffer.
|
stream buffer.
|
||||||
*/
|
*/
|
||||||
basic_streambuf(basic_streambuf const& other,
|
basic_streambuf(basic_streambuf const&,
|
||||||
allocator_type const& alloc);
|
allocator_type const& alloc);
|
||||||
|
|
||||||
/** Copy assignment.
|
/** Copy assignment.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
@param other The stream buffer to copy.
|
|
||||||
*/
|
*/
|
||||||
basic_streambuf& operator=(basic_streambuf const& other);
|
basic_streambuf& operator=(basic_streambuf const&);
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy constructor.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
@param other The stream buffer to copy.
|
|
||||||
*/
|
*/
|
||||||
template<class OtherAlloc>
|
template<class OtherAlloc>
|
||||||
basic_streambuf(basic_streambuf<OtherAlloc> const& other);
|
basic_streambuf(basic_streambuf<OtherAlloc> const&);
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy constructor.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
@param other The stream buffer to copy.
|
|
||||||
|
|
||||||
@param alloc The allocator to associate with the
|
@param alloc The allocator to associate with the
|
||||||
stream buffer.
|
stream buffer.
|
||||||
*/
|
*/
|
||||||
template<class OtherAlloc>
|
template<class OtherAlloc>
|
||||||
basic_streambuf(basic_streambuf<OtherAlloc> const& other,
|
basic_streambuf(basic_streambuf<OtherAlloc> const&,
|
||||||
allocator_type const& alloc);
|
allocator_type const& alloc);
|
||||||
|
|
||||||
/** Copy assignment.
|
/** Copy assignment.
|
||||||
|
|
||||||
The output sequence of this object will be empty.
|
This object will have a copy of the other stream
|
||||||
|
buffer's input sequence, and an empty output sequence.
|
||||||
@param other The stream buffer to copy.
|
|
||||||
*/
|
*/
|
||||||
template<class OtherAlloc>
|
template<class OtherAlloc>
|
||||||
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const& other);
|
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const&);
|
||||||
|
|
||||||
/** Default constructor.
|
/** Construct a stream buffer.
|
||||||
|
|
||||||
@param alloc_size The size of buffer to allocate. This is a soft
|
@param alloc_size The size of buffer to allocate. This is a
|
||||||
limit, calls to prepare for buffers exceeding this size will allocate
|
soft limit, calls to prepare for buffers exceeding this size
|
||||||
the larger size.
|
will allocate the larger size. The default allocation size
|
||||||
|
is 1KB (1024 bytes).
|
||||||
|
|
||||||
@param alloc The allocator to use.
|
@param alloc The allocator to use. If this parameter is
|
||||||
|
unspecified, a default constructed allocator will be used.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
basic_streambuf(std::size_t alloc_size = 1024,
|
basic_streambuf(std::size_t alloc_size = 1024,
|
||||||
@@ -219,15 +223,26 @@ public:
|
|||||||
return in_size_;
|
return in_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a list of buffers that represents the output sequence, with the given size.
|
/** Get a list of buffers that represents the output sequence, with the given size.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
|
*/
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(size_type n);
|
prepare(size_type n);
|
||||||
|
|
||||||
/// Move bytes from the output sequence to the input sequence.
|
/** Move bytes from the output sequence to the input sequence.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
commit(size_type n);
|
commit(size_type n);
|
||||||
|
|
||||||
/// Get a list of buffers that represents the input sequence.
|
/** Get a list of buffers that represents the input sequence.
|
||||||
|
|
||||||
|
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||||
|
*/
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const;
|
||||||
|
|
||||||
@@ -277,19 +292,9 @@ private:
|
|||||||
|
|
||||||
@return The stream buffer.
|
@return The stream buffer.
|
||||||
*/
|
*/
|
||||||
template<class Alloc, class T>
|
template<class Allocator, class T>
|
||||||
basic_streambuf<Alloc>&
|
basic_streambuf<Allocator>&
|
||||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t);
|
operator<<(basic_streambuf<Allocator>& streambuf, T const& t);
|
||||||
|
|
||||||
/** Convert the entire basic_streambuf to a string.
|
|
||||||
|
|
||||||
@param streambuf The streambuf to convert.
|
|
||||||
|
|
||||||
@return A string representing the contents of the input sequence.
|
|
||||||
*/
|
|
||||||
template<class Allocator>
|
|
||||||
std::string
|
|
||||||
to_string(basic_streambuf<Allocator> const& streambuf);
|
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
|||||||
@@ -8,110 +8,19 @@
|
|||||||
#ifndef BEAST_BIND_HANDLER_HPP
|
#ifndef BEAST_BIND_HANDLER_HPP
|
||||||
#define BEAST_BIND_HANDLER_HPP
|
#define BEAST_BIND_HANDLER_HPP
|
||||||
|
|
||||||
#include <beast/detail/integer_sequence.hpp>
|
#include <beast/handler_concepts.hpp>
|
||||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
#include <beast/detail/bind_handler.hpp>
|
||||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
|
||||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
|
||||||
#include <functional>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/* Nullary handler that calls Handler with bound arguments.
|
|
||||||
|
|
||||||
The bound handler provides the same io_service execution
|
|
||||||
guarantees as the original handler.
|
|
||||||
*/
|
|
||||||
template<class Handler, class... Args>
|
|
||||||
class bound_handler
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using args_type = std::tuple<typename std::decay<Args>::type...>;
|
|
||||||
|
|
||||||
Handler h_;
|
|
||||||
args_type args_;
|
|
||||||
|
|
||||||
template<class Tuple, std::size_t... S>
|
|
||||||
static void invoke(Handler& h, Tuple& args,
|
|
||||||
index_sequence<S...>)
|
|
||||||
{
|
|
||||||
h(std::get<S>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
template<class DeducedHandler>
|
|
||||||
explicit
|
|
||||||
bound_handler(DeducedHandler&& handler, Args&&... args)
|
|
||||||
: h_(std::forward<DeducedHandler>(handler))
|
|
||||||
, args_(std::forward<Args>(args)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()()
|
|
||||||
{
|
|
||||||
invoke(h_, args_,
|
|
||||||
index_sequence_for<Args...> ());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()() const
|
|
||||||
{
|
|
||||||
invoke(h_, args_,
|
|
||||||
index_sequence_for<Args...> ());
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void*
|
|
||||||
asio_handler_allocate(
|
|
||||||
std::size_t size, bound_handler* h)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_alloc_helpers::
|
|
||||||
allocate(size, h->h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void
|
|
||||||
asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bound_handler* h)
|
|
||||||
{
|
|
||||||
boost_asio_handler_alloc_helpers::
|
|
||||||
deallocate(p, size, h->h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
asio_handler_is_continuation(bound_handler* h)
|
|
||||||
{
|
|
||||||
return boost_asio_handler_cont_helpers::
|
|
||||||
is_continuation (h->h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class F>
|
|
||||||
friend
|
|
||||||
void
|
|
||||||
asio_handler_invoke(F&& f, bound_handler* h)
|
|
||||||
{
|
|
||||||
boost_asio_handler_invoke_helpers::
|
|
||||||
invoke(f, h->h_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Bind parameters to a completion handler, creating a wrapped handler.
|
/** Bind parameters to a completion handler, creating a wrapped handler.
|
||||||
|
|
||||||
This function creates a new handler which invoked with no parameters
|
This function creates a new handler which, when invoked with no
|
||||||
calls the original handler with the list of bound arguments. The passed
|
parameters, calls the original handler with the list of bound arguments.
|
||||||
handler and arguments are forwarded into the returned handler, which
|
The passed handler and arguments are forwarded into the returned handler,
|
||||||
provides the same `io_service` execution guarantees as the original
|
which provides the same `io_service` execution guarantees as the original
|
||||||
handler.
|
handler.
|
||||||
|
|
||||||
Unlike `io_service::wrap`, the returned handler can be used in a
|
Unlike `io_service::wrap`, the returned handler can be used in a
|
||||||
@@ -145,6 +54,9 @@ detail::bound_handler<
|
|||||||
#endif
|
#endif
|
||||||
bind_handler(CompletionHandler&& handler, Args&&... args)
|
bind_handler(CompletionHandler&& handler, Args&&... args)
|
||||||
{
|
{
|
||||||
|
static_assert(is_CompletionHandler<
|
||||||
|
CompletionHandler, void(Args...)>::value,
|
||||||
|
"CompletionHandler requirements not met");
|
||||||
return detail::bound_handler<typename std::decay<
|
return detail::bound_handler<typename std::decay<
|
||||||
CompletionHandler>::type, Args...>(std::forward<
|
CompletionHandler>::type, Args...>(std::forward<
|
||||||
CompletionHandler>(handler),
|
CompletionHandler>(handler),
|
||||||
@@ -153,10 +65,4 @@ bind_handler(CompletionHandler&& handler, Args&&... args)
|
|||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<class Handler, class... Args>
|
|
||||||
void bind(beast::detail::bound_handler<
|
|
||||||
Handler, Args...>, ...) = delete;
|
|
||||||
} // std
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#ifndef BEAST_BUFFER_CAT_HPP
|
#ifndef BEAST_BUFFER_CAT_HPP
|
||||||
#define BEAST_BUFFER_CAT_HPP
|
#define BEAST_BUFFER_CAT_HPP
|
||||||
|
|
||||||
|
#include <beast/detail/buffer_cat.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@@ -18,463 +19,9 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
class buffer_cat_helper
|
|
||||||
{
|
|
||||||
std::tuple<Bs...> bs_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = ValueType;
|
|
||||||
|
|
||||||
class const_iterator;
|
|
||||||
|
|
||||||
buffer_cat_helper(buffer_cat_helper&&) = default;
|
|
||||||
buffer_cat_helper(buffer_cat_helper const&) = default;
|
|
||||||
buffer_cat_helper& operator=(buffer_cat_helper&&) = default;
|
|
||||||
buffer_cat_helper& operator=(buffer_cat_helper const&) = default;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
buffer_cat_helper(Bs const&... bs)
|
|
||||||
: bs_(bs...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator
|
|
||||||
begin() const;
|
|
||||||
|
|
||||||
const_iterator
|
|
||||||
end() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class U>
|
|
||||||
std::size_t constexpr
|
|
||||||
max_sizeof()
|
|
||||||
{
|
|
||||||
return sizeof(U);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U0, class U1, class... Us>
|
|
||||||
std::size_t constexpr
|
|
||||||
max_sizeof()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
|
||||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
class buffer_cat_helper<
|
|
||||||
ValueType, Bs...>::const_iterator
|
|
||||||
{
|
|
||||||
std::size_t n_;
|
|
||||||
std::tuple<Bs...> const* bs_;
|
|
||||||
std::array<std::uint8_t,
|
|
||||||
max_sizeof<typename Bs::const_iterator...>()> buf_;
|
|
||||||
|
|
||||||
friend class buffer_cat_helper<ValueType, Bs...>;
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
using C = std::integral_constant<std::size_t, I>;
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
using iter_t = typename std::tuple_element<
|
|
||||||
I, std::tuple<Bs...>>::type::const_iterator;
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
iter_t<I>&
|
|
||||||
iter()
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<
|
|
||||||
iter_t<I>*>(buf_.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
iter_t<I> const&
|
|
||||||
iter() const
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<
|
|
||||||
iter_t<I> const*>(buf_.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = ValueType;
|
|
||||||
using pointer = value_type const*;
|
|
||||||
using reference = value_type;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using iterator_category =
|
|
||||||
std::bidirectional_iterator_tag;
|
|
||||||
|
|
||||||
~const_iterator();
|
|
||||||
const_iterator();
|
|
||||||
const_iterator(const_iterator&& other);
|
|
||||||
const_iterator(const_iterator const& other);
|
|
||||||
const_iterator& operator=(const_iterator&& other);
|
|
||||||
const_iterator& operator=(const_iterator const& other);
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator==(const_iterator const& other) const;
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator!=(const_iterator const& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
reference
|
|
||||||
operator*() const;
|
|
||||||
|
|
||||||
pointer
|
|
||||||
operator->() const = delete;
|
|
||||||
|
|
||||||
const_iterator&
|
|
||||||
operator++();
|
|
||||||
|
|
||||||
const_iterator
|
|
||||||
operator++(int)
|
|
||||||
{
|
|
||||||
auto temp = *this;
|
|
||||||
++(*this);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator&
|
|
||||||
operator--();
|
|
||||||
|
|
||||||
const_iterator
|
|
||||||
operator--(int)
|
|
||||||
{
|
|
||||||
auto temp = *this;
|
|
||||||
--(*this);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const_iterator(
|
|
||||||
std::tuple<Bs...> const& bs, bool at_end);
|
|
||||||
|
|
||||||
void
|
|
||||||
construct(C<sizeof...(Bs)>)
|
|
||||||
{
|
|
||||||
auto constexpr I = sizeof...(Bs);
|
|
||||||
n_ = I;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
construct(C<I>)
|
|
||||||
{
|
|
||||||
if(std::get<I>(*bs_).begin() !=
|
|
||||||
std::get<I>(*bs_).end())
|
|
||||||
{
|
|
||||||
n_ = I;
|
|
||||||
new(buf_.data()) iter_t<I>{
|
|
||||||
std::get<I>(*bs_).begin()};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
construct(C<I+1>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
destroy(C<sizeof...(Bs)>)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
destroy(C<I>)
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
using Iter = iter_t<I>;
|
|
||||||
iter<I>().~Iter();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
destroy(C<I+1>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
move(C<sizeof...(Bs)>, const_iterator&&)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
move(C<I>, const_iterator&& other)
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
new(buf_.data()) iter_t<I>{
|
|
||||||
std::move(other.iter<I>())};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
move(C<I+1>{}, std::move(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
copy(C<sizeof...(Bs)>, const_iterator const&)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
copy(C<I>, const_iterator const& other)
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
new(buf_.data()) iter_t<I>{
|
|
||||||
other.iter<I>()};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
copy(C<I+1>{}, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
equal(C<sizeof...(Bs)>,
|
|
||||||
const_iterator const&) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
bool
|
|
||||||
equal(C<I>, const_iterator const& other) const
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
return iter<I>() == other.iter<I>();
|
|
||||||
return equal(C<I+1>{}, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]]
|
|
||||||
reference
|
|
||||||
dereference(C<sizeof...(Bs)>) const
|
|
||||||
{
|
|
||||||
throw std::logic_error("invalid iterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
reference
|
|
||||||
dereference(C<I>) const
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
return *iter<I>();
|
|
||||||
return dereference(C<I+1>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]]
|
|
||||||
void
|
|
||||||
increment(C<sizeof...(Bs)>)
|
|
||||||
{
|
|
||||||
throw std::logic_error("invalid iterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
increment(C<I>)
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
if(++iter<I>() !=
|
|
||||||
std::get<I>(*bs_).end())
|
|
||||||
return;
|
|
||||||
using Iter = iter_t<I>;
|
|
||||||
iter<I>().~Iter();
|
|
||||||
return construct(C<I+1>{});
|
|
||||||
}
|
|
||||||
increment(C<I+1>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
decrement(C<sizeof...(Bs)>)
|
|
||||||
{
|
|
||||||
auto constexpr I = sizeof...(Bs);
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
--n_;
|
|
||||||
new(buf_.data()) iter_t<I-1>{
|
|
||||||
std::get<I-1>(*bs_).end()};
|
|
||||||
}
|
|
||||||
decrement(C<I-1>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
decrement(C<0>)
|
|
||||||
{
|
|
||||||
auto constexpr I = 0;
|
|
||||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
|
||||||
{
|
|
||||||
--iter<I>();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw std::logic_error("invalid iterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t I>
|
|
||||||
void
|
|
||||||
decrement(C<I>)
|
|
||||||
{
|
|
||||||
if(n_ == I)
|
|
||||||
{
|
|
||||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
|
||||||
{
|
|
||||||
--iter<I>();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--n_;
|
|
||||||
using Iter = iter_t<I>;
|
|
||||||
iter<I>().~Iter();
|
|
||||||
new(buf_.data()) iter_t<I-1>{
|
|
||||||
std::get<I-1>(*bs_).end()};
|
|
||||||
}
|
|
||||||
decrement(C<I-1>{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::~const_iterator()
|
|
||||||
{
|
|
||||||
destroy(C<0>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::const_iterator()
|
|
||||||
: n_(sizeof...(Bs))
|
|
||||||
, bs_(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::const_iterator(
|
|
||||||
std::tuple<Bs...> const& bs, bool at_end)
|
|
||||||
: bs_(&bs)
|
|
||||||
{
|
|
||||||
if(at_end)
|
|
||||||
n_ = sizeof...(Bs);
|
|
||||||
else
|
|
||||||
construct(C<0>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::const_iterator(const_iterator&& other)
|
|
||||||
: n_(other.n_)
|
|
||||||
, bs_(other.bs_)
|
|
||||||
{
|
|
||||||
move(C<0>{}, std::move(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::const_iterator(const_iterator const& other)
|
|
||||||
: n_(other.n_)
|
|
||||||
, bs_(other.bs_)
|
|
||||||
{
|
|
||||||
copy(C<0>{}, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator=(const_iterator&& other) ->
|
|
||||||
const_iterator&
|
|
||||||
{
|
|
||||||
if(&other == this)
|
|
||||||
return *this;
|
|
||||||
destroy(C<0>{});
|
|
||||||
n_ = other.n_;
|
|
||||||
bs_ = other.bs_;
|
|
||||||
move(C<0>{}, std::move(other));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator=(const_iterator const& other) ->
|
|
||||||
const_iterator&
|
|
||||||
{
|
|
||||||
if(&other == this)
|
|
||||||
return *this;
|
|
||||||
destroy(C<0>{});
|
|
||||||
n_ = other.n_;
|
|
||||||
bs_ = other.bs_;
|
|
||||||
copy(C<0>{}, other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
bool
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator==(const_iterator const& other) const
|
|
||||||
{
|
|
||||||
if(bs_ != other.bs_)
|
|
||||||
return false;
|
|
||||||
if(n_ != other.n_)
|
|
||||||
return false;
|
|
||||||
return equal(C<0>{}, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator*() const ->
|
|
||||||
reference
|
|
||||||
{
|
|
||||||
return dereference(C<0>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator++() ->
|
|
||||||
const_iterator&
|
|
||||||
{
|
|
||||||
increment(C<0>{});
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::
|
|
||||||
const_iterator::operator--() ->
|
|
||||||
const_iterator&
|
|
||||||
{
|
|
||||||
decrement(C<sizeof...(Bs)>{});
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::begin() const ->
|
|
||||||
const_iterator
|
|
||||||
{
|
|
||||||
return const_iterator(bs_, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ValueType, class... Bs>
|
|
||||||
auto
|
|
||||||
buffer_cat_helper<ValueType, Bs...>::end() const ->
|
|
||||||
const_iterator
|
|
||||||
{
|
|
||||||
return const_iterator(bs_, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Concatenate 2 or more buffer sequences to form a `ConstBufferSequence`.
|
/** Concatenate 2 or more buffer sequences to form a `ConstBufferSequence`.
|
||||||
|
|
||||||
This function returns a `ConstBufferSequence` that when iterated,
|
This function returns a @b `ConstBufferSequence` that when iterated,
|
||||||
efficiently concatenates the input buffer sequences. Copies of the
|
efficiently concatenates the input buffer sequences. Copies of the
|
||||||
arguments passed will be made; however, the returned object does
|
arguments passed will be made; however, the returned object does
|
||||||
not take ownership of the underlying memory. The application is still
|
not take ownership of the underlying memory. The application is still
|
||||||
@@ -482,8 +29,8 @@ buffer_cat_helper<ValueType, Bs...>::end() const ->
|
|||||||
|
|
||||||
@param buffers The list of buffer sequences to concatenate.
|
@param buffers The list of buffer sequences to concatenate.
|
||||||
|
|
||||||
@return A new `ConstBufferSequence` that represents the concatenation
|
@return A new @b `ConstBufferSequence` that represents the
|
||||||
of the input buffer sequences.
|
concatenation of the input buffer sequences.
|
||||||
*/
|
*/
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
template<class... BufferSequence>
|
template<class... BufferSequence>
|
||||||
|
|||||||
61
src/beast/include/beast/buffer_concepts.hpp
Normal file
61
src/beast/include/beast/buffer_concepts.hpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// 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_BUFFER_CONCEPTS_HPP
|
||||||
|
#define BEAST_BUFFER_CONCEPTS_HPP
|
||||||
|
|
||||||
|
#include <beast/detail/buffer_concepts.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `BufferSequence`.
|
||||||
|
template<class T, class BufferType>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_BufferSequence : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_BufferSequence : detail::is_BufferSequence<T, BufferType>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `ConstBufferSequence`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_ConstBufferSequence : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_ConstBufferSequence :
|
||||||
|
is_BufferSequence<T, boost::asio::const_buffer>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `MutableBufferSequence`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_MutableBufferSequence : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_MutableBufferSequence :
|
||||||
|
is_BufferSequence<T, boost::asio::mutable_buffer>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `Streambuf`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_Streambuf : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_Streambuf : detail::is_Streambuf<T>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,15 +8,16 @@
|
|||||||
#ifndef BEAST_BUFFERS_ADAPTER_HPP
|
#ifndef BEAST_BUFFERS_ADAPTER_HPP
|
||||||
#define BEAST_BUFFERS_ADAPTER_HPP
|
#define BEAST_BUFFERS_ADAPTER_HPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** Adapts a `MutableBufferSequence` into a `Streambuf`.
|
/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`.
|
||||||
|
|
||||||
This class wraps a `MutableBufferSequence` to meet the requirements
|
This class wraps a @b `MutableBufferSequence` to meet the requirements
|
||||||
of `Streambuf`. Upon construction the input and output sequences are
|
of @b `Streambuf`. Upon construction the input and output sequences are
|
||||||
empty. A copy of the mutable buffer sequence object is stored; however,
|
empty. A copy of the mutable buffer sequence object is stored; however,
|
||||||
ownership of the underlying memory is not transferred. The caller is
|
ownership of the underlying memory is not transferred. The caller is
|
||||||
responsible for making sure that referenced memory remains valid
|
responsible for making sure that referenced memory remains valid
|
||||||
@@ -25,20 +26,18 @@ namespace beast {
|
|||||||
The size of the mutable buffer sequence determines the maximum
|
The size of the mutable buffer sequence determines the maximum
|
||||||
number of bytes which may be prepared and committed.
|
number of bytes which may be prepared and committed.
|
||||||
|
|
||||||
@tparam Buffers The type of mutable buffer sequence to wrap.
|
@tparam MutableBufferSequence The type of mutable buffer sequence to wrap.
|
||||||
*/
|
*/
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter
|
class buffers_adapter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using buffers_type = typename std::decay<Buffers>::type;
|
static_assert(is_MutableBufferSequence<MutableBufferSequence>::value,
|
||||||
using iter_type = typename buffers_type::const_iterator;
|
"MutableBufferSequence requirements not met");
|
||||||
|
|
||||||
static auto constexpr is_mutable =
|
using iter_type = typename MutableBufferSequence::const_iterator;
|
||||||
std::is_constructible<boost::asio::mutable_buffer,
|
|
||||||
typename std::iterator_traits<iter_type>::value_type>::value;
|
|
||||||
|
|
||||||
Buffers bs_;
|
MutableBufferSequence bs_;
|
||||||
iter_type begin_;
|
iter_type begin_;
|
||||||
iter_type out_;
|
iter_type out_;
|
||||||
iter_type end_;
|
iter_type end_;
|
||||||
@@ -98,7 +97,7 @@ public:
|
|||||||
transferred.
|
transferred.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
buffers_adapter(Buffers const& buffers);
|
buffers_adapter(MutableBufferSequence const& buffers);
|
||||||
|
|
||||||
/// Returns the largest size output sequence possible.
|
/// Returns the largest size output sequence possible.
|
||||||
std::size_t
|
std::size_t
|
||||||
@@ -118,15 +117,25 @@ public:
|
|||||||
|
|
||||||
@throws std::length_error if the size would exceed the limit
|
@throws std::length_error if the size would exceed the limit
|
||||||
imposed by the underlying mutable buffer sequence.
|
imposed by the underlying mutable buffer sequence.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
*/
|
*/
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(std::size_t n);
|
prepare(std::size_t n);
|
||||||
|
|
||||||
/// Move bytes from the output sequence to the input sequence.
|
/** Move bytes from the output sequence to the input sequence.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
commit(std::size_t n);
|
commit(std::size_t n);
|
||||||
|
|
||||||
/// Get a list of buffers that represents the input sequence.
|
/** Get a list of buffers that represents the input sequence.
|
||||||
|
|
||||||
|
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||||
|
*/
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +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_BUFFERS_DEBUG_HPP
|
|
||||||
#define BEAST_BUFFERS_DEBUG_HPP
|
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
std::string s;
|
|
||||||
s.reserve(buffer_size(bs));
|
|
||||||
for(auto const& b : bs)
|
|
||||||
s.append(buffer_cast<char const*>(b),
|
|
||||||
buffer_size(b));
|
|
||||||
for(auto i = s.size(); i-- > 0;)
|
|
||||||
if(s[i] == '\r')
|
|
||||||
s.replace(i, 1, "\\r");
|
|
||||||
else if(s[i] == '\n')
|
|
||||||
s.replace(i, 1, "\\n\n");
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // debug
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#ifndef BEAST_CONSUMING_BUFFERS_HPP
|
#ifndef BEAST_CONSUMING_BUFFERS_HPP
|
||||||
#define BEAST_CONSUMING_BUFFERS_HPP
|
#define BEAST_CONSUMING_BUFFERS_HPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@@ -28,26 +29,29 @@ namespace beast {
|
|||||||
Ownership of the underlying memory is not transferred, the application
|
Ownership of the underlying memory is not transferred, the application
|
||||||
is still responsible for managing its lifetime.
|
is still responsible for managing its lifetime.
|
||||||
|
|
||||||
@tparam Buffers The buffer sequence to wrap.
|
@tparam BufferSequence The buffer sequence to wrap.
|
||||||
|
|
||||||
@ptaram ValueType The type of buffer of the final buffer sequence. This
|
@tparam ValueType The type of buffer of the final buffer sequence. This
|
||||||
can be different from the buffer type of the wrapped sequence. For
|
can be different from the buffer type of the wrapped sequence. For
|
||||||
example, a `MutableBufferSequence` can be transformed into a
|
example, a `MutableBufferSequence` can be transformed into a
|
||||||
consumable `ConstBufferSequence`. Violations of buffer const safety
|
consumable `ConstBufferSequence`. Violations of buffer const safety
|
||||||
are not permitted, and will result in a compile error.
|
are not permitted, and will result in a compile error.
|
||||||
*/
|
*/
|
||||||
template<class Buffers,
|
template<class BufferSequence,
|
||||||
class ValueType = typename Buffers::value_type>
|
class ValueType = typename BufferSequence::value_type>
|
||||||
class consuming_buffers
|
class consuming_buffers
|
||||||
{
|
{
|
||||||
using iter_type =
|
using iter_type =
|
||||||
typename Buffers::const_iterator;
|
typename BufferSequence::const_iterator;
|
||||||
|
|
||||||
|
static_assert(is_BufferSequence<BufferSequence, ValueType>::value,
|
||||||
|
"BufferSequence requirements not met");
|
||||||
|
|
||||||
static_assert(std::is_constructible<ValueType,
|
static_assert(std::is_constructible<ValueType,
|
||||||
typename std::iterator_traits<iter_type>::value_type>::value,
|
typename std::iterator_traits<iter_type>::value_type>::value,
|
||||||
"ValueType requirements not met");
|
"ValueType requirements not met");
|
||||||
|
|
||||||
Buffers bs_;
|
BufferSequence bs_;
|
||||||
iter_type begin_;
|
iter_type begin_;
|
||||||
std::size_t skip_ = 0;
|
std::size_t skip_ = 0;
|
||||||
|
|
||||||
@@ -90,7 +94,7 @@ public:
|
|||||||
underlying memory is not transferred or copied.
|
underlying memory is not transferred or copied.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
consuming_buffers(Buffers const& buffers);
|
consuming_buffers(BufferSequence const& buffers);
|
||||||
|
|
||||||
/// Get a bidirectional iterator to the first element.
|
/// Get a bidirectional iterator to the first element.
|
||||||
const_iterator
|
const_iterator
|
||||||
@@ -110,10 +114,24 @@ public:
|
|||||||
consume(std::size_t n);
|
consume(std::size_t n);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns a consumed buffer
|
/** Returns a new, consumed buffer sequence.
|
||||||
template<class Buffers>
|
|
||||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
This function returns a new buffer sequence which when iterated,
|
||||||
consumed_buffers(Buffers const& bs, std::size_t n);
|
efficiently represents the portion of the original buffer sequence
|
||||||
|
with `n` bytes removed from the beginning.
|
||||||
|
|
||||||
|
Copies will be made of the buffer sequence passed, but ownership
|
||||||
|
of the underlying memory is not transferred.
|
||||||
|
|
||||||
|
@param buffers The buffer sequence to consume.
|
||||||
|
|
||||||
|
@param n The number of bytes to remove from the front. If this is
|
||||||
|
larger than the size of the buffer sequence, an empty buffer sequence
|
||||||
|
is returned.
|
||||||
|
*/
|
||||||
|
template<class BufferSequence>
|
||||||
|
consuming_buffers<BufferSequence, typename BufferSequence::value_type>
|
||||||
|
consumed_buffers(BufferSequence const& buffers, std::size_t n);
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
|||||||
113
src/beast/include/beast/detail/bind_handler.hpp
Normal file
113
src/beast/include/beast/detail/bind_handler.hpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// 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_BIND_DETAIL_HANDLER_HPP
|
||||||
|
#define BEAST_BIND_DETAIL_HANDLER_HPP
|
||||||
|
|
||||||
|
#include <beast/detail/integer_sequence.hpp>
|
||||||
|
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||||
|
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||||
|
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/* Nullary handler that calls Handler with bound arguments.
|
||||||
|
|
||||||
|
The bound handler provides the same io_service execution
|
||||||
|
guarantees as the original handler.
|
||||||
|
*/
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
class bound_handler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using args_type = std::tuple<
|
||||||
|
typename std::decay<Args>::type...>;
|
||||||
|
|
||||||
|
Handler h_;
|
||||||
|
args_type args_;
|
||||||
|
|
||||||
|
template<class Tuple, std::size_t... S>
|
||||||
|
static void invoke(Handler& h, Tuple& args,
|
||||||
|
index_sequence<S...>)
|
||||||
|
{
|
||||||
|
h(std::get<S>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
using result_type = void;
|
||||||
|
|
||||||
|
template<class DeducedHandler>
|
||||||
|
explicit
|
||||||
|
bound_handler(DeducedHandler&& handler, Args&&... args)
|
||||||
|
: h_(std::forward<DeducedHandler>(handler))
|
||||||
|
, args_(std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator()()
|
||||||
|
{
|
||||||
|
invoke(h_, args_,
|
||||||
|
index_sequence_for<Args...> ());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator()() const
|
||||||
|
{
|
||||||
|
invoke(h_, args_,
|
||||||
|
index_sequence_for<Args...> ());
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
void*
|
||||||
|
asio_handler_allocate(
|
||||||
|
std::size_t size, bound_handler* h)
|
||||||
|
{
|
||||||
|
return boost_asio_handler_alloc_helpers::
|
||||||
|
allocate(size, h->h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
void
|
||||||
|
asio_handler_deallocate(
|
||||||
|
void* p, std::size_t size, bound_handler* h)
|
||||||
|
{
|
||||||
|
boost_asio_handler_alloc_helpers::
|
||||||
|
deallocate(p, size, h->h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
bool
|
||||||
|
asio_handler_is_continuation(bound_handler* h)
|
||||||
|
{
|
||||||
|
return boost_asio_handler_cont_helpers::
|
||||||
|
is_continuation (h->h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
friend
|
||||||
|
void
|
||||||
|
asio_handler_invoke(F&& f, bound_handler* h)
|
||||||
|
{
|
||||||
|
boost_asio_handler_invoke_helpers::
|
||||||
|
invoke(f, h->h_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
namespace std {
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
void bind(beast::detail::bound_handler<
|
||||||
|
Handler, Args...>, ...) = delete;
|
||||||
|
} // std
|
||||||
|
|
||||||
|
#endif
|
||||||
473
src/beast/include/beast/detail/buffer_cat.hpp
Normal file
473
src/beast/include/beast/detail/buffer_cat.hpp
Normal file
@@ -0,0 +1,473 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_BUFFER_CAT_HPP
|
||||||
|
#define BEAST_DETAIL_BUFFER_CAT_HPP
|
||||||
|
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iterator>
|
||||||
|
#include <new>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
class buffer_cat_helper
|
||||||
|
{
|
||||||
|
std::tuple<Bs...> bs_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = ValueType;
|
||||||
|
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
buffer_cat_helper(buffer_cat_helper&&) = default;
|
||||||
|
buffer_cat_helper(buffer_cat_helper const&) = default;
|
||||||
|
buffer_cat_helper& operator=(buffer_cat_helper&&) = default;
|
||||||
|
buffer_cat_helper& operator=(buffer_cat_helper const&) = default;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
buffer_cat_helper(Bs const&... bs)
|
||||||
|
: bs_(bs...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
begin() const;
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
end() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
std::size_t constexpr
|
||||||
|
max_sizeof()
|
||||||
|
{
|
||||||
|
return sizeof(U);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U0, class U1, class... Us>
|
||||||
|
std::size_t constexpr
|
||||||
|
max_sizeof()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
||||||
|
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
class buffer_cat_helper<
|
||||||
|
ValueType, Bs...>::const_iterator
|
||||||
|
{
|
||||||
|
std::size_t n_;
|
||||||
|
std::tuple<Bs...> const* bs_;
|
||||||
|
std::array<std::uint8_t,
|
||||||
|
max_sizeof<typename Bs::const_iterator...>()> buf_;
|
||||||
|
|
||||||
|
friend class buffer_cat_helper<ValueType, Bs...>;
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
using C = std::integral_constant<std::size_t, I>;
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
using iter_t = typename std::tuple_element<
|
||||||
|
I, std::tuple<Bs...>>::type::const_iterator;
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
iter_t<I>&
|
||||||
|
iter()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<
|
||||||
|
iter_t<I>*>(buf_.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
iter_t<I> const&
|
||||||
|
iter() const
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<
|
||||||
|
iter_t<I> const*>(buf_.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = ValueType;
|
||||||
|
using pointer = value_type const*;
|
||||||
|
using reference = value_type;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using iterator_category =
|
||||||
|
std::bidirectional_iterator_tag;
|
||||||
|
|
||||||
|
~const_iterator();
|
||||||
|
const_iterator();
|
||||||
|
const_iterator(const_iterator&& other);
|
||||||
|
const_iterator(const_iterator const& other);
|
||||||
|
const_iterator& operator=(const_iterator&& other);
|
||||||
|
const_iterator& operator=(const_iterator const& other);
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(const_iterator const& other) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!=(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
reference
|
||||||
|
operator*() const;
|
||||||
|
|
||||||
|
pointer
|
||||||
|
operator->() const = delete;
|
||||||
|
|
||||||
|
const_iterator&
|
||||||
|
operator++();
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
operator++(int)
|
||||||
|
{
|
||||||
|
auto temp = *this;
|
||||||
|
++(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator&
|
||||||
|
operator--();
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
operator--(int)
|
||||||
|
{
|
||||||
|
auto temp = *this;
|
||||||
|
--(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const_iterator(
|
||||||
|
std::tuple<Bs...> const& bs, bool at_end);
|
||||||
|
|
||||||
|
void
|
||||||
|
construct(C<sizeof...(Bs)>)
|
||||||
|
{
|
||||||
|
auto constexpr I = sizeof...(Bs);
|
||||||
|
n_ = I;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
construct(C<I>)
|
||||||
|
{
|
||||||
|
if(std::get<I>(*bs_).begin() !=
|
||||||
|
std::get<I>(*bs_).end())
|
||||||
|
{
|
||||||
|
n_ = I;
|
||||||
|
new(buf_.data()) iter_t<I>{
|
||||||
|
std::get<I>(*bs_).begin()};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
construct(C<I+1>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroy(C<sizeof...(Bs)>)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
destroy(C<I>)
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
using Iter = iter_t<I>;
|
||||||
|
iter<I>().~Iter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destroy(C<I+1>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
move(C<sizeof...(Bs)>, const_iterator&&)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
move(C<I>, const_iterator&& other)
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
new(buf_.data()) iter_t<I>{
|
||||||
|
std::move(other.iter<I>())};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
move(C<I+1>{}, std::move(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copy(C<sizeof...(Bs)>, const_iterator const&)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
copy(C<I>, const_iterator const& other)
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
new(buf_.data()) iter_t<I>{
|
||||||
|
other.iter<I>()};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
copy(C<I+1>{}, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
equal(C<sizeof...(Bs)>,
|
||||||
|
const_iterator const&) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
bool
|
||||||
|
equal(C<I>, const_iterator const& other) const
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
return iter<I>() == other.iter<I>();
|
||||||
|
return equal(C<I+1>{}, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]]
|
||||||
|
reference
|
||||||
|
dereference(C<sizeof...(Bs)>) const
|
||||||
|
{
|
||||||
|
throw std::logic_error("invalid iterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
reference
|
||||||
|
dereference(C<I>) const
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
return *iter<I>();
|
||||||
|
return dereference(C<I+1>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]]
|
||||||
|
void
|
||||||
|
increment(C<sizeof...(Bs)>)
|
||||||
|
{
|
||||||
|
throw std::logic_error("invalid iterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
increment(C<I>)
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
if(++iter<I>() !=
|
||||||
|
std::get<I>(*bs_).end())
|
||||||
|
return;
|
||||||
|
using Iter = iter_t<I>;
|
||||||
|
iter<I>().~Iter();
|
||||||
|
return construct(C<I+1>{});
|
||||||
|
}
|
||||||
|
increment(C<I+1>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
decrement(C<sizeof...(Bs)>)
|
||||||
|
{
|
||||||
|
auto constexpr I = sizeof...(Bs);
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
--n_;
|
||||||
|
new(buf_.data()) iter_t<I-1>{
|
||||||
|
std::get<I-1>(*bs_).end()};
|
||||||
|
}
|
||||||
|
decrement(C<I-1>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
decrement(C<0>)
|
||||||
|
{
|
||||||
|
auto constexpr I = 0;
|
||||||
|
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||||
|
{
|
||||||
|
--iter<I>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::logic_error("invalid iterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t I>
|
||||||
|
void
|
||||||
|
decrement(C<I>)
|
||||||
|
{
|
||||||
|
if(n_ == I)
|
||||||
|
{
|
||||||
|
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||||
|
{
|
||||||
|
--iter<I>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--n_;
|
||||||
|
using Iter = iter_t<I>;
|
||||||
|
iter<I>().~Iter();
|
||||||
|
new(buf_.data()) iter_t<I-1>{
|
||||||
|
std::get<I-1>(*bs_).end()};
|
||||||
|
}
|
||||||
|
decrement(C<I-1>{});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::~const_iterator()
|
||||||
|
{
|
||||||
|
destroy(C<0>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::const_iterator()
|
||||||
|
: n_(sizeof...(Bs))
|
||||||
|
, bs_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::const_iterator(
|
||||||
|
std::tuple<Bs...> const& bs, bool at_end)
|
||||||
|
: bs_(&bs)
|
||||||
|
{
|
||||||
|
if(at_end)
|
||||||
|
n_ = sizeof...(Bs);
|
||||||
|
else
|
||||||
|
construct(C<0>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::const_iterator(const_iterator&& other)
|
||||||
|
: n_(other.n_)
|
||||||
|
, bs_(other.bs_)
|
||||||
|
{
|
||||||
|
move(C<0>{}, std::move(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::const_iterator(const_iterator const& other)
|
||||||
|
: n_(other.n_)
|
||||||
|
, bs_(other.bs_)
|
||||||
|
{
|
||||||
|
copy(C<0>{}, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator=(const_iterator&& other) ->
|
||||||
|
const_iterator&
|
||||||
|
{
|
||||||
|
if(&other == this)
|
||||||
|
return *this;
|
||||||
|
destroy(C<0>{});
|
||||||
|
n_ = other.n_;
|
||||||
|
bs_ = other.bs_;
|
||||||
|
move(C<0>{}, std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator=(const_iterator const& other) ->
|
||||||
|
const_iterator&
|
||||||
|
{
|
||||||
|
if(&other == this)
|
||||||
|
return *this;
|
||||||
|
destroy(C<0>{});
|
||||||
|
n_ = other.n_;
|
||||||
|
bs_ = other.bs_;
|
||||||
|
copy(C<0>{}, other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
bool
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator==(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
if(bs_ != other.bs_)
|
||||||
|
return false;
|
||||||
|
if(n_ != other.n_)
|
||||||
|
return false;
|
||||||
|
return equal(C<0>{}, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator*() const ->
|
||||||
|
reference
|
||||||
|
{
|
||||||
|
return dereference(C<0>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator++() ->
|
||||||
|
const_iterator&
|
||||||
|
{
|
||||||
|
increment(C<0>{});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::
|
||||||
|
const_iterator::operator--() ->
|
||||||
|
const_iterator&
|
||||||
|
{
|
||||||
|
decrement(C<sizeof...(Bs)>{});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::begin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator(bs_, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ValueType, class... Bs>
|
||||||
|
auto
|
||||||
|
buffer_cat_helper<ValueType, Bs...>::end() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator(bs_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
140
src/beast/include/beast/detail/buffer_concepts.hpp
Normal file
140
src/beast/include/beast/detail/buffer_concepts.hpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_BUFFER_CONCEPTS_HPP
|
||||||
|
#define BEAST_DETAIL_BUFFER_CONCEPTS_HPP
|
||||||
|
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Types that meet the requirements,
|
||||||
|
// for use with std::declval only.
|
||||||
|
template<class BufferType>
|
||||||
|
struct BufferSequence
|
||||||
|
{
|
||||||
|
using value_type = BufferType;
|
||||||
|
using const_iterator = BufferType const*;
|
||||||
|
~BufferSequence();
|
||||||
|
BufferSequence(BufferSequence const&) = default;
|
||||||
|
const_iterator begin() const noexcept;
|
||||||
|
const_iterator end() const noexcept;
|
||||||
|
};
|
||||||
|
using ConstBufferSequence =
|
||||||
|
BufferSequence<boost::asio::const_buffer>;
|
||||||
|
using MutableBufferSequence =
|
||||||
|
BufferSequence<boost::asio::mutable_buffer>;
|
||||||
|
|
||||||
|
template<class T, class BufferType>
|
||||||
|
class is_BufferSequence
|
||||||
|
{
|
||||||
|
template<class U, class R = std::is_convertible<
|
||||||
|
typename U::value_type, BufferType> >
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_base_of<
|
||||||
|
#if 0
|
||||||
|
std::bidirectional_iterator_tag,
|
||||||
|
typename std::iterator_traits<
|
||||||
|
typename U::const_iterator>::iterator_category>>
|
||||||
|
#else
|
||||||
|
// workaround:
|
||||||
|
// boost::asio::detail::consuming_buffers::const_iterator
|
||||||
|
// is not bidirectional
|
||||||
|
std::forward_iterator_tag,
|
||||||
|
typename std::iterator_traits<
|
||||||
|
typename U::const_iterator>::iterator_category>>
|
||||||
|
#endif
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = typename
|
||||||
|
std::is_convertible<decltype(
|
||||||
|
std::declval<U>().begin()),
|
||||||
|
typename U::const_iterator>::type>
|
||||||
|
static R check3(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check3(...);
|
||||||
|
using type3 = decltype(check3<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = typename std::is_convertible<decltype(
|
||||||
|
std::declval<U>().end()),
|
||||||
|
typename U::const_iterator>::type>
|
||||||
|
static R check4(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check4(...);
|
||||||
|
using type4 = decltype(check4<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
std::is_copy_constructible<T>::value &&
|
||||||
|
std::is_destructible<T>::value &&
|
||||||
|
type1::value && type2::value &&
|
||||||
|
type3::value && type4::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_Streambuf
|
||||||
|
{
|
||||||
|
template<class U, class R = std::integral_constant<
|
||||||
|
bool, is_BufferSequence<decltype(
|
||||||
|
std::declval<U>().prepare(1)),
|
||||||
|
boost::asio::mutable_buffer>::type::value>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::integral_constant<
|
||||||
|
bool, is_BufferSequence<decltype(
|
||||||
|
std::declval<U>().data()),
|
||||||
|
boost::asio::const_buffer>::type::value>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().commit(1), std::true_type{})>
|
||||||
|
static R check3(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check3(...);
|
||||||
|
using type3 = decltype(check3<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().consume(1), std::true_type{})>
|
||||||
|
static R check4(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check4(...);
|
||||||
|
using type4 = decltype(check4<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().size()), std::size_t>>
|
||||||
|
static R check5(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check5(...);
|
||||||
|
using type5 = decltype(check5<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value && type2::value &&
|
||||||
|
type3::value && type4::value &&
|
||||||
|
type5::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
53
src/beast/include/beast/detail/get_lowest_layer.hpp
Normal file
53
src/beast/include/beast/detail/get_lowest_layer.hpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_GET_LOWEST_LAYER_HPP
|
||||||
|
#define BEAST_DETAIL_GET_LOWEST_LAYER_HPP
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class has_lowest_layer
|
||||||
|
{
|
||||||
|
template<class U, class R =
|
||||||
|
typename U::lowest_layer_type>
|
||||||
|
static std::true_type check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
static bool constexpr value = type::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, bool B>
|
||||||
|
struct maybe_get_lowest_layer
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct maybe_get_lowest_layer<T, true>
|
||||||
|
{
|
||||||
|
using type = typename T::lowest_layer_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If T has a nested type lowest_layer_type,
|
||||||
|
// returns that, else returns T.
|
||||||
|
template<class T>
|
||||||
|
struct get_lowest_layer
|
||||||
|
{
|
||||||
|
using type = typename maybe_get_lowest_layer<T,
|
||||||
|
has_lowest_layer<T>::value>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
140
src/beast/include/beast/detail/stream_concepts.hpp
Normal file
140
src/beast/include/beast/detail/stream_concepts.hpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_STREAM_CONCEPTS_HPP
|
||||||
|
#define BEAST_DETAIL_STREAM_CONCEPTS_HPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
|
#include <boost/asio/io_service.hpp>
|
||||||
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Types that meet the requirements,
|
||||||
|
// for use with std::declval only.
|
||||||
|
struct StreamHandler
|
||||||
|
{
|
||||||
|
StreamHandler(StreamHandler const&) = default;
|
||||||
|
void operator()(boost::system::error_code ec, std::size_t);
|
||||||
|
};
|
||||||
|
using ReadHandler = StreamHandler;
|
||||||
|
using WriteHandler = StreamHandler;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class has_get_io_service
|
||||||
|
{
|
||||||
|
template<class U, class R = typename std::is_same<
|
||||||
|
decltype(std::declval<U>().get_io_service()),
|
||||||
|
boost::asio::io_service&>>
|
||||||
|
static R check(int);
|
||||||
|
template <class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
public:
|
||||||
|
using type = decltype(check<T>(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_AsyncReadStream
|
||||||
|
{
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().async_read_some(
|
||||||
|
std::declval<MutableBufferSequence>(),
|
||||||
|
std::declval<ReadHandler>()),
|
||||||
|
std::true_type{})>
|
||||||
|
static R check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type1 = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value &&
|
||||||
|
has_get_io_service<T>::type::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_AsyncWriteStream
|
||||||
|
{
|
||||||
|
template<class U, class R = decltype(
|
||||||
|
std::declval<U>().async_write_some(
|
||||||
|
std::declval<ConstBufferSequence>(),
|
||||||
|
std::declval<WriteHandler>()),
|
||||||
|
std::true_type{})>
|
||||||
|
static R check(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type1 = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value &&
|
||||||
|
has_get_io_service<T>::type::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_SyncReadStream
|
||||||
|
{
|
||||||
|
using error_code =
|
||||||
|
boost::system::error_code;
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().read_some(
|
||||||
|
std::declval<MutableBufferSequence>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().read_some(
|
||||||
|
std::declval<MutableBufferSequence>(),
|
||||||
|
std::declval<error_code&>())), std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value && type2::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class is_SyncWriteStream
|
||||||
|
{
|
||||||
|
using error_code =
|
||||||
|
boost::system::error_code;
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().write_some(
|
||||||
|
std::declval<ConstBufferSequence>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R = std::is_same<decltype(
|
||||||
|
std::declval<U>().write_some(
|
||||||
|
std::declval<ConstBufferSequence>(),
|
||||||
|
std::declval<error_code&>())), std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = std::integral_constant<bool,
|
||||||
|
type1::value && type2::value>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
||||||
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -41,13 +42,6 @@ public:
|
|||||||
! is_string_literal<T>::value;
|
! is_string_literal<T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Streambuf>
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
write_streambuf(Streambuf&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class Streambuf>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf,
|
write_streambuf(Streambuf& streambuf,
|
||||||
@@ -133,11 +127,11 @@ write_streambuf(Streambuf& streambuf, T const& t)
|
|||||||
|
|
||||||
template<class Streambuf, class T0, class T1, class... TN>
|
template<class Streambuf, class T0, class T1, class... TN>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf, T0&& t0, T1&& t1, TN... tn)
|
write_streambuf(Streambuf& streambuf,
|
||||||
|
T0 const& t0, T1 const& t1, TN const&... tn)
|
||||||
{
|
{
|
||||||
write_streambuf(streambuf, std::forward<T0>(t0));
|
write_streambuf(streambuf, t0);
|
||||||
write_streambuf(streambuf, std::forward<T1>(t1));
|
write_streambuf(streambuf, t1, tn...);
|
||||||
write_streambuf(streambuf, std::forward<TN>(tn)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
170
src/beast/include/beast/doc_debug.hpp
Normal file
170
src/beast/include/beast/doc_debug.hpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
//
|
||||||
|
// 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_DOC_DEBUG_HPP
|
||||||
|
#define BEAST_DOC_DEBUG_HPP
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
|
||||||
|
/// doc type (documentation debug helper)
|
||||||
|
using doc_type = int;
|
||||||
|
|
||||||
|
/// doc enum (documentation debug helper)
|
||||||
|
enum doc_enum
|
||||||
|
{
|
||||||
|
/// One (documentation debug helper)
|
||||||
|
one,
|
||||||
|
|
||||||
|
/// Two (documentation debug helper)
|
||||||
|
two
|
||||||
|
};
|
||||||
|
|
||||||
|
/// doc enum class (documentation debug helper)
|
||||||
|
enum class doc_enum_class : unsigned
|
||||||
|
{
|
||||||
|
/// one (documentation debug helper)
|
||||||
|
one,
|
||||||
|
|
||||||
|
/// two (documentation debug helper)
|
||||||
|
two
|
||||||
|
};
|
||||||
|
|
||||||
|
/// doc func (documentation debug helper)
|
||||||
|
void doc_func();
|
||||||
|
|
||||||
|
/// doc class (documentation debug helper)
|
||||||
|
struct doc_class
|
||||||
|
{
|
||||||
|
/// doc class member func (documentation debug helper)
|
||||||
|
void func();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// (documentation debug helper)
|
||||||
|
namespace nested {
|
||||||
|
|
||||||
|
/// doc type (documentation debug helper)
|
||||||
|
using nested_doc_type = int;
|
||||||
|
|
||||||
|
/// doc enum (documentation debug helper)
|
||||||
|
enum nested_doc_enum
|
||||||
|
{
|
||||||
|
/// One (documentation debug helper)
|
||||||
|
one,
|
||||||
|
|
||||||
|
/// Two (documentation debug helper)
|
||||||
|
two
|
||||||
|
};
|
||||||
|
|
||||||
|
/// doc enum class (documentation debug helper)
|
||||||
|
enum class nested_doc_enum_class : unsigned
|
||||||
|
{
|
||||||
|
/// one (documentation debug helper)
|
||||||
|
one,
|
||||||
|
|
||||||
|
/// two (documentation debug helper)
|
||||||
|
two
|
||||||
|
};
|
||||||
|
|
||||||
|
/// doc func (documentation debug helper)
|
||||||
|
void nested_doc_func();
|
||||||
|
|
||||||
|
/// doc class (documentation debug helper)
|
||||||
|
struct nested_doc_class
|
||||||
|
{
|
||||||
|
/// doc class member func (documentation debug helper)
|
||||||
|
void func();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // nested
|
||||||
|
|
||||||
|
/** This is here to help troubleshoot doc/reference.xsl problems
|
||||||
|
|
||||||
|
Embedded references:
|
||||||
|
|
||||||
|
@li type @ref doc_type
|
||||||
|
|
||||||
|
@li enum @ref doc_enum
|
||||||
|
|
||||||
|
@li enum item @ref doc_enum::one
|
||||||
|
|
||||||
|
@li enum_class @ref doc_enum_class
|
||||||
|
|
||||||
|
@li enum_class item @ref doc_enum_class::one
|
||||||
|
|
||||||
|
@li func @ref doc_func
|
||||||
|
|
||||||
|
@li class @ref doc_class
|
||||||
|
|
||||||
|
@li class func @ref doc_class::func
|
||||||
|
|
||||||
|
@li nested type @ref nested::nested_doc_type
|
||||||
|
|
||||||
|
@li nested enum @ref nested::nested_doc_enum
|
||||||
|
|
||||||
|
@li nested enum item @ref nested::nested_doc_enum::one
|
||||||
|
|
||||||
|
@li nested enum_class @ref nested::nested_doc_enum_class
|
||||||
|
|
||||||
|
@li nested enum_class item @ref nested::nested_doc_enum_class::one
|
||||||
|
|
||||||
|
@li nested func @ref nested::nested_doc_func
|
||||||
|
|
||||||
|
@li nested class @ref nested::nested_doc_class
|
||||||
|
|
||||||
|
@li nested class func @ref nested::nested_doc_class::func
|
||||||
|
*/
|
||||||
|
void doc_debug();
|
||||||
|
|
||||||
|
namespace nested {
|
||||||
|
|
||||||
|
/** This is here to help troubleshoot doc/reference.xsl problems
|
||||||
|
|
||||||
|
Embedded references:
|
||||||
|
|
||||||
|
@li type @ref doc_type
|
||||||
|
|
||||||
|
@li enum @ref doc_enum
|
||||||
|
|
||||||
|
@li enum item @ref doc_enum::one
|
||||||
|
|
||||||
|
@li enum_class @ref doc_enum_class
|
||||||
|
|
||||||
|
@li enum_class item @ref doc_enum_class::one
|
||||||
|
|
||||||
|
@li func @ref doc_func
|
||||||
|
|
||||||
|
@li class @ref doc_class
|
||||||
|
|
||||||
|
@li class func @ref doc_class::func
|
||||||
|
|
||||||
|
@li nested type @ref nested_doc_type
|
||||||
|
|
||||||
|
@li nested enum @ref nested_doc_enum
|
||||||
|
|
||||||
|
@li nested enum item @ref nested_doc_enum::one
|
||||||
|
|
||||||
|
@li nested enum_class @ref nested_doc_enum_class
|
||||||
|
|
||||||
|
@li nested enum_class item @ref nested_doc_enum_class::one
|
||||||
|
|
||||||
|
@li nested func @ref nested_doc_func
|
||||||
|
|
||||||
|
@li nested class @ref nested_doc_class
|
||||||
|
|
||||||
|
@li nested class func @ref nested_doc_class::func
|
||||||
|
*/
|
||||||
|
void nested_doc_debug();
|
||||||
|
|
||||||
|
} // nested
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -28,28 +28,28 @@ namespace beast {
|
|||||||
|
|
||||||
@tparam T The type of objects allocated by the allocator.
|
@tparam T The type of objects allocated by the allocator.
|
||||||
|
|
||||||
@tparam Handler The type of handler.
|
@tparam CompletionHandler The type of handler.
|
||||||
|
|
||||||
@note Allocated memory is only valid until the handler is called. The
|
@note Allocated memory is only valid until the handler is called. The
|
||||||
caller is still responsible for freeing memory.
|
caller is still responsible for freeing memory.
|
||||||
*/
|
*/
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
template <class T, class Handler>
|
template <class T, class CompletionHandler>
|
||||||
class handler_alloc;
|
class handler_alloc;
|
||||||
#else
|
#else
|
||||||
template <class T, class Handler>
|
template <class T, class CompletionHandler>
|
||||||
class handler_alloc
|
class handler_alloc
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// We want a partial template specialization as a friend
|
// We want a partial template specialization as a friend
|
||||||
// but that isn't allowed so we friend all versions. This
|
// but that isn't allowed so we friend all versions. This
|
||||||
// should produce a compile error if Handler is not
|
// should produce a compile error if CompletionHandler is not
|
||||||
// constructible from H.
|
// constructible from H.
|
||||||
//
|
//
|
||||||
template <class U, class H>
|
template <class U, class H>
|
||||||
friend class handler_alloc;
|
friend class handler_alloc;
|
||||||
|
|
||||||
Handler h_;
|
CompletionHandler h_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
The handler is moved or copied into the allocator.
|
The handler is moved or copied into the allocator.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
handler_alloc(Handler&& h)
|
handler_alloc(CompletionHandler&& h)
|
||||||
: h_(std::move(h))
|
: h_(std::move(h))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -76,21 +76,21 @@ public:
|
|||||||
A copy of the handler is made.
|
A copy of the handler is made.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
handler_alloc(Handler const& h)
|
handler_alloc(CompletionHandler const& h)
|
||||||
: h_(h)
|
: h_(h)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
handler_alloc(
|
handler_alloc(
|
||||||
handler_alloc<U, Handler>&& other)
|
handler_alloc<U, CompletionHandler>&& other)
|
||||||
: h_(std::move(other.h_))
|
: h_(std::move(other.h_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
handler_alloc(
|
handler_alloc(
|
||||||
handler_alloc<U, Handler> const& other)
|
handler_alloc<U, CompletionHandler> const& other)
|
||||||
: h_(other.h_)
|
: h_(other.h_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ public:
|
|||||||
friend
|
friend
|
||||||
bool
|
bool
|
||||||
operator==(handler_alloc const& lhs,
|
operator==(handler_alloc const& lhs,
|
||||||
handler_alloc<U, Handler> const& rhs)
|
handler_alloc<U, CompletionHandler> const& rhs)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ public:
|
|||||||
friend
|
friend
|
||||||
bool
|
bool
|
||||||
operator!=(handler_alloc const& lhs,
|
operator!=(handler_alloc const& lhs,
|
||||||
handler_alloc<U, Handler> const& rhs)
|
handler_alloc<U, CompletionHandler> const& rhs)
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/beast/include/beast/handler_concepts.hpp
Normal file
27
src/beast/include/beast/handler_concepts.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// 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_HANDLER_CONCEPTS_HPP
|
||||||
|
#define BEAST_HANDLER_CONCEPTS_HPP
|
||||||
|
|
||||||
|
#include <beast/detail/is_call_possible.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `CompletionHandler`.
|
||||||
|
template<class T, class Signature>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
using is_CompletionHandler = std::integral_constant<bool, ...>;
|
||||||
|
#else
|
||||||
|
using is_CompletionHandler = std::integral_constant<bool,
|
||||||
|
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
||||||
|
detail::is_call_possible<T, Signature>::value>;
|
||||||
|
#endif
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,18 +5,19 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_HPP_INCLUDED
|
#ifndef BEAST_HTTP_HPP
|
||||||
#define BEAST_HTTP_HPP_INCLUDED
|
#define BEAST_HTTP_HPP
|
||||||
|
|
||||||
#include <beast/http/basic_headers.hpp>
|
#include <beast/http/basic_headers.hpp>
|
||||||
#include <beast/http/basic_parser.hpp>
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
#include <beast/http/chunk_encode.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/headers.hpp>
|
#include <beast/http/headers.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/parse_error.hpp>
|
#include <beast/http/parse_error.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/reason.hpp>
|
#include <beast/http/reason.hpp>
|
||||||
#include <beast/http/resume_context.hpp>
|
#include <beast/http/resume_context.hpp>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
|
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
|
||||||
#define BEAST_HTTP_BASIC_HEADERS_HPP
|
#define BEAST_HTTP_BASIC_HEADERS_HPP
|
||||||
|
|
||||||
#include <beast/type_check.hpp>
|
|
||||||
#include <beast/detail/ci_char_traits.hpp>
|
#include <beast/detail/ci_char_traits.hpp>
|
||||||
#include <beast/detail/empty_base_optimization.hpp>
|
#include <beast/detail/empty_base_optimization.hpp>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
@@ -237,9 +236,20 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Container to store HTTP headers.
|
/** A container for storing HTTP headers.
|
||||||
|
|
||||||
Meets the requirements of `FieldSequence`.
|
This container is designed to store the field value pairs that make
|
||||||
|
up the headers and trailers in a HTTP message. Objects of this type
|
||||||
|
are iterable, which each element holding the field name and field
|
||||||
|
value.
|
||||||
|
|
||||||
|
Field names are stored as-is, but comparison are case-insensitive.
|
||||||
|
The container preserves the order of insertion of fields with
|
||||||
|
different names. For fields with the same name, the implementation
|
||||||
|
concatenates values inserted with duplicate names as per the
|
||||||
|
rules in rfc2616 section 4.2.
|
||||||
|
|
||||||
|
@note Meets the requirements of @b `FieldSequence`.
|
||||||
*/
|
*/
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class basic_headers
|
class basic_headers
|
||||||
|
|||||||
@@ -5,15 +5,14 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_BASIC_PARSER_HPP
|
#ifndef BEAST_HTTP_BASIC_PARSER_v1_HPP
|
||||||
#define BEAST_HTTP_BASIC_PARSER_HPP
|
#define BEAST_HTTP_BASIC_PARSER_v1_HPP
|
||||||
|
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
#include <beast/http/parse_error.hpp>
|
#include <beast/http/parse_error.hpp>
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/http/detail/basic_parser.hpp>
|
#include <beast/http/detail/basic_parser_v1.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <beast/detail/ci_char_traits.hpp>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@@ -37,55 +36,55 @@ enum values
|
|||||||
};
|
};
|
||||||
} // parse_flag
|
} // parse_flag
|
||||||
|
|
||||||
/** Parser for producing HTTP requests and responses.
|
/** Base class for parsing HTTP/1 requests and responses.
|
||||||
|
|
||||||
During parsing, callbacks will be made to the derived class
|
During parsing, callbacks will be made to the derived class
|
||||||
if those members are present (detected through SFINAE). The
|
if those members are present (detected through SFINAE). The
|
||||||
signatures which can be present in the derived class are:<br>
|
signatures which can be present in the derived class are:<br>
|
||||||
|
|
||||||
@li `void on_method(boost::string_ref const&, error_code& ec)`
|
@li `void on_method(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the Request-Method
|
Called for each piece of the Request-Method
|
||||||
|
|
||||||
@li `void on_uri(boost::string_ref const&, error_code& ec)`
|
@li `void on_uri(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the Request-URI
|
Called for each piece of the Request-URI
|
||||||
|
|
||||||
@li `void on_reason(boost::string_ref const&, error_code& ec)`
|
@li `void on_reason(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the reason-phrase
|
Called for each piece of the reason-phrase
|
||||||
|
|
||||||
@li `void on_request(error_code& ec)`
|
@li `void on_request(error_code&)`
|
||||||
|
|
||||||
Called after the entire Request-Line has been parsed successfully.
|
Called after the entire Request-Line has been parsed successfully.
|
||||||
|
|
||||||
@li `void on_response(error_code& ec)`
|
@li `void on_response(error_code&)`
|
||||||
|
|
||||||
Called after the entire Response-Line has been parsed successfully.
|
Called after the entire Response-Line has been parsed successfully.
|
||||||
|
|
||||||
@li `void on_field(boost::string_ref const&, error_code& ec)`
|
@li `void on_field(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the current header field.
|
Called for each piece of the current header field.
|
||||||
|
|
||||||
@li `void on_value(boost::string_ref const&, error_code& ec)`
|
@li `void on_value(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the current header value.
|
Called for each piece of the current header value.
|
||||||
|
|
||||||
@li `int on_headers(error_code& ec)`
|
@li `int on_headers(error_code&)`
|
||||||
|
|
||||||
Called when all the headers have been parsed successfully.
|
Called when all the headers have been parsed successfully.
|
||||||
|
|
||||||
@li `void on_body(boost::string_ref const&, error_code& ec)`
|
@li `void on_body(boost::string_ref const&, error_code&)`
|
||||||
|
|
||||||
Called for each piece of the body. If the headers indicated
|
Called for each piece of the body. If the headers indicated
|
||||||
chunked encoding, the chunk encoding is removed from the
|
chunked encoding, the chunk encoding is removed from the
|
||||||
buffer before being passed to the callback.
|
buffer before being passed to the callback.
|
||||||
|
|
||||||
@li `void on_complete(error_code& ec)`
|
@li `void on_complete(error_code&)`
|
||||||
|
|
||||||
Called when the entire message has been parsed successfully.
|
Called when the entire message has been parsed successfully.
|
||||||
At this point, basic_parser::complete() returns `true`, and
|
At this point, @ref basic_parser_v1::complete returns `true`, and
|
||||||
the parser is ready to parse another message if keep_alive()
|
the parser is ready to parse another message if keep_alive
|
||||||
would return `true`.
|
would return `true`.
|
||||||
|
|
||||||
The return value of `on_headers` is special, it controls whether
|
The return value of `on_headers` is special, it controls whether
|
||||||
@@ -101,7 +100,7 @@ enum values
|
|||||||
|
|
||||||
The parser uses traits to determine if the callback is possible.
|
The parser uses traits to determine if the callback is possible.
|
||||||
If the Derived type omits one or more callbacks, they are simply
|
If the Derived type omits one or more callbacks, they are simply
|
||||||
skipped with no compilation error. The default behavior of on_body
|
skipped with no compilation error. The default behavior of `on_body`
|
||||||
when the derived class does not provide the member, is to specify that
|
when the derived class does not provide the member, is to specify that
|
||||||
the body should not be skipped.
|
the body should not be skipped.
|
||||||
|
|
||||||
@@ -109,10 +108,10 @@ enum values
|
|||||||
and the error is returned to the caller.
|
and the error is returned to the caller.
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
class basic_parser
|
class basic_parser_v1
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using self = basic_parser;
|
using self = basic_parser_v1;
|
||||||
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
||||||
|
|
||||||
static std::uint64_t constexpr no_content_length =
|
static std::uint64_t constexpr no_content_length =
|
||||||
@@ -237,13 +236,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
basic_parser(basic_parser const&) = default;
|
basic_parser_v1(basic_parser_v1 const&) = default;
|
||||||
|
|
||||||
/// Copy assignment.
|
/// Copy assignment.
|
||||||
basic_parser& operator=(basic_parser const&) = default;
|
basic_parser_v1& operator=(basic_parser_v1 const&) = default;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
basic_parser()
|
basic_parser_v1()
|
||||||
{
|
{
|
||||||
init(std::integral_constant<bool, isRequest>{});
|
init(std::integral_constant<bool, isRequest>{});
|
||||||
}
|
}
|
||||||
@@ -345,7 +344,7 @@ public:
|
|||||||
return s_ == s_restart;
|
return s_ == s_restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write data to the parser.
|
/** Write a sequence of buffers to the parser.
|
||||||
|
|
||||||
@param buffers An object meeting the requirements of
|
@param buffers An object meeting the requirements of
|
||||||
ConstBufferSequence that represents the input sequence.
|
ConstBufferSequence that represents the input sequence.
|
||||||
@@ -355,19 +354,25 @@ public:
|
|||||||
@return The number of bytes consumed in the input sequence.
|
@return The number of bytes consumed in the input sequence.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
|
#if GENERATING_DOCS
|
||||||
std::size_t
|
std::size_t
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
! std::is_convertible<ConstBufferSequence,
|
||||||
|
boost::asio::const_buffer>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
#endif
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec);
|
write(ConstBufferSequence const& buffers, error_code& ec);
|
||||||
|
|
||||||
/** Write data to the parser.
|
/** Write a single buffer of data to the parser.
|
||||||
|
|
||||||
@param data A pointer to a buffer representing the input sequence.
|
@param buffer The buffer to write.
|
||||||
@param size The number of bytes in the buffer pointed to by data.
|
|
||||||
@param ec Set to the error, if any error occurred.
|
@param ec Set to the error, if any error occurred.
|
||||||
|
|
||||||
@return The number of bytes consumed in the input sequence.
|
@return The number of bytes consumed in the buffer.
|
||||||
*/
|
*/
|
||||||
std::size_t
|
std::size_t
|
||||||
write(void const* data, std::size_t size, error_code& ec);
|
write(boost::asio::const_buffer const& buffer, error_code& ec);
|
||||||
|
|
||||||
/** Called to indicate the end of file.
|
/** Called to indicate the end of file.
|
||||||
|
|
||||||
@@ -377,8 +382,6 @@ public:
|
|||||||
Callbacks and errors will still be processed as usual.
|
Callbacks and errors will still be processed as usual.
|
||||||
|
|
||||||
@note This is typically called when a socket read returns eof.
|
@note This is typically called when a socket read returns eof.
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
write_eof(error_code& ec);
|
write_eof(error_code& ec);
|
||||||
@@ -756,6 +759,6 @@ private:
|
|||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#include <beast/http/impl/basic_parser.ipp>
|
#include <beast/http/impl/basic_parser_v1.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
19
src/beast/include/beast/http/body_type.hpp
Normal file
19
src/beast/include/beast/http/body_type.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// 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_BODY_TYPE_HPP
|
||||||
|
#define BEAST_HTTP_BODY_TYPE_HPP
|
||||||
|
|
||||||
|
// Convenience header to include everything
|
||||||
|
// needed when declarating a user defined Body type.
|
||||||
|
|
||||||
|
#include <beast/http/error.hpp>
|
||||||
|
#include <beast/http/message.hpp>
|
||||||
|
#include <beast/http/resume_context.hpp>
|
||||||
|
#include <boost/logic/tribool.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
|
#ifndef BEAST_HTTP_DETAIL_BASIC_PARSER_V1_HPP
|
||||||
#define BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
|
#define BEAST_HTTP_DETAIL_BASIC_PARSER_V1_HPP
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <boost/utility/string_ref.hpp>
|
#include <boost/utility/string_ref.hpp>
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_CHUNK_ENCODE_HPP
|
#ifndef BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||||
#define BEAST_HTTP_CHUNK_ENCODE_HPP
|
#define BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||||
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <class Buffers>
|
template <class Buffers>
|
||||||
@@ -237,9 +236,7 @@ chunk_encoded_buffers<Buffers>::const_iterator::const_iterator(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
/* Returns a chunk-encoded BufferSequence.
|
||||||
|
|
||||||
/** Returns a chunk-encoded BufferSequence.
|
|
||||||
|
|
||||||
See:
|
See:
|
||||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
|
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
|
||||||
@@ -276,6 +273,7 @@ chunk_encode_final()
|
|||||||
"0\r\n\r\n", 5);
|
"0\r\n\r\n", 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
43
src/beast/include/beast/http/detail/has_content_length.hpp
Normal file
43
src/beast/include/beast/http/detail/has_content_length.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_HAS_CONTENT_LENGTH_HPP
|
||||||
|
#define BEAST_HTTP_DETAIL_HAS_CONTENT_LENGTH_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class has_content_length_value
|
||||||
|
{
|
||||||
|
template<class U, class R = typename std::is_convertible<
|
||||||
|
decltype(std::declval<U>().content_length()),
|
||||||
|
std::uint64_t>>
|
||||||
|
static R check(int);
|
||||||
|
template <class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
// `true` if `T` meets the requirements.
|
||||||
|
static bool const value = type::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determines if the writer can provide the content length
|
||||||
|
template<class T>
|
||||||
|
using has_content_length =
|
||||||
|
std::integral_constant<bool,
|
||||||
|
has_content_length_value<T>::value>;
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,123 +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_DETAIL_WRITE_PREPARATION_HPP
|
|
||||||
#define BEAST_HTTP_DETAIL_WRITE_PREPARATION_HPP
|
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
|
||||||
#include <beast/write_streambuf.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class has_content_length_value
|
|
||||||
{
|
|
||||||
template<class U, class R = typename std::is_convertible<
|
|
||||||
decltype(std::declval<U>().content_length()),
|
|
||||||
std::size_t>>
|
|
||||||
static R check(int);
|
|
||||||
template <class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
public:
|
|
||||||
// `true` if `T` meets the requirements.
|
|
||||||
static bool const value = type::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determines if the writer can provide the content length
|
|
||||||
template<class T>
|
|
||||||
using has_content_length =
|
|
||||||
std::integral_constant<bool,
|
|
||||||
has_content_length_value<T>::value>;
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
struct write_preparation
|
|
||||||
{
|
|
||||||
using headers_type =
|
|
||||||
basic_headers<std::allocator<char>>;
|
|
||||||
|
|
||||||
message<isRequest, Body, Headers> const& msg;
|
|
||||||
typename Body::writer w;
|
|
||||||
streambuf sb;
|
|
||||||
bool chunked;
|
|
||||||
bool close;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
write_preparation(
|
|
||||||
message<isRequest, Body, Headers> const& msg_)
|
|
||||||
: msg(msg_)
|
|
||||||
, w(msg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
init(error_code& ec)
|
|
||||||
{
|
|
||||||
w.init(ec);
|
|
||||||
if(ec)
|
|
||||||
return;
|
|
||||||
// VFALCO TODO This implementation requires making a
|
|
||||||
// copy of the headers, we can do better.
|
|
||||||
// VFALCO Should we be using handler_alloc?
|
|
||||||
headers_type h(msg.headers.begin(), msg.headers.end());
|
|
||||||
set_content_length(h, has_content_length<
|
|
||||||
typename Body::writer>{});
|
|
||||||
|
|
||||||
// VFALCO TODO Keep-Alive
|
|
||||||
|
|
||||||
if(close)
|
|
||||||
{
|
|
||||||
if(msg.version >= 11)
|
|
||||||
h.insert("Connection", "close");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(msg.version < 11)
|
|
||||||
h.insert("Connection", "keep-alive");
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.write_firstline(sb);
|
|
||||||
write_fields(sb, h);
|
|
||||||
beast::write(sb, "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void
|
|
||||||
set_content_length(headers_type& h,
|
|
||||||
std::true_type)
|
|
||||||
{
|
|
||||||
close = false;
|
|
||||||
chunked = false;
|
|
||||||
h.insert("Content-Length", w.content_length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_content_length(headers_type& h,
|
|
||||||
std::false_type)
|
|
||||||
{
|
|
||||||
if(msg.version >= 11)
|
|
||||||
{
|
|
||||||
close = false;
|
|
||||||
chunked = true;
|
|
||||||
h.insert("Transfer-Encoding", "chunked");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close = true;
|
|
||||||
chunked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
||||||
#define BEAST_HTTP_EMPTY_BODY_HPP
|
#define BEAST_HTTP_EMPTY_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -19,6 +18,8 @@ namespace beast {
|
|||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** An empty content-body.
|
/** An empty content-body.
|
||||||
|
|
||||||
|
Meets the requirements of @b `Body`.
|
||||||
*/
|
*/
|
||||||
struct empty_body
|
struct empty_body
|
||||||
{
|
{
|
||||||
@@ -35,9 +36,9 @@ private:
|
|||||||
|
|
||||||
struct reader
|
struct reader
|
||||||
{
|
{
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, empty_body, Allocator>&)
|
reader(message<isRequest, empty_body, Headers>&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,9 +50,12 @@ private:
|
|||||||
|
|
||||||
struct writer
|
struct writer
|
||||||
{
|
{
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, empty_body, Allocator> const& m)
|
writer(message<isRequest, empty_body, Headers> const& m)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +64,7 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::uint64_t
|
||||||
content_length() const
|
content_length() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define BEAST_HTTP_ERROR_HPP
|
#define BEAST_HTTP_ERROR_HPP
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <boost/system/system_error.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|||||||
@@ -14,10 +14,7 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
template<class Allocator>
|
using headers =
|
||||||
using headers = basic_headers<Allocator>;
|
|
||||||
|
|
||||||
using http_headers =
|
|
||||||
basic_headers<std::allocator<char>>;
|
basic_headers<std::allocator<char>>;
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||||
|
|
||||||
#include <beast/type_check.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
@@ -59,7 +57,7 @@ delete_all()
|
|||||||
for(auto it = list_.begin(); it != list_.end();)
|
for(auto it = list_.begin(); it != list_.end();)
|
||||||
{
|
{
|
||||||
auto& e = *it++;
|
auto& e = *it++;
|
||||||
e.~element();
|
alloc_traits::destroy(this->member(), &e);
|
||||||
alloc_traits::deallocate(
|
alloc_traits::deallocate(
|
||||||
this->member(), &e, 1);
|
this->member(), &e, 1);
|
||||||
}
|
}
|
||||||
@@ -252,6 +250,7 @@ erase(boost::string_ref const& name)
|
|||||||
auto& e = *it;
|
auto& e = *it;
|
||||||
set_.erase(set_.iterator_to(e));
|
set_.erase(set_.iterator_to(e));
|
||||||
list_.erase(list_.iterator_to(e));
|
list_.erase(list_.iterator_to(e));
|
||||||
|
alloc_traits::destroy(this->member(), &e);
|
||||||
alloc_traits::deallocate(this->member(), &e, 1);
|
alloc_traits::deallocate(this->member(), &e, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,17 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
keep_alive() const
|
keep_alive() const
|
||||||
{
|
{
|
||||||
if(http_major_ > 0 && http_minor_ > 0)
|
if(http_major_ > 0 && http_minor_ > 0)
|
||||||
@@ -31,10 +33,31 @@ keep_alive() const
|
|||||||
|
|
||||||
// Implementation inspired by nodejs/http-parser
|
// Implementation inspired by nodejs/http-parser
|
||||||
|
|
||||||
|
template<bool isRequest, class Derived>
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
typename std::enable_if<
|
||||||
|
! std::is_convertible<ConstBufferSequence,
|
||||||
|
boost::asio::const_buffer>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
basic_parser_v1<isRequest, Derived>::
|
||||||
|
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
|
{
|
||||||
|
static_assert(is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
|
std::size_t used = 0;
|
||||||
|
for(auto const& buffer : buffers)
|
||||||
|
{
|
||||||
|
used += write(buffer, ec);
|
||||||
|
if(ec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
std::size_t
|
std::size_t
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
write(void const* data, std::size_t size, error_code& ec)
|
write(boost::asio::const_buffer const& buffer, error_code& ec)
|
||||||
{
|
{
|
||||||
using beast::http::detail::is_digit;
|
using beast::http::detail::is_digit;
|
||||||
using beast::http::detail::is_token;
|
using beast::http::detail::is_token;
|
||||||
@@ -42,7 +65,12 @@ write(void const* data, std::size_t size, error_code& ec)
|
|||||||
using beast::http::detail::to_field_char;
|
using beast::http::detail::to_field_char;
|
||||||
using beast::http::detail::to_value_char;
|
using beast::http::detail::to_value_char;
|
||||||
using beast::http::detail::unhex;
|
using beast::http::detail::unhex;
|
||||||
|
using boost::asio::buffer_cast;
|
||||||
|
using boost::asio::buffer_size;
|
||||||
|
|
||||||
|
auto const data = buffer_cast<void const*>(buffer);
|
||||||
|
auto const size = buffer_size(buffer);
|
||||||
|
|
||||||
if(size == 0 && s_ != s_closed)
|
if(size == 0 && s_ != s_closed)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -997,30 +1025,9 @@ write(void const* data, std::size_t size, error_code& ec)
|
|||||||
return used();
|
return used();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
basic_parser<isRequest, Derived>::
|
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(is_ConstBufferSequence<ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
std::size_t used = 0;
|
|
||||||
for(auto const& buffer : buffers)
|
|
||||||
{
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
used += write(buffer_cast<void const*>(buffer),
|
|
||||||
buffer_size(buffer), ec);
|
|
||||||
if(ec)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
void
|
void
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
write_eof(error_code& ec)
|
write_eof(error_code& ec)
|
||||||
{
|
{
|
||||||
switch(s_)
|
switch(s_)
|
||||||
@@ -1040,7 +1047,7 @@ write_eof(error_code& ec)
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
needs_eof(std::true_type) const
|
needs_eof(std::true_type) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -1048,7 +1055,7 @@ needs_eof(std::true_type) const
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
needs_eof(std::false_type) const
|
needs_eof(std::false_type) const
|
||||||
{
|
{
|
||||||
// See RFC 2616 section 4.4
|
// See RFC 2616 section 4.4
|
||||||
@@ -1,318 +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_IMPL_MESSAGE_IPP
|
|
||||||
#define BEAST_HTTP_IMPL_MESSAGE_IPP
|
|
||||||
|
|
||||||
#include <beast/http/chunk_encode.hpp>
|
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <beast/http/rfc2616.hpp>
|
|
||||||
#include <beast/write_streambuf.hpp>
|
|
||||||
#include <beast/type_check.hpp>
|
|
||||||
#include <beast/http/detail/write_preparation.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/logic/tribool.hpp>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
message()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
message(request_params params)
|
|
||||||
{
|
|
||||||
static_assert(isRequest, "message is not a request");
|
|
||||||
this->method = params.method;
|
|
||||||
this->url = std::move(params.url);
|
|
||||||
version = params.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
message(response_params params)
|
|
||||||
{
|
|
||||||
static_assert(! isRequest, "message is not a response");
|
|
||||||
this->status = params.status;
|
|
||||||
this->reason = std::move(params.reason);
|
|
||||||
version = params.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::true_type) const
|
|
||||||
{
|
|
||||||
write(streambuf, to_string(this->method));
|
|
||||||
write(streambuf, " ");
|
|
||||||
write(streambuf, this->url);
|
|
||||||
switch(version)
|
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, " HTTP/1.0\r\n");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, " HTTP/1.1\r\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
|
||||||
write(streambuf, version / 10);
|
|
||||||
write(streambuf, ".");
|
|
||||||
write(streambuf, version % 10);
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::false_type) const
|
|
||||||
{
|
|
||||||
switch(version)
|
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, "HTTP/1.0 ");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, "HTTP/1.1 ");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
|
||||||
write(streambuf, version / 10);
|
|
||||||
write(streambuf, ".");
|
|
||||||
write(streambuf, version % 10);
|
|
||||||
write(streambuf, " ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
write(streambuf, this->status);
|
|
||||||
write(streambuf, " ");
|
|
||||||
write(streambuf, this->reason);
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
std::string
|
|
||||||
buffers_to_string(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
using boost::asio::buffer_cast;
|
|
||||||
using boost::asio::buffer_size;
|
|
||||||
std::string s;
|
|
||||||
s.reserve(buffer_size(buffers));
|
|
||||||
for(auto const& b : buffers)
|
|
||||||
s.append(buffer_cast<char const*>(b),
|
|
||||||
buffer_size(b));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
class writef_ostream
|
|
||||||
{
|
|
||||||
std::ostream& os_;
|
|
||||||
bool chunked_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
writef_ostream(std::ostream& os, bool chunked)
|
|
||||||
: os_(os)
|
|
||||||
, chunked_(chunked)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
void
|
|
||||||
operator()(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
if(chunked_)
|
|
||||||
os_ << buffers_to_string(
|
|
||||||
chunk_encode(buffers));
|
|
||||||
else
|
|
||||||
os_ << buffers_to_string(
|
|
||||||
buffers);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
// Diagnostic output only
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
std::ostream&
|
|
||||||
operator<<(std::ostream& os,
|
|
||||||
message<isRequest, Body, Headers> const& msg)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
|
||||||
wp.init(ec);
|
|
||||||
if(ec)
|
|
||||||
return os;
|
|
||||||
std::mutex m;
|
|
||||||
std::condition_variable cv;
|
|
||||||
bool ready = false;
|
|
||||||
resume_context resume{
|
|
||||||
[&]
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m);
|
|
||||||
ready = true;
|
|
||||||
cv.notify_one();
|
|
||||||
}};
|
|
||||||
auto copy = resume;
|
|
||||||
os << detail::buffers_to_string(wp.sb.data());
|
|
||||||
wp.sb.consume(wp.sb.size());
|
|
||||||
detail::writef_ostream writef(os, wp.chunked);
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
auto result = wp.w(std::move(copy), ec, writef);
|
|
||||||
if(ec)
|
|
||||||
return os;
|
|
||||||
if(result)
|
|
||||||
break;
|
|
||||||
if(boost::indeterminate(result))
|
|
||||||
{
|
|
||||||
copy = resume;
|
|
||||||
std::unique_lock<std::mutex> lock(m);
|
|
||||||
cv.wait(lock, [&]{ return ready; });
|
|
||||||
ready = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wp.sb.consume(wp.sb.size());
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
auto result = wp.w(std::move(copy), ec, writef);
|
|
||||||
if(ec)
|
|
||||||
return os;
|
|
||||||
if(result)
|
|
||||||
break;
|
|
||||||
if(boost::indeterminate(result))
|
|
||||||
{
|
|
||||||
copy = resume;
|
|
||||||
std::unique_lock<std::mutex> lock(m);
|
|
||||||
cv.wait(lock, [&]{ return ready; });
|
|
||||||
ready = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(wp.chunked)
|
|
||||||
{
|
|
||||||
// VFALCO Unfortunately the current interface to the
|
|
||||||
// Writer concept prevents us from using coalescing the
|
|
||||||
// final body chunk with the final chunk delimiter.
|
|
||||||
//
|
|
||||||
// write final chunk
|
|
||||||
os << detail::buffers_to_string(chunk_encode_final());
|
|
||||||
if(ec)
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
os << std::endl;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
set_connection(bool keep_alive,
|
|
||||||
message<isRequest, Body, Headers>& req)
|
|
||||||
{
|
|
||||||
if(req.version >= 11)
|
|
||||||
{
|
|
||||||
if(! keep_alive)
|
|
||||||
req.headers.replace("Connection", "close");
|
|
||||||
else
|
|
||||||
req.headers.erase("Connection");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(keep_alive)
|
|
||||||
req.headers.replace("Connection", "keep-alive");
|
|
||||||
else
|
|
||||||
req.headers.erase("Connection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Body, class Headers,
|
|
||||||
class OtherBody, class OtherAllocator>
|
|
||||||
void
|
|
||||||
set_connection(bool keep_alive,
|
|
||||||
message<false, Body, Headers>& resp,
|
|
||||||
message<true, OtherBody, OtherAllocator> const& req)
|
|
||||||
{
|
|
||||||
if(req.version >= 11)
|
|
||||||
{
|
|
||||||
if(rfc2616::token_in_list(req["Connection"], "close"))
|
|
||||||
keep_alive = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(! rfc2616::token_in_list(req["Connection"], "keep-alive"))
|
|
||||||
keep_alive = false;
|
|
||||||
}
|
|
||||||
set_connection(keep_alive, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Streambuf, class FieldSequence>
|
|
||||||
void
|
|
||||||
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
|
||||||
{
|
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
|
||||||
"Streambuf requirements not met");
|
|
||||||
//static_assert(is_FieldSequence<FieldSequence>::value,
|
|
||||||
// "FieldSequence requirements not met");
|
|
||||||
for(auto const& field : fields)
|
|
||||||
{
|
|
||||||
write(streambuf, field.name());
|
|
||||||
write(streambuf, ": ");
|
|
||||||
write(streambuf, field.value());
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
|
||||||
{
|
|
||||||
if(msg.version >= 11)
|
|
||||||
{
|
|
||||||
if(rfc2616::token_in_list(
|
|
||||||
msg.headers["Connection"], "close"))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(rfc2616::token_in_list(
|
|
||||||
msg.headers["Connection"], "keep-alive"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_upgrade(message<isRequest, Body, Headers> const& msg)
|
|
||||||
{
|
|
||||||
if(msg.version < 11)
|
|
||||||
return false;
|
|
||||||
if(rfc2616::token_in_list(
|
|
||||||
msg.headers["Connection"], "upgrade"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#include <beast/http/impl/message.ipp>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
242
src/beast/include/beast/http/impl/message_v1.ipp
Normal file
242
src/beast/include/beast/http/impl/message_v1.ipp
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
//
|
||||||
|
// 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_IMPL_MESSAGE_V1_IPP
|
||||||
|
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||||
|
|
||||||
|
#include <beast/http/rfc2616.hpp>
|
||||||
|
#include <beast/http/detail/has_content_length.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
message_v1<isRequest, Body, Headers>::
|
||||||
|
message_v1(request_params params)
|
||||||
|
{
|
||||||
|
static_assert(isRequest, "message is not a request");
|
||||||
|
this->method = params.method;
|
||||||
|
this->url = std::move(params.url);
|
||||||
|
version = params.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
message_v1<isRequest, Body, Headers>::
|
||||||
|
message_v1(response_params params)
|
||||||
|
{
|
||||||
|
static_assert(! isRequest, "message is not a response");
|
||||||
|
this->status = params.status;
|
||||||
|
this->reason = std::move(params.reason);
|
||||||
|
version = params.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
if(msg.version >= 11)
|
||||||
|
{
|
||||||
|
if(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "close"))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "keep-alive"))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_upgrade(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
if(msg.version < 11)
|
||||||
|
return false;
|
||||||
|
if(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "upgrade"))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct prepare_info
|
||||||
|
{
|
||||||
|
boost::optional<connection> connection_value;
|
||||||
|
boost::optional<std::uint64_t> content_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
prepare_options(prepare_info& pi,
|
||||||
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
prepare_option(prepare_info& pi,
|
||||||
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
|
connection value)
|
||||||
|
{
|
||||||
|
pi.connection_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Headers,
|
||||||
|
class Opt, class... Opts>
|
||||||
|
void
|
||||||
|
prepare_options(prepare_info& pi,
|
||||||
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
|
Opt&& opt, Opts&&... opts)
|
||||||
|
{
|
||||||
|
prepare_option(pi, msg, opt);
|
||||||
|
prepare_options(pi, msg,
|
||||||
|
std::forward<Opts>(opts)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
prepare_content_length(prepare_info& pi,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
typename Body::writer w(msg);
|
||||||
|
//w.init(ec); // VFALCO This is a design problem!
|
||||||
|
pi.content_length = w.content_length();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
prepare_content_length(prepare_info& pi,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
|
std::false_type)
|
||||||
|
{
|
||||||
|
pi.content_length = boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
prepare_connection(
|
||||||
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
|
{
|
||||||
|
if(msg.version >= 11)
|
||||||
|
{
|
||||||
|
if(! msg.headers.exists("Content-Length") &&
|
||||||
|
! rfc2616::token_in_list(
|
||||||
|
msg.headers["Transfer-Encoding"], "chunked"))
|
||||||
|
if(! rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "close"))
|
||||||
|
msg.headers.insert("Connection", "close");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(! msg.headers.exists("Content-Length"))
|
||||||
|
{
|
||||||
|
// VFALCO We are erasing the whole header when we
|
||||||
|
// should be removing just the keep-alive.
|
||||||
|
if(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "keep-alive"))
|
||||||
|
msg.headers.erase("Connection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Headers,
|
||||||
|
class... Options>
|
||||||
|
void
|
||||||
|
prepare(message_v1<isRequest, Body, Headers>& msg,
|
||||||
|
Options&&... options)
|
||||||
|
{
|
||||||
|
// VFALCO TODO
|
||||||
|
//static_assert(is_WritableBody<Body>::value,
|
||||||
|
// "WritableBody requirements not met");
|
||||||
|
detail::prepare_info pi;
|
||||||
|
detail::prepare_content_length(pi, msg,
|
||||||
|
detail::has_content_length<typename Body::writer>{});
|
||||||
|
detail::prepare_options(pi, msg,
|
||||||
|
std::forward<Options>(options)...);
|
||||||
|
|
||||||
|
if(msg.headers.exists("Connection"))
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"prepare called with Connection field set");
|
||||||
|
|
||||||
|
if(msg.headers.exists("Content-Length"))
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"prepare called with Content-Length field set");
|
||||||
|
|
||||||
|
if(rfc2616::token_in_list(
|
||||||
|
msg.headers["Transfer-Encoding"], "chunked"))
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"prepare called with Transfer-Encoding: chunked set");
|
||||||
|
|
||||||
|
if(pi.connection_value != connection::upgrade)
|
||||||
|
{
|
||||||
|
if(pi.content_length)
|
||||||
|
{
|
||||||
|
// VFALCO TODO Use a static string here
|
||||||
|
msg.headers.insert("Content-Length",
|
||||||
|
std::to_string(*pi.content_length));
|
||||||
|
}
|
||||||
|
else if(msg.version >= 11)
|
||||||
|
{
|
||||||
|
msg.headers.insert("Transfer-Encoding", "chunked");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const content_length =
|
||||||
|
msg.headers.exists("Content-Length");
|
||||||
|
|
||||||
|
if(pi.connection_value)
|
||||||
|
{
|
||||||
|
switch(*pi.connection_value)
|
||||||
|
{
|
||||||
|
case connection::upgrade:
|
||||||
|
msg.headers.insert("Connection", "upgrade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case connection::keep_alive:
|
||||||
|
if(msg.version < 11)
|
||||||
|
{
|
||||||
|
if(content_length)
|
||||||
|
msg.headers.insert("Connection", "keep-alive");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case connection::close:
|
||||||
|
if(msg.version >= 11)
|
||||||
|
msg.headers.insert("Connection", "close");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rfc7230 6.7.
|
||||||
|
if(msg.version < 11 && rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "upgrade"))
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"invalid version for Connection: upgrade");
|
||||||
|
|
||||||
|
// rfc7230 3.3.2
|
||||||
|
if(msg.headers.exists("Content-Length") &&
|
||||||
|
msg.headers.exists("Transfer-Encoding"))
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"Content-Length and Transfer-Encoding cannot be combined");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,8 +8,10 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||||
|
|
||||||
|
#include <beast/http/parser_v1.hpp>
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/bind_handler.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
|
#include <beast/stream_concepts.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -26,10 +28,10 @@ class read_op
|
|||||||
handler_alloc<char, Handler>;
|
handler_alloc<char, Handler>;
|
||||||
|
|
||||||
using parser_type =
|
using parser_type =
|
||||||
parser<isRequest, Body, Headers>;
|
parser_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
using message_type =
|
using message_type =
|
||||||
message<isRequest, Body, Headers>;
|
message_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
@@ -214,14 +216,14 @@ template<class SyncReadStream, class Streambuf,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_Streambuf<Streambuf>::value,
|
||||||
"Streambuf requirements not met");
|
"Streambuf requirements not met");
|
||||||
parser<isRequest, Body, Headers> p;
|
parser_v1<isRequest, Body, Headers> p;
|
||||||
bool started = false;
|
bool started = false;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@@ -264,7 +266,7 @@ template<class AsyncReadStream, class Streambuf,
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||||
|
|||||||
@@ -8,18 +8,22 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
|
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
|
||||||
#define BEAST_HTTP_IMPL_WRITE_IPP
|
#define BEAST_HTTP_IMPL_WRITE_IPP
|
||||||
|
|
||||||
#include <beast/http/chunk_encode.hpp>
|
|
||||||
#include <beast/http/resume_context.hpp>
|
#include <beast/http/resume_context.hpp>
|
||||||
#include <beast/http/detail/write_preparation.hpp>
|
#include <beast/http/detail/chunk_encode.hpp>
|
||||||
|
#include <beast/http/detail/has_content_length.hpp>
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/bind_handler.hpp>
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
|
#include <beast/stream_concepts.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/write_streambuf.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -27,6 +31,114 @@ namespace http {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
template<class Streambuf, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write_firstline(Streambuf& streambuf,
|
||||||
|
message_v1<true, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
write(streambuf, msg.method);
|
||||||
|
write(streambuf, " ");
|
||||||
|
write(streambuf, msg.url);
|
||||||
|
switch(msg.version)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
write(streambuf, " HTTP/1.0\r\n");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
write(streambuf, " HTTP/1.1\r\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
write(streambuf, " HTTP/");
|
||||||
|
write(streambuf, msg.version / 10);
|
||||||
|
write(streambuf, ".");
|
||||||
|
write(streambuf, msg.version % 10);
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Streambuf, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write_firstline(Streambuf& streambuf,
|
||||||
|
message_v1<false, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
switch(msg.version)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
write(streambuf, "HTTP/1.0 ");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
write(streambuf, "HTTP/1.1 ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
write(streambuf, " HTTP/");
|
||||||
|
write(streambuf, msg.version / 10);
|
||||||
|
write(streambuf, ".");
|
||||||
|
write(streambuf, msg.version % 10);
|
||||||
|
write(streambuf, " ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write(streambuf, msg.status);
|
||||||
|
write(streambuf, " ");
|
||||||
|
write(streambuf, msg.reason);
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Streambuf, class FieldSequence>
|
||||||
|
void
|
||||||
|
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
||||||
|
{
|
||||||
|
static_assert(is_Streambuf<Streambuf>::value,
|
||||||
|
"Streambuf requirements not met");
|
||||||
|
//static_assert(is_FieldSequence<FieldSequence>::value,
|
||||||
|
// "FieldSequence requirements not met");
|
||||||
|
for(auto const& field : fields)
|
||||||
|
{
|
||||||
|
write(streambuf, field.name());
|
||||||
|
write(streambuf, ": ");
|
||||||
|
write(streambuf, field.value());
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
struct write_preparation
|
||||||
|
{
|
||||||
|
using headers_type =
|
||||||
|
basic_headers<std::allocator<char>>;
|
||||||
|
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg;
|
||||||
|
typename Body::writer w;
|
||||||
|
streambuf sb;
|
||||||
|
bool chunked;
|
||||||
|
bool close;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
write_preparation(
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg_)
|
||||||
|
: msg(msg_)
|
||||||
|
, w(msg)
|
||||||
|
, chunked(rfc2616::token_in_list(
|
||||||
|
msg.headers["Transfer-Encoding"], "chunked"))
|
||||||
|
, close(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "close") ||
|
||||||
|
(msg.version < 11 && ! msg.headers.exists(
|
||||||
|
"Content-Length")))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
w.init(ec);
|
||||||
|
if(ec)
|
||||||
|
return;
|
||||||
|
write_firstline(sb, msg);
|
||||||
|
write_fields(sb, msg.headers);
|
||||||
|
beast::write(sb, "\r\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class Stream, class Handler,
|
template<class Stream, class Handler,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
class write_op
|
class write_op
|
||||||
@@ -48,7 +160,7 @@ class write_op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, Stream& s_,
|
data(DeducedHandler&& h_, Stream& s_,
|
||||||
message<isRequest, Body, Headers> const& m_)
|
message_v1<isRequest, Body, Headers> const& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, wp(m_)
|
, wp(m_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
@@ -77,7 +189,7 @@ class write_op
|
|||||||
if(d.wp.chunked)
|
if(d.wp.chunked)
|
||||||
boost::asio::async_write(d.s,
|
boost::asio::async_write(d.s,
|
||||||
buffer_cat(d.wp.sb.data(),
|
buffer_cat(d.wp.sb.data(),
|
||||||
chunk_encode(buffers)),
|
detail::chunk_encode(buffers)),
|
||||||
std::move(self_));
|
std::move(self_));
|
||||||
else
|
else
|
||||||
boost::asio::async_write(d.s,
|
boost::asio::async_write(d.s,
|
||||||
@@ -104,7 +216,7 @@ class write_op
|
|||||||
// write body
|
// write body
|
||||||
if(d.wp.chunked)
|
if(d.wp.chunked)
|
||||||
boost::asio::async_write(d.s,
|
boost::asio::async_write(d.s,
|
||||||
chunk_encode(buffers),
|
detail::chunk_encode(buffers),
|
||||||
std::move(self_));
|
std::move(self_));
|
||||||
else
|
else
|
||||||
boost::asio::async_write(d.s,
|
boost::asio::async_write(d.s,
|
||||||
@@ -269,7 +381,7 @@ operator()(error_code ec, std::size_t, bool again)
|
|||||||
// write final chunk
|
// write final chunk
|
||||||
d.state = 5;
|
d.state = 5;
|
||||||
boost::asio::async_write(d.s,
|
boost::asio::async_write(d.s,
|
||||||
chunk_encode_final(), std::move(*this));
|
detail::chunk_encode_final(), std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
@@ -311,7 +423,7 @@ public:
|
|||||||
// write headers and body
|
// write headers and body
|
||||||
if(chunked_)
|
if(chunked_)
|
||||||
boost::asio::write(stream_, buffer_cat(
|
boost::asio::write(stream_, buffer_cat(
|
||||||
sb_.data(), chunk_encode(buffers)), ec_);
|
sb_.data(), detail::chunk_encode(buffers)), ec_);
|
||||||
else
|
else
|
||||||
boost::asio::write(stream_, buffer_cat(
|
boost::asio::write(stream_, buffer_cat(
|
||||||
sb_.data(), buffers), ec_);
|
sb_.data(), buffers), ec_);
|
||||||
@@ -340,7 +452,7 @@ public:
|
|||||||
// write body
|
// write body
|
||||||
if(chunked_)
|
if(chunked_)
|
||||||
boost::asio::write(stream_,
|
boost::asio::write(stream_,
|
||||||
chunk_encode(buffers), ec_);
|
detail::chunk_encode(buffers), ec_);
|
||||||
else
|
else
|
||||||
boost::asio::write(stream_, buffers, ec_);
|
boost::asio::write(stream_, buffers, ec_);
|
||||||
}
|
}
|
||||||
@@ -354,9 +466,25 @@ template<class SyncWriteStream,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
write(stream, msg, ec);
|
||||||
|
if(ec)
|
||||||
|
throw boost::system::system_error{ec};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write(SyncWriteStream& stream,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
boost::system::error_code& ec)
|
boost::system::error_code& ec)
|
||||||
{
|
{
|
||||||
|
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||||
wp.init(ec);
|
wp.init(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -420,7 +548,7 @@ write(SyncWriteStream& stream,
|
|||||||
// final body chunk with the final chunk delimiter.
|
// final body chunk with the final chunk delimiter.
|
||||||
//
|
//
|
||||||
// write final chunk
|
// write final chunk
|
||||||
boost::asio::write(stream, chunk_encode_final(), ec);
|
boost::asio::write(stream, detail::chunk_encode_final(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -437,7 +565,7 @@ template<class AsyncWriteStream,
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
async_write(AsyncWriteStream& stream,
|
async_write(AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
@@ -450,6 +578,68 @@ async_write(AsyncWriteStream& stream,
|
|||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class ostream_SyncStream
|
||||||
|
{
|
||||||
|
std::ostream& os_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ostream_SyncStream(std::ostream& os)
|
||||||
|
: os_(os)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(ConstBufferSequence const& buffers)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
auto const n = write_some(buffers, ec);
|
||||||
|
if(ec)
|
||||||
|
throw boost::system::system_error{ec};
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(ConstBufferSequence const& buffers,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
std::size_t n = 0;
|
||||||
|
using boost::asio::buffer_cast;
|
||||||
|
using boost::asio::buffer_size;
|
||||||
|
for(auto const& buffer : buffers)
|
||||||
|
{
|
||||||
|
os_.write(buffer_cast<char const*>(buffer),
|
||||||
|
buffer_size(buffer));
|
||||||
|
if(os_.fail())
|
||||||
|
{
|
||||||
|
ec = boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::no_stream_resources);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n += buffer_size(buffer);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
std::ostream&
|
||||||
|
operator<<(std::ostream& os,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
detail::ostream_SyncStream oss(os);
|
||||||
|
error_code ec;
|
||||||
|
write(oss, msg, ec);
|
||||||
|
if(ec && ec != boost::asio::error::eof)
|
||||||
|
throw boost::system::system_error{ec};
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,7 @@
|
|||||||
#define BEAST_HTTP_MESSAGE_HPP
|
#define BEAST_HTTP_MESSAGE_HPP
|
||||||
|
|
||||||
#include <beast/http/basic_headers.hpp>
|
#include <beast/http/basic_headers.hpp>
|
||||||
#include <beast/http/method.hpp>
|
|
||||||
#include <beast/buffers_debug.hpp>
|
|
||||||
#include <beast/type_check.hpp>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -23,7 +19,7 @@ namespace detail {
|
|||||||
|
|
||||||
struct request_fields
|
struct request_fields
|
||||||
{
|
{
|
||||||
http::method_t method;
|
std::string method;
|
||||||
std::string url;
|
std::string url;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,24 +31,6 @@ struct response_fields
|
|||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
struct request_params
|
|
||||||
{
|
|
||||||
http::method_t method;
|
|
||||||
std::string url;
|
|
||||||
int version;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct response_params
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
std::string reason;
|
|
||||||
int version;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** A HTTP message.
|
/** A HTTP message.
|
||||||
|
|
||||||
A message can be a request or response, depending on the `isRequest`
|
A message can be a request or response, depending on the `isRequest`
|
||||||
@@ -73,62 +51,24 @@ struct message
|
|||||||
: std::conditional<isRequest,
|
: std::conditional<isRequest,
|
||||||
detail::request_fields, detail::response_fields>::type
|
detail::request_fields, detail::response_fields>::type
|
||||||
{
|
{
|
||||||
/** The trait type characterizing the body.
|
/** The type controlling the body traits.
|
||||||
|
|
||||||
The body member will be of type body_type::value_type.
|
The body member will be of type `body_type::value_type`.
|
||||||
*/
|
*/
|
||||||
using body_type = Body;
|
using body_type = Body;
|
||||||
|
|
||||||
|
/// The type representing the headers.
|
||||||
using headers_type = Headers;
|
using headers_type = Headers;
|
||||||
|
|
||||||
|
/// Indicates if the message is a request.
|
||||||
using is_request =
|
using is_request =
|
||||||
std::integral_constant<bool, isRequest>;
|
std::integral_constant<bool, isRequest>;
|
||||||
|
|
||||||
int version; // 10 or 11
|
/// The container holding the headers.
|
||||||
headers_type headers;
|
headers_type headers;
|
||||||
|
|
||||||
|
/// A container representing the body.
|
||||||
typename Body::value_type body;
|
typename Body::value_type body;
|
||||||
|
|
||||||
message();
|
|
||||||
message(message&&) = default;
|
|
||||||
message(message const&) = default;
|
|
||||||
message& operator=(message&&) = default;
|
|
||||||
message& operator=(message const&) = default;
|
|
||||||
|
|
||||||
/** Construct a HTTP request.
|
|
||||||
*/
|
|
||||||
explicit
|
|
||||||
message(request_params params);
|
|
||||||
|
|
||||||
/** Construct a HTTP response.
|
|
||||||
*/
|
|
||||||
explicit
|
|
||||||
message(response_params params);
|
|
||||||
|
|
||||||
/// Serialize the request or response line to a Streambuf.
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf) const
|
|
||||||
{
|
|
||||||
write_firstline(streambuf,
|
|
||||||
std::integral_constant<bool, isRequest>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Diagnostics only
|
|
||||||
template<bool, class, class>
|
|
||||||
friend
|
|
||||||
std::ostream&
|
|
||||||
operator<<(std::ostream& os,
|
|
||||||
message const& m);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::true_type) const;
|
|
||||||
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::false_type) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
#if ! GENERATING_DOCS
|
||||||
@@ -145,30 +85,7 @@ using response = message<false, Body, Headers>;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For diagnostic output only
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
std::ostream&
|
|
||||||
operator<<(std::ostream& os,
|
|
||||||
message<isRequest, Body, Headers> const& m);
|
|
||||||
|
|
||||||
/// Write a FieldSequence to a Streambuf.
|
|
||||||
template<class Streambuf, class FieldSequence>
|
|
||||||
void
|
|
||||||
write_fields(Streambuf& streambuf, FieldSequence const& fields);
|
|
||||||
|
|
||||||
/// Returns `true` if a message indicates a keep alive
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_keep_alive(message<isRequest, Body, Headers> const& msg);
|
|
||||||
|
|
||||||
/// Returns `true` if a message indicates a HTTP Upgrade request or response
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_upgrade(message<isRequest, Body, Headers> const& msg);
|
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#include <beast/http/impl/message.ipp>
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
130
src/beast/include/beast/http/message_v1.hpp
Normal file
130
src/beast/include/beast/http/message_v1.hpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
//
|
||||||
|
// 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_MESSAGE_V1_HPP
|
||||||
|
#define BEAST_HTTP_MESSAGE_V1_HPP
|
||||||
|
|
||||||
|
#include <beast/http/message.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
|
||||||
|
struct request_params
|
||||||
|
{
|
||||||
|
std::string method;
|
||||||
|
std::string url;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response_params
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
std::string reason;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** A HTTP/1 message.
|
||||||
|
|
||||||
|
A message can be a request or response, depending on the `isRequest`
|
||||||
|
template argument value. Requests and responses have different types,
|
||||||
|
so functions may be overloaded on them if desired.
|
||||||
|
|
||||||
|
The `Body` template argument type determines the model used
|
||||||
|
to read or write the content body of the message.
|
||||||
|
|
||||||
|
@tparam isRequest `true` if this is a request.
|
||||||
|
|
||||||
|
@tparam Body A type meeting the requirements of Body.
|
||||||
|
|
||||||
|
@tparam Headers A type meeting the requirements of Headers.
|
||||||
|
*/
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
struct message_v1 : message<isRequest, Body, Headers>
|
||||||
|
{
|
||||||
|
/// HTTP/1 version (10 or 11)
|
||||||
|
int version;
|
||||||
|
|
||||||
|
message_v1() = default;
|
||||||
|
|
||||||
|
/// Construct a HTTP/1 request.
|
||||||
|
explicit
|
||||||
|
message_v1(request_params params);
|
||||||
|
|
||||||
|
/// Construct a HTTP/1 response.
|
||||||
|
explicit
|
||||||
|
message_v1(response_params params);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
|
||||||
|
/// A typical HTTP/1 request
|
||||||
|
template<class Body,
|
||||||
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
|
using request_v1 = message_v1<true, Body, Headers>;
|
||||||
|
|
||||||
|
/// A typical HTTP/1 response
|
||||||
|
template<class Body,
|
||||||
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
|
using response_v1 = message_v1<false, Body, Headers>;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Returns `true` if a HTTP/1 message indicates a keep alive
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
|
/// Returns `true` if a HTTP/1 message indicates an Upgrade request or response
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_upgrade(message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
|
/** HTTP/1 connection prepare options.
|
||||||
|
|
||||||
|
@note These values are used with @ref prepare.
|
||||||
|
*/
|
||||||
|
enum class connection
|
||||||
|
{
|
||||||
|
/// Specify Connection: close.
|
||||||
|
close,
|
||||||
|
|
||||||
|
/// Specify Connection: keep-alive where possible.
|
||||||
|
keep_alive,
|
||||||
|
|
||||||
|
/// Specify Connection: upgrade.
|
||||||
|
upgrade
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Prepare a HTTP/1 message.
|
||||||
|
|
||||||
|
This function will adjust the Content-Length, Transfer-Encoding,
|
||||||
|
and Connection headers of the message based on the properties of
|
||||||
|
the body and the options passed in.
|
||||||
|
|
||||||
|
@param msg The message to prepare. The headers may be modified.
|
||||||
|
|
||||||
|
@param options A list of prepare options.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Headers,
|
||||||
|
class... Options>
|
||||||
|
void
|
||||||
|
prepare(message_v1<isRequest, Body, Headers>& msg,
|
||||||
|
Options&&... options);
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#include <beast/http/impl/message_v1.ipp>
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,179 +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_METHOD_HPP
|
|
||||||
#define BEAST_HTTP_METHOD_HPP
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
enum class method_t
|
|
||||||
{
|
|
||||||
http_delete,
|
|
||||||
http_get,
|
|
||||||
http_head,
|
|
||||||
http_post,
|
|
||||||
http_put,
|
|
||||||
|
|
||||||
// pathological
|
|
||||||
http_connect,
|
|
||||||
http_options,
|
|
||||||
http_trace,
|
|
||||||
|
|
||||||
// webdav
|
|
||||||
http_copy,
|
|
||||||
http_lock,
|
|
||||||
http_mkcol,
|
|
||||||
http_move,
|
|
||||||
http_propfind,
|
|
||||||
http_proppatch,
|
|
||||||
http_search,
|
|
||||||
http_unlock,
|
|
||||||
http_bind,
|
|
||||||
http_rebind,
|
|
||||||
http_unbind,
|
|
||||||
http_acl,
|
|
||||||
|
|
||||||
// subversion
|
|
||||||
http_report,
|
|
||||||
http_mkactivity,
|
|
||||||
http_checkout,
|
|
||||||
http_merge,
|
|
||||||
|
|
||||||
// upnp
|
|
||||||
http_msearch,
|
|
||||||
http_notify,
|
|
||||||
http_subscribe,
|
|
||||||
http_unsubscribe,
|
|
||||||
|
|
||||||
// RFC-5789
|
|
||||||
http_patch,
|
|
||||||
http_purge,
|
|
||||||
|
|
||||||
// CalDav
|
|
||||||
http_mkcalendar,
|
|
||||||
|
|
||||||
// RFC-2068, section 19.6.1.2
|
|
||||||
http_link,
|
|
||||||
http_unlink
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class = void>
|
|
||||||
std::string
|
|
||||||
to_string(method_t m)
|
|
||||||
{
|
|
||||||
switch(m)
|
|
||||||
{
|
|
||||||
case method_t::http_delete: return "DELETE";
|
|
||||||
case method_t::http_get: return "GET";
|
|
||||||
case method_t::http_head: return "HEAD";
|
|
||||||
case method_t::http_post: return "POST";
|
|
||||||
case method_t::http_put: return "PUT";
|
|
||||||
|
|
||||||
case method_t::http_connect: return "CONNECT";
|
|
||||||
case method_t::http_options: return "OPTIONS";
|
|
||||||
case method_t::http_trace: return "TRACE";
|
|
||||||
|
|
||||||
case method_t::http_copy: return "COPY";
|
|
||||||
case method_t::http_lock: return "LOCK";
|
|
||||||
case method_t::http_mkcol: return "MKCOL";
|
|
||||||
case method_t::http_move: return "MOVE";
|
|
||||||
case method_t::http_propfind: return "PROPFIND";
|
|
||||||
case method_t::http_proppatch: return "PROPPATCH";
|
|
||||||
case method_t::http_search: return "SEARCH";
|
|
||||||
case method_t::http_unlock: return "UNLOCK";
|
|
||||||
|
|
||||||
case method_t::http_report: return "REPORT";
|
|
||||||
case method_t::http_mkactivity: return "MKACTIVITY";
|
|
||||||
case method_t::http_checkout: return "CHECKOUT";
|
|
||||||
case method_t::http_merge: return "MERGE";
|
|
||||||
|
|
||||||
case method_t::http_msearch: return "MSEARCH";
|
|
||||||
case method_t::http_notify: return "NOTIFY";
|
|
||||||
case method_t::http_subscribe: return "SUBSCRIBE";
|
|
||||||
case method_t::http_unsubscribe: return "UNSUBSCRIBE";
|
|
||||||
|
|
||||||
case method_t::http_patch: return "PATCH";
|
|
||||||
case method_t::http_purge: return "PURGE";
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
return "GET";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Stream>
|
|
||||||
Stream&
|
|
||||||
operator<< (Stream& s, method_t m)
|
|
||||||
{
|
|
||||||
return s << to_string(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the string corresponding to the numeric HTTP status code. */
|
|
||||||
template<class = void>
|
|
||||||
std::string
|
|
||||||
status_text (int status)
|
|
||||||
{
|
|
||||||
switch(status)
|
|
||||||
{
|
|
||||||
case 100: return "Continue";
|
|
||||||
case 101: return "Switching Protocols";
|
|
||||||
case 200: return "OK";
|
|
||||||
case 201: return "Created";
|
|
||||||
case 202: return "Accepted";
|
|
||||||
case 203: return "Non-Authoritative Information";
|
|
||||||
case 204: return "No Content";
|
|
||||||
case 205: return "Reset Content";
|
|
||||||
case 206: return "Partial Content";
|
|
||||||
case 300: return "Multiple Choices";
|
|
||||||
case 301: return "Moved Permanently";
|
|
||||||
case 302: return "Found";
|
|
||||||
case 303: return "See Other";
|
|
||||||
case 304: return "Not Modified";
|
|
||||||
case 305: return "Use Proxy";
|
|
||||||
//case 306: return "<reserved>";
|
|
||||||
case 307: return "Temporary Redirect";
|
|
||||||
case 400: return "Bad Request";
|
|
||||||
case 401: return "Unauthorized";
|
|
||||||
case 402: return "Payment Required";
|
|
||||||
case 403: return "Forbidden";
|
|
||||||
case 404: return "Not Found";
|
|
||||||
case 405: return "Method Not Allowed";
|
|
||||||
case 406: return "Not Acceptable";
|
|
||||||
case 407: return "Proxy Authentication Required";
|
|
||||||
case 408: return "Request Timeout";
|
|
||||||
case 409: return "Conflict";
|
|
||||||
case 410: return "Gone";
|
|
||||||
case 411: return "Length Required";
|
|
||||||
case 412: return "Precondition Failed";
|
|
||||||
case 413: return "Request Entity Too Large";
|
|
||||||
case 414: return "Request-URI Too Long";
|
|
||||||
case 415: return "Unsupported Media Type";
|
|
||||||
case 416: return "Requested Range Not Satisfiable";
|
|
||||||
case 417: return "Expectation Failed";
|
|
||||||
case 500: return "Internal Server Error";
|
|
||||||
case 501: return "Not Implemented";
|
|
||||||
case 502: return "Bad Gateway";
|
|
||||||
case 503: return "Service Unavailable";
|
|
||||||
case 504: return "Gateway Timeout";
|
|
||||||
case 505: return "HTTP Version Not Supported";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "Unknown HTTP status";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,234 +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_PARSER_HPP
|
|
||||||
#define BEAST_HTTP_PARSER_HPP
|
|
||||||
|
|
||||||
#include <beast/http/basic_parser.hpp>
|
|
||||||
#include <beast/http/error.hpp>
|
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
struct parser_request
|
|
||||||
{
|
|
||||||
std::string method_;
|
|
||||||
std::string uri_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct parser_response
|
|
||||||
{
|
|
||||||
std::string reason_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
class parser
|
|
||||||
: public basic_parser<isRequest,
|
|
||||||
parser<isRequest, Body, Headers>>
|
|
||||||
, private std::conditional<isRequest,
|
|
||||||
detail::parser_request, detail::parser_response>::type
|
|
||||||
{
|
|
||||||
using message_type =
|
|
||||||
message<isRequest, Body, Headers>;
|
|
||||||
|
|
||||||
std::string field_;
|
|
||||||
std::string value_;
|
|
||||||
message_type m_;
|
|
||||||
typename message_type::body_type::reader r_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
parser(parser&&) = default;
|
|
||||||
|
|
||||||
parser()
|
|
||||||
: r_(m_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
message_type
|
|
||||||
release()
|
|
||||||
{
|
|
||||||
return std::move(m_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class basic_parser<isRequest, parser>;
|
|
||||||
|
|
||||||
void flush()
|
|
||||||
{
|
|
||||||
if(! value_.empty())
|
|
||||||
{
|
|
||||||
rfc2616::trim_right_in_place(value_);
|
|
||||||
// VFALCO could std::move
|
|
||||||
m_.headers.insert(field_, value_);
|
|
||||||
field_.clear();
|
|
||||||
value_.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_method(boost::string_ref const& s, error_code&)
|
|
||||||
{
|
|
||||||
this->method_.append(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_uri(boost::string_ref const& s, error_code&)
|
|
||||||
{
|
|
||||||
this->uri_.append(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_reason(boost::string_ref const& s, error_code&)
|
|
||||||
{
|
|
||||||
this->reason_.append(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_field(boost::string_ref const& s, error_code&)
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
field_.append(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_value(boost::string_ref const& s, error_code&)
|
|
||||||
{
|
|
||||||
value_.append(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(std::true_type)
|
|
||||||
{
|
|
||||||
// VFALCO This is terrible for setting method
|
|
||||||
auto m =
|
|
||||||
[&](char const* s, method_t m)
|
|
||||||
{
|
|
||||||
if(this->method_ == s)
|
|
||||||
{
|
|
||||||
m_.method = m;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if(m("DELETE", method_t::http_delete))
|
|
||||||
break;
|
|
||||||
if(m("GET", method_t::http_get))
|
|
||||||
break;
|
|
||||||
if(m("HEAD", method_t::http_head))
|
|
||||||
break;
|
|
||||||
if(m("POST", method_t::http_post))
|
|
||||||
break;
|
|
||||||
if(m("PUT", method_t::http_put))
|
|
||||||
break;
|
|
||||||
if(m("CONNECT", method_t::http_connect))
|
|
||||||
break;
|
|
||||||
if(m("OPTIONS", method_t::http_options))
|
|
||||||
break;
|
|
||||||
if(m("TRACE", method_t::http_trace))
|
|
||||||
break;
|
|
||||||
if(m("COPY", method_t::http_copy))
|
|
||||||
break;
|
|
||||||
if(m("LOCK", method_t::http_lock))
|
|
||||||
break;
|
|
||||||
if(m("MKCOL", method_t::http_mkcol))
|
|
||||||
break;
|
|
||||||
if(m("MOVE", method_t::http_move))
|
|
||||||
break;
|
|
||||||
if(m("PROPFIND", method_t::http_propfind))
|
|
||||||
break;
|
|
||||||
if(m("PROPPATCH", method_t::http_proppatch))
|
|
||||||
break;
|
|
||||||
if(m("SEARCH", method_t::http_search))
|
|
||||||
break;
|
|
||||||
if(m("UNLOCK", method_t::http_unlock))
|
|
||||||
break;
|
|
||||||
if(m("BIND", method_t::http_bind))
|
|
||||||
break;
|
|
||||||
if(m("REBID", method_t::http_rebind))
|
|
||||||
break;
|
|
||||||
if(m("UNBIND", method_t::http_unbind))
|
|
||||||
break;
|
|
||||||
if(m("ACL", method_t::http_acl))
|
|
||||||
break;
|
|
||||||
if(m("REPORT", method_t::http_report))
|
|
||||||
break;
|
|
||||||
if(m("MKACTIVITY", method_t::http_mkactivity))
|
|
||||||
break;
|
|
||||||
if(m("CHECKOUT", method_t::http_checkout))
|
|
||||||
break;
|
|
||||||
if(m("MERGE", method_t::http_merge))
|
|
||||||
break;
|
|
||||||
if(m("MSEARCH", method_t::http_msearch))
|
|
||||||
break;
|
|
||||||
if(m("NOTIFY", method_t::http_notify))
|
|
||||||
break;
|
|
||||||
if(m("SUBSCRIBE", method_t::http_subscribe))
|
|
||||||
break;
|
|
||||||
if(m("UNSUBSCRIBE",method_t::http_unsubscribe))
|
|
||||||
break;
|
|
||||||
if(m("PATCH", method_t::http_patch))
|
|
||||||
break;
|
|
||||||
if(m("PURGE", method_t::http_purge))
|
|
||||||
break;
|
|
||||||
if(m("MKCALENDAR", method_t::http_mkcalendar))
|
|
||||||
break;
|
|
||||||
if(m("LINK", method_t::http_link))
|
|
||||||
break;
|
|
||||||
if(m("UNLINK", method_t::http_unlink))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while(false);
|
|
||||||
|
|
||||||
m_.url = std::move(this->uri_);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(std::false_type)
|
|
||||||
{
|
|
||||||
m_.status = this->status_code();
|
|
||||||
m_.reason = this->reason_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int on_headers(error_code&)
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
m_.version = 10 * this->http_major() + this->http_minor();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_request(error_code& ec)
|
|
||||||
{
|
|
||||||
set(std::integral_constant<
|
|
||||||
bool, isRequest>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_response(error_code& ec)
|
|
||||||
{
|
|
||||||
set(std::integral_constant<
|
|
||||||
bool, isRequest>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_body(boost::string_ref const& s, error_code& ec)
|
|
||||||
{
|
|
||||||
r_.write(s.data(), s.size(), ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_complete(error_code&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
157
src/beast/include/beast/http/parser_v1.hpp
Normal file
157
src/beast/include/beast/http/parser_v1.hpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
//
|
||||||
|
// 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_PARSER_V1_HPP
|
||||||
|
#define BEAST_HTTP_PARSER_V1_HPP
|
||||||
|
|
||||||
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
|
#include <beast/http/error.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct parser_request
|
||||||
|
{
|
||||||
|
std::string method_;
|
||||||
|
std::string uri_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct parser_response
|
||||||
|
{
|
||||||
|
std::string reason_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
/** A parser for producing HTTP/1 messages.
|
||||||
|
|
||||||
|
This class uses the basic HTTP/1 wire format parser to convert
|
||||||
|
a series of octets into a `message_v1`.
|
||||||
|
*/
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
class parser_v1
|
||||||
|
: public basic_parser_v1<isRequest,
|
||||||
|
parser_v1<isRequest, Body, Headers>>
|
||||||
|
, private std::conditional<isRequest,
|
||||||
|
detail::parser_request, detail::parser_response>::type
|
||||||
|
{
|
||||||
|
using message_type =
|
||||||
|
message_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
|
std::string field_;
|
||||||
|
std::string value_;
|
||||||
|
message_type m_;
|
||||||
|
typename message_type::body_type::reader r_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
parser_v1(parser_v1&&) = default;
|
||||||
|
|
||||||
|
parser_v1()
|
||||||
|
: r_(m_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
message_type
|
||||||
|
release()
|
||||||
|
{
|
||||||
|
return std::move(m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class basic_parser_v1<isRequest, parser_v1>;
|
||||||
|
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
if(! value_.empty())
|
||||||
|
{
|
||||||
|
rfc2616::trim_right_in_place(value_);
|
||||||
|
// VFALCO could std::move
|
||||||
|
m_.headers.insert(field_, value_);
|
||||||
|
field_.clear();
|
||||||
|
value_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_method(boost::string_ref const& s, error_code&)
|
||||||
|
{
|
||||||
|
this->method_.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_uri(boost::string_ref const& s, error_code&)
|
||||||
|
{
|
||||||
|
this->uri_.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_reason(boost::string_ref const& s, error_code&)
|
||||||
|
{
|
||||||
|
this->reason_.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_field(boost::string_ref const& s, error_code&)
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
field_.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_value(boost::string_ref const& s, error_code&)
|
||||||
|
{
|
||||||
|
value_.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(std::true_type)
|
||||||
|
{
|
||||||
|
m_.method = std::move(this->method_);
|
||||||
|
m_.url = std::move(this->uri_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(std::false_type)
|
||||||
|
{
|
||||||
|
m_.status = this->status_code();
|
||||||
|
m_.reason = std::move(this->reason_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int on_headers(error_code&)
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
m_.version = 10 * this->http_major() + this->http_minor();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_request(error_code& ec)
|
||||||
|
{
|
||||||
|
set(std::integral_constant<
|
||||||
|
bool, isRequest>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_response(error_code& ec)
|
||||||
|
{
|
||||||
|
set(std::integral_constant<
|
||||||
|
bool, isRequest>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_body(boost::string_ref const& s, error_code& ec)
|
||||||
|
{
|
||||||
|
r_.write(s.data(), s.size(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_complete(error_code&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,34 +8,46 @@
|
|||||||
#ifndef BEAST_HTTP_READ_HPP
|
#ifndef BEAST_HTTP_READ_HPP
|
||||||
#define BEAST_HTTP_READ_HPP
|
#define BEAST_HTTP_READ_HPP
|
||||||
|
|
||||||
#include <beast/async_completion.hpp>
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
#include <beast/async_completion.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** Read a HTTP message from a stream.
|
/** Read a HTTP/1 message from a stream.
|
||||||
|
|
||||||
@param stream The stream to read the message from.
|
This function is used to synchronously read a message from
|
||||||
|
the stream. The call blocks until one of the following conditions
|
||||||
|
is true:
|
||||||
|
|
||||||
@param streambuf A Streambuf used to hold unread bytes. The
|
@li A complete message is read in.
|
||||||
implementation may read past the end of the message. The extra
|
|
||||||
bytes are stored here, to be presented in a subsequent call to
|
|
||||||
read.
|
|
||||||
|
|
||||||
@param msg An object used to store the read message. Any
|
@li An error occurs on the stream.
|
||||||
|
|
||||||
|
This function is implemented in terms of one or more calls to the
|
||||||
|
stream's `read_some` function.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
|
@param streambuf An object meeting the @b `Streambuf` type requirements
|
||||||
|
used to hold unread bytes. The implementation may read past the end of
|
||||||
|
the message. The extra bytes are stored here, to be presented in a
|
||||||
|
subsequent call to @ref read.
|
||||||
|
|
||||||
|
@param msg An object used to store the message. Any
|
||||||
contents will be overwritten.
|
contents will be overwritten.
|
||||||
|
|
||||||
@throws boost::system::system_error on failure.
|
@throws boost::system::system_error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
template<class SyncReadStream, class Streambuf,
|
template<class SyncReadStream, class Streambuf,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg)
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(stream, streambuf, msg, ec);
|
read(stream, streambuf, msg, ec);
|
||||||
@@ -43,17 +55,29 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
throw boost::system::system_error{ec};
|
throw boost::system::system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read a HTTP message from a stream.
|
/** Read a HTTP/1 message from a stream.
|
||||||
|
|
||||||
@param stream The stream to read the message from.
|
This function is used to synchronously read a message from
|
||||||
|
the stream. The call blocks until one of the following conditions
|
||||||
|
is true:
|
||||||
|
|
||||||
@param streambuf A Streambuf used to hold unread bytes. The
|
@li A complete message is read in.
|
||||||
implementation may read past the end of the message. The extra
|
|
||||||
bytes are stored here, to be presented in a subsequent call to
|
|
||||||
read.
|
|
||||||
|
|
||||||
@param msg An object used to store the read message. Any
|
@li An error occurs on the stream.
|
||||||
contents will be overwritten.
|
|
||||||
|
This function is implemented in terms of one or more calls to the
|
||||||
|
stream's `read_some` function.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
|
@param streambuf An object meeting the @b `Streambuf` type requirements
|
||||||
|
used to hold unread bytes. The implementation may read past the end of
|
||||||
|
the message. The extra bytes are stored here, to be presented in a
|
||||||
|
subsequent call to @ref read.
|
||||||
|
|
||||||
|
@param msg An object used to store the message. Any contents
|
||||||
|
will be overwritten.
|
||||||
|
|
||||||
@param ec Set to the error, if any occurred.
|
@param ec Set to the error, if any occurred.
|
||||||
*/
|
*/
|
||||||
@@ -61,20 +85,34 @@ template<class SyncReadStream, class Streambuf,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start reading a HTTP message from a stream asynchronously.
|
/** Start an asynchronous operation to read a HTTP/1 message from a stream.
|
||||||
|
|
||||||
|
This function is used to asynchronously read a message from the
|
||||||
|
stream. The function call always returns immediately. The asynchronous
|
||||||
|
operation will continue until one of the following conditions is true:
|
||||||
|
|
||||||
|
@li A complete message is read in.
|
||||||
|
|
||||||
|
@li An error occurs on the stream.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls to the
|
||||||
|
next layer's `async_read_some` function, and is known as a
|
||||||
|
<em>composed operation</em>. The program must ensure that the stream
|
||||||
|
performs no other operations until this operation completes.
|
||||||
|
|
||||||
@param stream The stream to read the message from.
|
@param stream The stream to read the message from.
|
||||||
|
The type must support the @b `AsyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A Streambuf used to hold unread bytes. The
|
@param streambuf A Streambuf used to hold unread bytes. The
|
||||||
implementation may read past the end of the message. The extra
|
implementation may read past the end of the message. The extra
|
||||||
bytes are stored here, to be presented in a subsequent call to
|
bytes are stored here, to be presented in a subsequent call to
|
||||||
async_read.
|
@ref async_read.
|
||||||
|
|
||||||
@param msg An object used to store the read message. Any
|
@param msg An object used to store the message. Any contents
|
||||||
contents will be overwritten.
|
will be overwritten.
|
||||||
|
|
||||||
@param handler The handler to be called when the request completes.
|
@param handler The handler to be called when the request completes.
|
||||||
Copies will be made of the handler as required. The equivalent
|
Copies will be made of the handler as required. The equivalent
|
||||||
@@ -85,7 +123,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class AsyncReadStream, class Streambuf,
|
template<class AsyncReadStream, class Streambuf,
|
||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
@@ -97,7 +135,7 @@ typename async_completion<
|
|||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
|
|||||||
71
src/beast/include/beast/http/status.hpp
Normal file
71
src/beast/include/beast/http/status.hpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// 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_STATUS_HPP
|
||||||
|
#define BEAST_HTTP_STATUS_HPP
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
/** Returns the string corresponding to the numeric HTTP status code. */
|
||||||
|
template<class = void>
|
||||||
|
char const*
|
||||||
|
status_text(int status)
|
||||||
|
{
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
case 100: return "Continue";
|
||||||
|
case 101: return "Switching Protocols";
|
||||||
|
case 200: return "OK";
|
||||||
|
case 201: return "Created";
|
||||||
|
case 202: return "Accepted";
|
||||||
|
case 203: return "Non-Authoritative Information";
|
||||||
|
case 204: return "No Content";
|
||||||
|
case 205: return "Reset Content";
|
||||||
|
case 206: return "Partial Content";
|
||||||
|
case 300: return "Multiple Choices";
|
||||||
|
case 301: return "Moved Permanently";
|
||||||
|
case 302: return "Found";
|
||||||
|
case 303: return "See Other";
|
||||||
|
case 304: return "Not Modified";
|
||||||
|
case 305: return "Use Proxy";
|
||||||
|
// case 306: return "<reserved>";
|
||||||
|
case 307: return "Temporary Redirect";
|
||||||
|
case 400: return "Bad Request";
|
||||||
|
case 401: return "Unauthorized";
|
||||||
|
case 402: return "Payment Required";
|
||||||
|
case 403: return "Forbidden";
|
||||||
|
case 404: return "Not Found";
|
||||||
|
case 405: return "Method Not Allowed";
|
||||||
|
case 406: return "Not Acceptable";
|
||||||
|
case 407: return "Proxy Authentication Required";
|
||||||
|
case 408: return "Request Timeout";
|
||||||
|
case 409: return "Conflict";
|
||||||
|
case 410: return "Gone";
|
||||||
|
case 411: return "Length Required";
|
||||||
|
case 412: return "Precondition Failed";
|
||||||
|
case 413: return "Request Entity Too Large";
|
||||||
|
case 414: return "Request-URI Too Long";
|
||||||
|
case 415: return "Unsupported Media Type";
|
||||||
|
case 416: return "Requested Range Not Satisfiable";
|
||||||
|
case 417: return "Expectation Failed";
|
||||||
|
case 500: return "Internal Server Error";
|
||||||
|
case 501: return "Not Implemented";
|
||||||
|
case 502: return "Bad Gateway";
|
||||||
|
case 503: return "Service Unavailable";
|
||||||
|
case 504: return "Gateway Timeout";
|
||||||
|
case 505: return "HTTP Version Not Supported";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "Unknown HTTP status";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -18,7 +17,9 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** A Body represented by a Streambuf
|
/** A message body represented by a Streambuf
|
||||||
|
|
||||||
|
Meets the requirements of @b `Body`.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
template<class Streambuf>
|
||||||
struct basic_streambuf_body
|
struct basic_streambuf_body
|
||||||
@@ -35,10 +36,10 @@ private:
|
|||||||
value_type& sb_;
|
value_type& sb_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(message<isRequest,
|
||||||
basic_streambuf_body, Allocator>& m) noexcept
|
basic_streambuf_body, Headers>& m) noexcept
|
||||||
: sb_(m.body)
|
: sb_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -59,10 +60,13 @@ private:
|
|||||||
Streambuf const& body_;
|
Streambuf const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, basic_streambuf_body,
|
writer(message<
|
||||||
Allocator> const& m)
|
isRequest, basic_streambuf_body, Headers> const& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -72,7 +76,7 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::uint64_t
|
||||||
content_length() const
|
content_length() const
|
||||||
{
|
{
|
||||||
return body_.size();
|
return body_.size();
|
||||||
|
|||||||
@@ -8,9 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
||||||
#define BEAST_HTTP_STRING_BODY_HPP
|
#define BEAST_HTTP_STRING_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -20,6 +18,8 @@ namespace beast {
|
|||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** A Body represented by a std::string.
|
/** A Body represented by a std::string.
|
||||||
|
|
||||||
|
Meets the requirements of @b `Body`.
|
||||||
*/
|
*/
|
||||||
struct string_body
|
struct string_body
|
||||||
{
|
{
|
||||||
@@ -35,10 +35,10 @@ private:
|
|||||||
value_type& s_;
|
value_type& s_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(message<isRequest,
|
||||||
string_body, Allocator>& m) noexcept
|
string_body, Headers>& m) noexcept
|
||||||
: s_(m.body)
|
: s_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -58,9 +58,13 @@ private:
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, string_body, Allocator> const& msg)
|
writer(message<
|
||||||
|
isRequest, string_body, Headers> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -70,7 +74,7 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::uint64_t
|
||||||
content_length() const
|
content_length() const
|
||||||
{
|
{
|
||||||
return body_.size();
|
return body_.size();
|
||||||
|
|||||||
62
src/beast/include/beast/http/type_check.hpp
Normal file
62
src/beast/include/beast/http/type_check.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// 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 <beast/http/error.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of `Parser`.
|
||||||
|
template<class T>
|
||||||
|
class is_Parser
|
||||||
|
{
|
||||||
|
template<class U, class R =
|
||||||
|
std::is_convertible<decltype(
|
||||||
|
std::declval<U>().complete()),
|
||||||
|
bool>>
|
||||||
|
static R check1(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check1(...);
|
||||||
|
using type1 = decltype(check1<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R =
|
||||||
|
std::is_convertible<decltype(
|
||||||
|
std::declval<U>().write(
|
||||||
|
std::declval<boost::asio::const_buffer const&>(),
|
||||||
|
std::declval<error_code&>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check2(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check2(...);
|
||||||
|
using type2 = decltype(check2<T>(0));
|
||||||
|
|
||||||
|
template<class U, class R =
|
||||||
|
std::is_convertible<decltype(
|
||||||
|
std::declval<U>().write_eof(
|
||||||
|
std::declval<error_code&>())),
|
||||||
|
std::size_t>>
|
||||||
|
static R check3(int);
|
||||||
|
template<class>
|
||||||
|
static std::false_type check3(...);
|
||||||
|
using type3 = decltype(check3<T>(0));
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// `true` if `T` meets the requirements.
|
||||||
|
static bool const value =
|
||||||
|
type1::value && type2::value && type3::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,39 +9,68 @@
|
|||||||
#define BEAST_HTTP_WRITE_HPP
|
#define BEAST_HTTP_WRITE_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/async_completion.hpp>
|
#include <beast/async_completion.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <ostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** Write a HTTP message to a stream.
|
/** Write a HTTP/1 message on a stream.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
This function is used to write a message to a stream. The call
|
||||||
|
will block until one of the following conditions is true:
|
||||||
|
|
||||||
@param msg The message to send.
|
@li The entire message is sent.
|
||||||
|
|
||||||
@throws boost::system::error code on failure.
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls
|
||||||
|
to the stream's `write_some` function.
|
||||||
|
|
||||||
|
The implementation will automatically perform chunk encoding if
|
||||||
|
the contents of the message indicate that chunk encoding is required.
|
||||||
|
If the semantics of the message indicate that the connection should
|
||||||
|
be closed after the message is sent, the error returns from this
|
||||||
|
function will be `boost::asio::error::eof`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b `SyncWriteStream` concept.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
|
||||||
|
@throws boost::system::error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
template<class SyncWriteStream,
|
template<class SyncWriteStream,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg)
|
message_v1<isRequest, Body, Headers> const& msg);
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
write(stream, msg, ec);
|
|
||||||
if(ec)
|
|
||||||
throw boost::system::system_error{ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Write a HTTP message to a stream.
|
/** Write a HTTP/1 message on a stream.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
This function is used to write a message to a stream. The call
|
||||||
|
will block until one of the following conditions is true:
|
||||||
|
|
||||||
@param msg The message to send.
|
@li The entire message is sent.
|
||||||
|
|
||||||
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls
|
||||||
|
to the stream's `write_some` function.
|
||||||
|
|
||||||
|
The implementation will automatically perform chunk encoding if
|
||||||
|
the contents of the message indicate that chunk encoding is required.
|
||||||
|
If the semantics of the message indicate that the connection should
|
||||||
|
be closed after the message is sent, the error returns from this
|
||||||
|
function will be `boost::asio::error::eof`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b `SyncWriteStream` concept.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
|
||||||
@param ec Set to the error, if any occurred.
|
@param ec Set to the error, if any occurred.
|
||||||
*/
|
*/
|
||||||
@@ -49,16 +78,38 @@ template<class SyncWriteStream,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start writing a HTTP message to a stream asynchronously.
|
/** Start an asynchronous operation to write a HTTP/1 message to a stream.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
This function is used to asynchronously write a message to a stream.
|
||||||
|
The function call always returns immediately. The asynchronous
|
||||||
|
operation will continue until one of the following conditions is true:
|
||||||
|
|
||||||
|
@li The entire message is sent.
|
||||||
|
|
||||||
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls to the
|
||||||
|
stream's `async_write_some` functions, and is known as a <em>composed
|
||||||
|
operation</em>. The program must ensure that the stream performs no
|
||||||
|
other write operations (such as @ref async_write, the stream's
|
||||||
|
`async_write_some` function, or any other composed operations that
|
||||||
|
perform writes) until this operation completes.
|
||||||
|
|
||||||
|
The implementation will automatically perform chunk encoding if
|
||||||
|
the contents of the message indicate that chunk encoding is required.
|
||||||
|
If the semantics of the message indicate that the connection should
|
||||||
|
be closed after the message is sent, the operation will complete with
|
||||||
|
the error set to `boost::asio::error::eof`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b `AsyncWriteStream` concept.
|
||||||
|
|
||||||
@param msg The message to send.
|
@param msg The message to send.
|
||||||
|
|
||||||
@param token The handler to be called when the request completes.
|
@param handler The handler to be called when the request completes.
|
||||||
Copies will be made of the handler as required. The equivalent
|
Copies will be made of the handler as required. The equivalent
|
||||||
function signature of the handler must be:
|
function signature of the handler must be:
|
||||||
@code void handler(
|
@code void handler(
|
||||||
@@ -67,9 +118,9 @@ write(SyncWriteStream& stream,
|
|||||||
Regardless of whether the asynchronous operation completes
|
Regardless of whether the asynchronous operation completes
|
||||||
immediately or not, the handler will not be invoked from within
|
immediately or not, the handler will not be invoked from within
|
||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
|
|
||||||
@note The message must remain valid at least until the
|
@note The message object must remain valid at least until the
|
||||||
completion handler is called, no copies are made.
|
completion handler is called, no copies are made.
|
||||||
*/
|
*/
|
||||||
template<class AsyncWriteStream,
|
template<class AsyncWriteStream,
|
||||||
@@ -82,9 +133,26 @@ typename async_completion<
|
|||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(AsyncWriteStream& stream,
|
async_write(AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
|
/** Serialize a HTTP/1 message to an ostream.
|
||||||
|
|
||||||
|
The function converts the message to its HTTP/1 serialized
|
||||||
|
representation and stores the result in the output stream.
|
||||||
|
|
||||||
|
The implementation will automatically perform chunk encoding if
|
||||||
|
the contents of the message indicate that chunk encoding is required.
|
||||||
|
|
||||||
|
@param os The ostream to write to.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
*/
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
std::ostream&
|
||||||
|
operator<<(std::ostream& os,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
|
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||||
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
|
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||||
|
|
||||||
|
#include <beast/detail/write_streambuf.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@@ -118,7 +119,7 @@ public:
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class basic_streambuf<Allocator>::const_buffers_type
|
class basic_streambuf<Allocator>::const_buffers_type
|
||||||
{
|
{
|
||||||
basic_streambuf const* sb_ = nullptr;
|
basic_streambuf const* sb_;
|
||||||
|
|
||||||
friend class basic_streambuf;
|
friend class basic_streambuf;
|
||||||
|
|
||||||
@@ -126,12 +127,12 @@ class basic_streambuf<Allocator>::const_buffers_type
|
|||||||
const_buffers_type(basic_streambuf const& sb);
|
const_buffers_type(basic_streambuf const& sb);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Why?
|
// Why?
|
||||||
using value_type = boost::asio::const_buffer;
|
using value_type = boost::asio::const_buffer;
|
||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
const_buffers_type() = default;
|
const_buffers_type() = delete;
|
||||||
const_buffers_type(const_buffers_type const&) = default;
|
const_buffers_type(const_buffers_type const&) = default;
|
||||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ public:
|
|||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
mutable_buffers_type() = default;
|
mutable_buffers_type() = delete;
|
||||||
mutable_buffers_type(mutable_buffers_type const&) = default;
|
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||||
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||||
|
|
||||||
@@ -849,22 +850,6 @@ basic_streambuf<Allocator>::debug_check() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Alloc, class T>
|
|
||||||
basic_streambuf<Alloc>&
|
|
||||||
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();
|
|
||||||
streambuf.commit(buffer_copy(
|
|
||||||
streambuf.prepare(s.size()), buffer(s)));
|
|
||||||
return streambuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_size_helper(basic_streambuf<
|
read_size_helper(basic_streambuf<
|
||||||
@@ -874,17 +859,12 @@ read_size_helper(basic_streambuf<
|
|||||||
std::max<std::size_t>(512, streambuf.prepare_size()));
|
std::max<std::size_t>(512, streambuf.prepare_size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Alloc, class T>
|
||||||
std::string
|
basic_streambuf<Alloc>&
|
||||||
to_string(basic_streambuf<Allocator> const& streambuf)
|
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
detail::write_streambuf(streambuf, t);
|
||||||
using boost::asio::buffer_copy;
|
return streambuf;
|
||||||
std::string s;
|
|
||||||
s.resize(streambuf.size());
|
|
||||||
buffer_copy(
|
|
||||||
buffer(&s[0], s.size()), streambuf.data());
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter<Buffers>::const_buffers_type
|
class buffers_adapter<MutableBufferSequence>::
|
||||||
|
const_buffers_type
|
||||||
{
|
{
|
||||||
buffers_adapter const* ba_;
|
buffers_adapter const* ba_;
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ public:
|
|||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
const_buffers_type() = default;
|
const_buffers_type() = delete;
|
||||||
const_buffers_type(
|
const_buffers_type(
|
||||||
const_buffers_type const&) = default;
|
const_buffers_type const&) = default;
|
||||||
const_buffers_type& operator=(
|
const_buffers_type& operator=(
|
||||||
@@ -48,11 +49,12 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
class buffers_adapter<MutableBufferSequence>::
|
||||||
|
const_buffers_type::const_iterator
|
||||||
{
|
{
|
||||||
iter_type it_;
|
iter_type it_;
|
||||||
buffers_adapter const* ba_;
|
buffers_adapter const* ba_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = boost::asio::const_buffer;
|
using value_type = boost::asio::const_buffer;
|
||||||
@@ -136,19 +138,19 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->begin_};
|
return const_iterator{*ba_, ba_->begin_};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->out_ ==
|
return const_iterator{*ba_, ba_->out_ ==
|
||||||
@@ -157,8 +159,9 @@ buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
class buffers_adapter<MutableBufferSequence>::
|
||||||
|
mutable_buffers_type
|
||||||
{
|
{
|
||||||
buffers_adapter const* ba_;
|
buffers_adapter const* ba_;
|
||||||
|
|
||||||
@@ -167,7 +170,7 @@ public:
|
|||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
mutable_buffers_type() = default;
|
mutable_buffers_type() = delete;
|
||||||
mutable_buffers_type(
|
mutable_buffers_type(
|
||||||
mutable_buffers_type const&) = default;
|
mutable_buffers_type const&) = default;
|
||||||
mutable_buffers_type& operator=(
|
mutable_buffers_type& operator=(
|
||||||
@@ -189,11 +192,12 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
class buffers_adapter<MutableBufferSequence>::
|
||||||
|
mutable_buffers_type::const_iterator
|
||||||
{
|
{
|
||||||
iter_type it_;
|
iter_type it_;
|
||||||
buffers_adapter const* ba_;
|
buffers_adapter const* ba_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = boost::asio::mutable_buffer;
|
using value_type = boost::asio::mutable_buffer;
|
||||||
@@ -277,19 +281,19 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->out_};
|
return const_iterator{*ba_, ba_->out_};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*ba_, ba_->end_};
|
return const_iterator{*ba_, ba_->end_};
|
||||||
@@ -297,8 +301,8 @@ buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
buffers_adapter<Buffers>::buffers_adapter(
|
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||||
buffers_adapter&& other)
|
buffers_adapter&& other)
|
||||||
: buffers_adapter(std::move(other),
|
: buffers_adapter(std::move(other),
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||||
@@ -307,8 +311,8 @@ buffers_adapter<Buffers>::buffers_adapter(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
buffers_adapter<Buffers>::buffers_adapter(
|
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||||
buffers_adapter const& other)
|
buffers_adapter const& other)
|
||||||
: buffers_adapter(other,
|
: buffers_adapter(other,
|
||||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||||
@@ -317,9 +321,9 @@ buffers_adapter<Buffers>::buffers_adapter(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::operator=(
|
buffers_adapter<MutableBufferSequence>::operator=(
|
||||||
buffers_adapter&& other) -> buffers_adapter&
|
buffers_adapter&& other) -> buffers_adapter&
|
||||||
{
|
{
|
||||||
auto const nbegin = std::distance<iter_type>(
|
auto const nbegin = std::distance<iter_type>(
|
||||||
@@ -340,9 +344,9 @@ buffers_adapter<Buffers>::operator=(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::operator=(
|
buffers_adapter<MutableBufferSequence>::operator=(
|
||||||
buffers_adapter const& other) -> buffers_adapter&
|
buffers_adapter const& other) -> buffers_adapter&
|
||||||
{
|
{
|
||||||
auto const nbegin = std::distance<iter_type>(
|
auto const nbegin = std::distance<iter_type>(
|
||||||
@@ -363,9 +367,9 @@ buffers_adapter<Buffers>::operator=(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
buffers_adapter<Buffers>::buffers_adapter(
|
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||||
Buffers const& bs)
|
MutableBufferSequence const& bs)
|
||||||
: bs_(bs)
|
: bs_(bs)
|
||||||
, begin_(bs_.begin())
|
, begin_(bs_.begin())
|
||||||
, out_(bs_.begin())
|
, out_(bs_.begin())
|
||||||
@@ -374,14 +378,12 @@ buffers_adapter<Buffers>::buffers_adapter(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
static_assert(is_mutable,
|
|
||||||
"Operation not valid for ConstBufferSequence");
|
|
||||||
end_ = out_;
|
end_ = out_;
|
||||||
if(end_ != bs_.end())
|
if(end_ != bs_.end())
|
||||||
{
|
{
|
||||||
@@ -416,13 +418,11 @@ buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
|||||||
return mutable_buffers_type{*this};
|
return mutable_buffers_type{*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
void
|
void
|
||||||
buffers_adapter<Buffers>::commit(std::size_t n)
|
buffers_adapter<MutableBufferSequence>::commit(std::size_t n)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
static_assert(is_mutable,
|
|
||||||
"Operation not valid for ConstBufferSequence");
|
|
||||||
if(out_ == end_)
|
if(out_ == end_)
|
||||||
return;
|
return;
|
||||||
auto const last = std::prev(end_);
|
auto const last = std::prev(end_);
|
||||||
@@ -456,18 +456,18 @@ buffers_adapter<Buffers>::commit(std::size_t n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
buffers_adapter<Buffers>::data() const ->
|
buffers_adapter<MutableBufferSequence>::data() const ->
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
{
|
{
|
||||||
return const_buffers_type{*this};
|
return const_buffers_type{*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class MutableBufferSequence>
|
||||||
void
|
void
|
||||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||||
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||||
|
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/buffer_concepts.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -18,16 +18,16 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
class consuming_buffers<BufferSequence, ValueType>::const_iterator
|
||||||
{
|
{
|
||||||
friend class consuming_buffers<Buffers, ValueType>;
|
friend class consuming_buffers<BufferSequence, ValueType>;
|
||||||
|
|
||||||
using iter_type =
|
using iter_type =
|
||||||
typename Buffers::const_iterator;
|
typename BufferSequence::const_iterator;
|
||||||
|
|
||||||
iter_type it_;
|
iter_type it_;
|
||||||
consuming_buffers const* b_;
|
consuming_buffers const* b_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type =
|
using value_type =
|
||||||
@@ -59,9 +59,8 @@ public:
|
|||||||
reference
|
reference
|
||||||
operator*() const
|
operator*() const
|
||||||
{
|
{
|
||||||
if(it_ == b_->begin_)
|
return it_ == b_->begin_ ?
|
||||||
return *it_ + b_->skip_;
|
*it_ + b_->skip_ : *it_;
|
||||||
return *it_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer
|
pointer
|
||||||
@@ -106,8 +105,8 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
consuming_buffers<Buffers, ValueType>::
|
consuming_buffers<BufferSequence, ValueType>::
|
||||||
consuming_buffers(consuming_buffers&& other)
|
consuming_buffers(consuming_buffers&& other)
|
||||||
: consuming_buffers(std::move(other),
|
: consuming_buffers(std::move(other),
|
||||||
std::distance<iter_type>(
|
std::distance<iter_type>(
|
||||||
@@ -115,8 +114,8 @@ consuming_buffers(consuming_buffers&& other)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
consuming_buffers<Buffers, ValueType>::
|
consuming_buffers<BufferSequence, ValueType>::
|
||||||
consuming_buffers(consuming_buffers const& other)
|
consuming_buffers(consuming_buffers const& other)
|
||||||
: consuming_buffers(other,
|
: consuming_buffers(other,
|
||||||
std::distance<iter_type>(
|
std::distance<iter_type>(
|
||||||
@@ -124,9 +123,9 @@ consuming_buffers(consuming_buffers const& other)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
auto
|
auto
|
||||||
consuming_buffers<Buffers, ValueType>::
|
consuming_buffers<BufferSequence, ValueType>::
|
||||||
operator=(consuming_buffers&& other) ->
|
operator=(consuming_buffers&& other) ->
|
||||||
consuming_buffers&
|
consuming_buffers&
|
||||||
{
|
{
|
||||||
@@ -138,9 +137,9 @@ operator=(consuming_buffers&& other) ->
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
auto
|
auto
|
||||||
consuming_buffers<Buffers, ValueType>::
|
consuming_buffers<BufferSequence, ValueType>::
|
||||||
operator=(consuming_buffers const& other) ->
|
operator=(consuming_buffers const& other) ->
|
||||||
consuming_buffers&
|
consuming_buffers&
|
||||||
{
|
{
|
||||||
@@ -152,35 +151,35 @@ operator=(consuming_buffers const& other) ->
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
consuming_buffers<Buffers, ValueType>::
|
consuming_buffers<BufferSequence, ValueType>::
|
||||||
consuming_buffers(Buffers const& bs)
|
consuming_buffers(BufferSequence const& bs)
|
||||||
: bs_(bs)
|
: bs_(bs)
|
||||||
, begin_(bs_.begin())
|
, begin_(bs_.begin())
|
||||||
{
|
{
|
||||||
static_assert(is_BufferSequence<Buffers, ValueType>::value,
|
static_assert(is_BufferSequence<BufferSequence, ValueType>::value,
|
||||||
"BufferSequence requirements not met");
|
"BufferSequence requirements not met");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
auto
|
auto
|
||||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
consuming_buffers<BufferSequence, ValueType>::begin() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*this, begin_};
|
return const_iterator{*this, begin_};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
auto
|
auto
|
||||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
consuming_buffers<BufferSequence, ValueType>::end() const ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*this, bs_.end()};
|
return const_iterator{*this, bs_.end()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers, class ValueType>
|
template<class BufferSequence, class ValueType>
|
||||||
void
|
void
|
||||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
consuming_buffers<BufferSequence, ValueType>::consume(std::size_t n)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||||
@@ -197,11 +196,11 @@ consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Buffers>
|
template<class BufferSequence>
|
||||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
consuming_buffers<BufferSequence, typename BufferSequence::value_type>
|
||||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
consumed_buffers(BufferSequence const& bs, std::size_t n)
|
||||||
{
|
{
|
||||||
consuming_buffers<Buffers> cb(bs);
|
consuming_buffers<BufferSequence> cb(bs);
|
||||||
cb.consume(n);
|
cb.consume(n);
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class prepared_buffers<BufferSequence>::const_iterator
|
|||||||
using iter_type =
|
using iter_type =
|
||||||
typename BufferSequence::const_iterator;
|
typename BufferSequence::const_iterator;
|
||||||
|
|
||||||
prepared_buffers const* b_;
|
prepared_buffers const* b_ = nullptr;
|
||||||
typename BufferSequence::const_iterator it_;
|
typename BufferSequence::const_iterator it_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public:
|
|||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
const_buffers_type() = default;
|
const_buffers_type() = delete;
|
||||||
const_buffers_type(
|
const_buffers_type(
|
||||||
const_buffers_type const&) = default;
|
const_buffers_type const&) = default;
|
||||||
const_buffers_type& operator=(
|
const_buffers_type& operator=(
|
||||||
@@ -51,8 +51,8 @@ private:
|
|||||||
|
|
||||||
class static_streambuf::const_buffers_type::const_iterator
|
class static_streambuf::const_buffers_type::const_iterator
|
||||||
{
|
{
|
||||||
std::size_t n_;
|
std::size_t n_ = 0;
|
||||||
std::uint8_t const* p_;
|
std::uint8_t const* p_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = boost::asio::const_buffer;
|
using value_type = boost::asio::const_buffer;
|
||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
mutable_buffers_type() = default;
|
mutable_buffers_type() = delete;
|
||||||
mutable_buffers_type(
|
mutable_buffers_type(
|
||||||
mutable_buffers_type const&) = default;
|
mutable_buffers_type const&) = default;
|
||||||
mutable_buffers_type& operator=(
|
mutable_buffers_type& operator=(
|
||||||
@@ -183,8 +183,8 @@ private:
|
|||||||
|
|
||||||
class static_streambuf::mutable_buffers_type::const_iterator
|
class static_streambuf::mutable_buffers_type::const_iterator
|
||||||
{
|
{
|
||||||
std::size_t n_;
|
std::size_t n_ = 0;
|
||||||
std::uint8_t* p_;
|
std::uint8_t* p_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = boost::asio::mutable_buffer;
|
using value_type = boost::asio::mutable_buffer;
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP
|
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP
|
||||||
|
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/bind_handler.hpp>
|
||||||
|
#include <beast/handler_concepts.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <boost/system/system_error.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
@@ -158,10 +160,6 @@ streambuf_readstream<Stream, Streambuf>::
|
|||||||
streambuf_readstream(Args&&... args)
|
streambuf_readstream(Args&&... args)
|
||||||
: next_layer_(std::forward<Args>(args)...)
|
: next_layer_(std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
static_assert(is_Stream<next_layer_type>::value,
|
|
||||||
"Stream requirements not met");
|
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
|
||||||
"Streambuf requirements not met");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class Streambuf>
|
||||||
@@ -173,10 +171,12 @@ async_write_some(ConstBufferSequence const& buffers,
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
{
|
{
|
||||||
|
static_assert(is_AsyncWriteStream<next_layer_type>::value,
|
||||||
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_ConstBufferSequence<
|
static_assert(is_ConstBufferSequence<
|
||||||
ConstBufferSequence>::value,
|
ConstBufferSequence>::value,
|
||||||
"ConstBufferSequence requirements not met");
|
"ConstBufferSequence requirements not met");
|
||||||
static_assert(is_Handler<WriteHandler,
|
static_assert(is_CompletionHandler<WriteHandler,
|
||||||
void(error_code, std::size_t)>::value,
|
void(error_code, std::size_t)>::value,
|
||||||
"WriteHandler requirements not met");
|
"WriteHandler requirements not met");
|
||||||
return next_layer_.async_write_some(buffers,
|
return next_layer_.async_write_some(buffers,
|
||||||
@@ -190,6 +190,8 @@ streambuf_readstream<Stream, Streambuf>::
|
|||||||
read_some(
|
read_some(
|
||||||
MutableBufferSequence const& buffers)
|
MutableBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
|
static_assert(is_SyncReadStream<next_layer_type>::value,
|
||||||
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_MutableBufferSequence<
|
static_assert(is_MutableBufferSequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
@@ -207,6 +209,8 @@ streambuf_readstream<Stream, Streambuf>::
|
|||||||
read_some(MutableBufferSequence const& buffers,
|
read_some(MutableBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
|
static_assert(is_SyncReadStream<next_layer_type>::value,
|
||||||
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_MutableBufferSequence<
|
static_assert(is_MutableBufferSequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
@@ -239,6 +243,8 @@ async_read_some(
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
{
|
{
|
||||||
|
static_assert(is_AsyncReadStream<next_layer_type>::value,
|
||||||
|
"Stream requirements not met");
|
||||||
static_assert(is_MutableBufferSequence<
|
static_assert(is_MutableBufferSequence<
|
||||||
MutableBufferSequence>::value,
|
MutableBufferSequence>::value,
|
||||||
"MutableBufferSequence requirements not met");
|
"MutableBufferSequence requirements not met");
|
||||||
|
|||||||
@@ -15,15 +15,15 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A `Streambuf` with a fixed size internal buffer.
|
/** A @b `Streambuf` with a fixed size internal buffer.
|
||||||
|
|
||||||
Ownership of the underlying storage belongs to the derived class.
|
Ownership of the underlying storage belongs to the derived class.
|
||||||
|
|
||||||
@note Variables are usually declared using the template class
|
@note Variables are usually declared using the template class
|
||||||
`static_streambuf_n`; however, to reduce the number of instantiations
|
@ref static_streambuf_n; however, to reduce the number of instantiations
|
||||||
of template functions receiving static stream buffer arguments in a
|
of template functions receiving static stream buffer arguments in a
|
||||||
deduced context, the signature of the receiving function should use
|
deduced context, the signature of the receiving function should use
|
||||||
`static_streambuf`.
|
@ref static_streambuf.
|
||||||
*/
|
*/
|
||||||
class static_streambuf
|
class static_streambuf
|
||||||
{
|
{
|
||||||
@@ -75,18 +75,28 @@ public:
|
|||||||
|
|
||||||
@throws std::length_error if the size would exceed the limit
|
@throws std::length_error if the size would exceed the limit
|
||||||
imposed by the underlying mutable buffer sequence.
|
imposed by the underlying mutable buffer sequence.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
*/
|
*/
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(std::size_t n);
|
prepare(std::size_t n);
|
||||||
|
|
||||||
/// Move bytes from the output sequence to the input sequence.
|
/** Move bytes from the output sequence to the input sequence.
|
||||||
|
|
||||||
|
@note Buffers representing the input sequence acquired prior to
|
||||||
|
this call remain valid.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
commit(std::size_t n)
|
commit(std::size_t n)
|
||||||
{
|
{
|
||||||
out_ += std::min<std::size_t>(n, last_ - out_);
|
out_ += std::min<std::size_t>(n, last_ - out_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a list of buffers that represents the input sequence.
|
/** Get a list of buffers that represents the input sequence.
|
||||||
|
|
||||||
|
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||||
|
*/
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const;
|
||||||
|
|
||||||
@@ -129,9 +139,11 @@ protected:
|
|||||||
*/
|
*/
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
class static_streambuf_n
|
class static_streambuf_n
|
||||||
: private boost::base_from_member<
|
: public static_streambuf
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
, private boost::base_from_member<
|
||||||
std::array<std::uint8_t, N>>
|
std::array<std::uint8_t, N>>
|
||||||
, public static_streambuf
|
#endif
|
||||||
{
|
{
|
||||||
using member_type = boost::base_from_member<
|
using member_type = boost::base_from_member<
|
||||||
std::array<std::uint8_t, N>>;
|
std::array<std::uint8_t, N>>;
|
||||||
|
|||||||
692
src/beast/include/beast/static_string.hpp
Normal file
692
src/beast/include/beast/static_string.hpp
Normal file
@@ -0,0 +1,692 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||||
|
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||||
|
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/** A string with a fixed-size storage area.
|
||||||
|
|
||||||
|
These objects behave like `std::string` except that the storage
|
||||||
|
is not dynamically allocated but rather fixed in size.
|
||||||
|
|
||||||
|
These strings offer performance advantages when a protocol
|
||||||
|
imposes a natural small upper limit on the size of a value.
|
||||||
|
|
||||||
|
@note The stored string is always null-terminated.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
std::size_t N,
|
||||||
|
class CharT = char,
|
||||||
|
class Traits = std::char_traits<CharT>>
|
||||||
|
class static_string
|
||||||
|
{
|
||||||
|
template<std::size_t, class, class>
|
||||||
|
friend class static_string;
|
||||||
|
|
||||||
|
std::size_t n_;
|
||||||
|
std::array<CharT, N+1> s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using traits_type = Traits;
|
||||||
|
using value_type = typename Traits::char_type;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_pointer = value_type const*;
|
||||||
|
using const_reference = value_type const&;
|
||||||
|
using iterator = value_type*;
|
||||||
|
using const_iterator = value_type const*;
|
||||||
|
using reverse_iterator =
|
||||||
|
std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator =
|
||||||
|
std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
/** Default constructor.
|
||||||
|
|
||||||
|
The string is initially empty, and null terminated.
|
||||||
|
*/
|
||||||
|
static_string();
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
static_string(static_string const& s);
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string(static_string<M, CharT, Traits> const& s);
|
||||||
|
|
||||||
|
/// Copy assignment.
|
||||||
|
static_string&
|
||||||
|
operator=(static_string const& s);
|
||||||
|
|
||||||
|
/// Copy assignment.
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string&
|
||||||
|
operator=(static_string<M, CharT, Traits> const& s);
|
||||||
|
|
||||||
|
/// Construct from string literal.
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string(const CharT (&s)[M]);
|
||||||
|
|
||||||
|
/// Assign from string literal.
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string& operator=(const CharT (&s)[M]);
|
||||||
|
|
||||||
|
/// Access specified character with bounds checking.
|
||||||
|
reference
|
||||||
|
at(size_type pos);
|
||||||
|
|
||||||
|
/// Access specified character with bounds checking.
|
||||||
|
const_reference
|
||||||
|
at(size_type pos) const;
|
||||||
|
|
||||||
|
/// Access specified character.
|
||||||
|
reference
|
||||||
|
operator[](size_type pos)
|
||||||
|
{
|
||||||
|
return s_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access specified character.
|
||||||
|
const_reference
|
||||||
|
operator[](size_type pos) const
|
||||||
|
{
|
||||||
|
return s_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accesses the first character.
|
||||||
|
CharT&
|
||||||
|
front()
|
||||||
|
{
|
||||||
|
return s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accesses the first character.
|
||||||
|
CharT const&
|
||||||
|
front() const
|
||||||
|
{
|
||||||
|
return s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accesses the last character.
|
||||||
|
CharT&
|
||||||
|
back()
|
||||||
|
{
|
||||||
|
return s_[n_-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accesses the last character.
|
||||||
|
CharT const&
|
||||||
|
back() const
|
||||||
|
{
|
||||||
|
return s_[n_-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a pointer to the first character of a string.
|
||||||
|
CharT*
|
||||||
|
data()
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a pointer to the first character of a string.
|
||||||
|
CharT const*
|
||||||
|
data() const
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a non-modifiable standard C character array version of the string.
|
||||||
|
CharT const*
|
||||||
|
c_str() const
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the beginning.
|
||||||
|
iterator
|
||||||
|
begin()
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the beginning.
|
||||||
|
const_iterator
|
||||||
|
begin() const
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the beginning.
|
||||||
|
const_iterator
|
||||||
|
cbegin() const
|
||||||
|
{
|
||||||
|
return &s_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the end.
|
||||||
|
iterator
|
||||||
|
end()
|
||||||
|
{
|
||||||
|
return &s_[n_];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the end.
|
||||||
|
const_iterator
|
||||||
|
end() const
|
||||||
|
{
|
||||||
|
return &s_[n_];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator to the end.
|
||||||
|
const_iterator
|
||||||
|
cend() const
|
||||||
|
{
|
||||||
|
return &s_[n_];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the beginning.
|
||||||
|
reverse_iterator
|
||||||
|
rbegin()
|
||||||
|
{
|
||||||
|
return reverse_iterator{end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the beginning.
|
||||||
|
const_reverse_iterator
|
||||||
|
rbegin() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator{cend()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the beginning.
|
||||||
|
const_reverse_iterator
|
||||||
|
crbegin() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator{cend()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the end.
|
||||||
|
reverse_iterator
|
||||||
|
rend()
|
||||||
|
{
|
||||||
|
return reverse_iterator{begin()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the end.
|
||||||
|
const_reverse_iterator
|
||||||
|
rend() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator{cbegin()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reverse iterator to the end.
|
||||||
|
const_reverse_iterator
|
||||||
|
crend() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator{cbegin()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the string is empty.
|
||||||
|
bool
|
||||||
|
empty() const
|
||||||
|
{
|
||||||
|
return n_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of characters, excluding the null terminator.
|
||||||
|
size_type
|
||||||
|
size() const
|
||||||
|
{
|
||||||
|
return n_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum number of characters that can be stored, excluding the null terminator.
|
||||||
|
size_type constexpr
|
||||||
|
max_size() const
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of characters that can be held in currently allocated storage.
|
||||||
|
size_type
|
||||||
|
capacity() const
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reduces memory usage by freeing unused memory.
|
||||||
|
void
|
||||||
|
shrink_to_fit()
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the contents.
|
||||||
|
void
|
||||||
|
clear()
|
||||||
|
{
|
||||||
|
resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Changes the number of characters stored.
|
||||||
|
|
||||||
|
@note No value-initialization is performed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
resize(std::size_t n);
|
||||||
|
|
||||||
|
/** Changes the number of characters stored.
|
||||||
|
|
||||||
|
If the resulting string is larger, the new
|
||||||
|
characters are initialized to the value of `c`.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
resize(std::size_t n, CharT c);
|
||||||
|
|
||||||
|
/// Compare two character sequences.
|
||||||
|
template<std::size_t M>
|
||||||
|
int compare(static_string<M, CharT, Traits> const& rhs) const;
|
||||||
|
|
||||||
|
/// Return the characters as a `basic_string`.
|
||||||
|
std::basic_string<CharT, Traits>
|
||||||
|
to_string() const
|
||||||
|
{
|
||||||
|
return std::basic_string<
|
||||||
|
CharT, Traits>{&s_[0], n_};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
assign(CharT const* s);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
static_string()
|
||||||
|
: n_(0)
|
||||||
|
{
|
||||||
|
s_[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
static_string(static_string const& s)
|
||||||
|
: n_(s.n_)
|
||||||
|
{
|
||||||
|
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
static_string(static_string<M, CharT, Traits> const& s)
|
||||||
|
{
|
||||||
|
if(s.size() > N)
|
||||||
|
throw std::length_error("static_string overflow");
|
||||||
|
n_ = s.size();
|
||||||
|
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
auto
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
operator=(static_string const& s) ->
|
||||||
|
static_string&
|
||||||
|
{
|
||||||
|
n_ = s.n_;
|
||||||
|
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
template<std::size_t M>
|
||||||
|
auto
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
operator=(static_string<M, CharT, Traits> const& s) ->
|
||||||
|
static_string&
|
||||||
|
{
|
||||||
|
if(s.size() > N)
|
||||||
|
throw std::length_error("static_string overflow");
|
||||||
|
n_ = s.size();
|
||||||
|
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
template<std::size_t M>
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
static_string(const CharT (&s)[M])
|
||||||
|
: n_(M-1)
|
||||||
|
{
|
||||||
|
static_assert(M-1 <= N,
|
||||||
|
"static_string overflow");
|
||||||
|
Traits::copy(&s_[0], &s[0], M);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
template<std::size_t M>
|
||||||
|
auto
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
operator=(const CharT (&s)[M]) ->
|
||||||
|
static_string&
|
||||||
|
{
|
||||||
|
static_assert(M-1 <= N,
|
||||||
|
"static_string overflow");
|
||||||
|
n_ = M-1;
|
||||||
|
Traits::copy(&s_[0], &s[0], M);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
auto
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
at(size_type pos) ->
|
||||||
|
reference
|
||||||
|
{
|
||||||
|
if(pos >= n_)
|
||||||
|
throw std::out_of_range("static_string::at");
|
||||||
|
return s_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
auto
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
at(size_type pos) const ->
|
||||||
|
const_reference
|
||||||
|
{
|
||||||
|
if(pos >= n_)
|
||||||
|
throw std::out_of_range("static_string::at");
|
||||||
|
return s_[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
void
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
resize(std::size_t n)
|
||||||
|
{
|
||||||
|
if(n > N)
|
||||||
|
throw std::length_error("static_string overflow");
|
||||||
|
n_ = n;
|
||||||
|
s_[n_] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
void
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
resize(std::size_t n, CharT c)
|
||||||
|
{
|
||||||
|
if(n > N)
|
||||||
|
throw std::length_error("static_string overflow");
|
||||||
|
if(n > n_)
|
||||||
|
Traits::assign(&s_[n_], n - n_, c);
|
||||||
|
n_ = n;
|
||||||
|
s_[n_] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
template<std::size_t M>
|
||||||
|
int
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
compare(static_string<M, CharT, Traits> const& rhs) const
|
||||||
|
{
|
||||||
|
if(size() < rhs.size())
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
data(), rhs.data(), size());
|
||||||
|
if(v == 0)
|
||||||
|
return -1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else if(size() > rhs.size())
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
data(), rhs.data(), rhs.size());
|
||||||
|
if(v == 0)
|
||||||
|
return 1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return Traits::compare(data(), rhs.data(), size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits>
|
||||||
|
void
|
||||||
|
static_string<N, CharT, Traits>::
|
||||||
|
assign(CharT const* s)
|
||||||
|
{
|
||||||
|
auto const n = Traits::length(s);
|
||||||
|
if(n > N)
|
||||||
|
throw std::out_of_range("too large");
|
||||||
|
n_ = n;
|
||||||
|
Traits::copy(&s_[0], s, n_ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
int compare(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
if(lhs.size() < M-1)
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
lhs.data(), &s[0], lhs.size());
|
||||||
|
if(v == 0)
|
||||||
|
return -1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else if(lhs.size() > M-1)
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
lhs.data(), &s[0], M-1);
|
||||||
|
if(v == 0)
|
||||||
|
return 1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return Traits::compare(lhs.data(), &s[0], lhs.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
int compare(
|
||||||
|
const CharT (&s)[M],
|
||||||
|
static_string<N, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
if(M-1 < rhs.size())
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
&s[0], rhs.data(), M-1);
|
||||||
|
if(v == 0)
|
||||||
|
return -1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else if(M-1 > rhs.size())
|
||||||
|
{
|
||||||
|
auto const v = Traits::compare(
|
||||||
|
&s[0], rhs.data(), rhs.size());
|
||||||
|
if(v == 0)
|
||||||
|
return 1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return Traits::compare(&s[0], rhs.data(), M-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator==(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator!=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator<(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator<=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator>(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator>=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.compare(rhs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator==(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator==(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator!=(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator!=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator<(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator<(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator<=(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator<=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator>(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator>(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
|
bool operator>=(
|
||||||
|
const CharT (&s)[N],
|
||||||
|
static_string<M, CharT, Traits> const& rhs)
|
||||||
|
{
|
||||||
|
return detail::compare(s, rhs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||||
|
bool operator>=(
|
||||||
|
static_string<N, CharT, Traits> const& lhs,
|
||||||
|
const CharT (&s)[M])
|
||||||
|
{
|
||||||
|
return detail::compare(lhs, s) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
76
src/beast/include/beast/stream_concepts.hpp
Normal file
76
src/beast/include/beast/stream_concepts.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// 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_STREAM_CONCEPTS_HPP
|
||||||
|
#define BEAST_STREAM_CONCEPTS_HPP
|
||||||
|
|
||||||
|
#include <beast/detail/stream_concepts.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/// Determine if `T` has the `get_io_service` member.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using has_get_io_service = typename detail::has_get_io_service<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `AsyncReadStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_AsyncReadStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_AsyncReadStream = typename detail::is_AsyncReadStream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `AsyncWriteStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_AsyncWriteStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_AsyncWriteStream = typename detail::is_AsyncWriteStream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `SyncReadStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_SyncReadStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_SyncReadStream = typename detail::is_SyncReadStream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `SyncWriterStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_SyncWriteStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_SyncWriteStream = typename detail::is_SyncWriteStream<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `AsyncStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_AsyncStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_AsyncStream = std::integral_constant<bool,
|
||||||
|
is_AsyncReadStream<T>::value && is_AsyncWriteStream<T>::value>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `SyncStream`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_SyncStream : std::integral_constant<bool, ...>{};
|
||||||
|
#else
|
||||||
|
using is_SyncStream = std::integral_constant<bool,
|
||||||
|
is_SyncReadStream<T>::value && is_SyncWriteStream<T>::value>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -12,6 +12,15 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
|
/** A @b `Streambuf` that uses multiple buffers internally.
|
||||||
|
|
||||||
|
The implementation uses a sequence of one or more character arrays
|
||||||
|
of varying sizes. Additional character array objects are appended to
|
||||||
|
the sequence to accommodate changes in the size of the character
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@note Meets the requirements of @b `Streambuf`.
|
||||||
|
*/
|
||||||
using streambuf = basic_streambuf<std::allocator<char>>;
|
using streambuf = basic_streambuf<std::allocator<char>>;
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
#define BEAST_STREAMBUF_READSTREAM_HPP
|
#define BEAST_STREAMBUF_READSTREAM_HPP
|
||||||
|
|
||||||
#include <beast/async_completion.hpp>
|
#include <beast/async_completion.hpp>
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
|
#include <beast/stream_concepts.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
|
#include <beast/detail/get_lowest_layer.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
@@ -18,11 +21,11 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A `Stream` with attached `Streambuf` to buffer reads.
|
/** A @b `Stream` with attached @b `Streambuf` to buffer reads.
|
||||||
|
|
||||||
This wraps a `Stream` implementation so that calls to write are
|
This wraps a @b `Stream` implementation so that calls to write are
|
||||||
passed through to the underlying stream, while calls to read will
|
passed through to the underlying stream, while calls to read will
|
||||||
first consume the input sequence stored in a `Streambuf` which
|
first consume the input sequence stored in a @b `Streambuf` which
|
||||||
is part of the object.
|
is part of the object.
|
||||||
|
|
||||||
The use-case for this class is different than that of the
|
The use-case for this class is different than that of the
|
||||||
@@ -35,10 +38,10 @@ namespace beast {
|
|||||||
|
|
||||||
Uses:
|
Uses:
|
||||||
|
|
||||||
* Transparently leave untouched input acquired in calls
|
@li Transparently leave untouched input acquired in calls
|
||||||
to `boost::asio::read_until` behind for subsequent callers.
|
to `boost::asio::read_until` behind for subsequent callers.
|
||||||
|
|
||||||
* "Preload" a stream with handshake input data acquired
|
@li "Preload" a stream with handshake input data acquired
|
||||||
from other sources.
|
from other sources.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -83,10 +86,12 @@ namespace beast {
|
|||||||
|
|
||||||
@tparam Streambuf The type of stream buffer to use.
|
@tparam Streambuf The type of stream buffer to use.
|
||||||
*/
|
*/
|
||||||
template<class Stream,
|
template<class Stream, class Streambuf>
|
||||||
class Streambuf = streambuf>
|
|
||||||
class streambuf_readstream
|
class streambuf_readstream
|
||||||
{
|
{
|
||||||
|
static_assert(is_Streambuf<Streambuf>::value,
|
||||||
|
"Streambuf requirements not met");
|
||||||
|
|
||||||
using error_code = boost::system::error_code;
|
using error_code = boost::system::error_code;
|
||||||
|
|
||||||
template<class Buffers, class Handler>
|
template<class Buffers, class Handler>
|
||||||
@@ -106,11 +111,27 @@ public:
|
|||||||
|
|
||||||
/// The type of the lowest layer.
|
/// The type of the lowest layer.
|
||||||
using lowest_layer_type =
|
using lowest_layer_type =
|
||||||
typename next_layer_type::lowest_layer_type;
|
#if GENERATING_DOCS
|
||||||
|
implementation_defined;
|
||||||
|
#else
|
||||||
|
typename detail::get_lowest_layer<
|
||||||
|
next_layer_type>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Move constructor.
|
/** Move constructor.
|
||||||
|
|
||||||
|
@note The behavior of move assignment on or from streams
|
||||||
|
with active or pending operations is undefined.
|
||||||
|
*/
|
||||||
streambuf_readstream(streambuf_readstream&&) = default;
|
streambuf_readstream(streambuf_readstream&&) = default;
|
||||||
|
|
||||||
|
/** Move assignment.
|
||||||
|
|
||||||
|
@note The behavior of move assignment on or from streams
|
||||||
|
with active or pending operations is undefined.
|
||||||
|
*/
|
||||||
|
streambuf_readstream& operator=(streambuf_readstream&&) = default;
|
||||||
|
|
||||||
/** Construct the wrapping stream.
|
/** Construct the wrapping stream.
|
||||||
|
|
||||||
@param args Parameters forwarded to the `Stream` constructor.
|
@param args Parameters forwarded to the `Stream` constructor.
|
||||||
@@ -200,6 +221,8 @@ public:
|
|||||||
std::size_t
|
std::size_t
|
||||||
write_some(ConstBufferSequence const& buffers)
|
write_some(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
|
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
return next_layer_.write_some(buffers);
|
return next_layer_.write_some(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,14 +233,19 @@ public:
|
|||||||
write_some(ConstBufferSequence const& buffers,
|
write_some(ConstBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
|
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
return next_layer_.write_some(buffers, ec);
|
return next_layer_.write_some(buffers, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start an asynchronous write. The data being written must be valid for the
|
/// Start an asynchronous write. The data being written must be valid for the
|
||||||
/// lifetime of the asynchronous operation.
|
/// lifetime of the asynchronous operation.
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
typename async_completion<
|
#if GENERATING_DOCS
|
||||||
WriteHandler, void(error_code)>::result_type
|
void_or_deduced
|
||||||
|
#else
|
||||||
|
typename async_completion<WriteHandler, void(error_code)>::result_type
|
||||||
|
#endif
|
||||||
async_write_some(ConstBufferSequence const& buffers,
|
async_write_some(ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
@@ -237,8 +265,11 @@ public:
|
|||||||
/// Start an asynchronous read. The buffer into which the data will be read
|
/// Start an asynchronous read. The buffer into which the data will be read
|
||||||
/// must be valid for the lifetime of the asynchronous operation.
|
/// must be valid for the lifetime of the asynchronous operation.
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
typename async_completion<
|
#if GENERATING_DOCS
|
||||||
ReadHandler, void(error_code)>::result_type
|
void_or_deduced
|
||||||
|
#else
|
||||||
|
typename async_completion<ReadHandler, void(error_code)>::result_type
|
||||||
|
#endif
|
||||||
async_read_some(MutableBufferSequence const& buffers,
|
async_read_some(MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
};
|
};
|
||||||
|
|||||||
51
src/beast/include/beast/to_string.hpp
Normal file
51
src/beast/include/beast/to_string.hpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// 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_TO_STRING_HPP
|
||||||
|
#define BEAST_TO_STRING_HPP
|
||||||
|
|
||||||
|
#include <beast/buffer_concepts.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/** Convert a @b `ConstBufferSequence` to a `std::string`.
|
||||||
|
|
||||||
|
This function will convert the octets in a buffer sequence to a string.
|
||||||
|
All octets will be inserted into the resulting string, including null
|
||||||
|
or unprintable characters.
|
||||||
|
|
||||||
|
@param buffers The buffer sequence to convert.
|
||||||
|
|
||||||
|
@return A string representing the contents of the input area.
|
||||||
|
|
||||||
|
@note This function participates in overload resolution only if
|
||||||
|
the streambuf parameter meets the requirements of @b `Streambuf`.
|
||||||
|
*/
|
||||||
|
template<class ConstBufferSequence
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
,class = std::enable_if<is_ConstBufferSequence<
|
||||||
|
ConstBufferSequence>::value>
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
std::string
|
||||||
|
to_string(ConstBufferSequence const& buffers)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer_cast;
|
||||||
|
using boost::asio::buffer_size;
|
||||||
|
std::string s;
|
||||||
|
s.reserve(buffer_size(buffers));
|
||||||
|
for(auto const& buffer : buffers)
|
||||||
|
s.append(buffer_cast<char const*>(buffer),
|
||||||
|
buffer_size(buffer));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,348 +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_TYPE_CHECK_HPP
|
|
||||||
#define BEAST_TYPE_CHECK_HPP
|
|
||||||
|
|
||||||
#include <beast/detail/is_call_possible.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/error.hpp>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <iterator>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Types that meet the requirements,
|
|
||||||
// for use with std::declval only.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
namespace detail {
|
|
||||||
#else
|
|
||||||
namespace concept {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class BufferType>
|
|
||||||
struct BufferSequence
|
|
||||||
{
|
|
||||||
using value_type = BufferType;
|
|
||||||
using const_iterator = BufferType const*;
|
|
||||||
~BufferSequence();
|
|
||||||
BufferSequence(BufferSequence const&) = default;
|
|
||||||
const_iterator
|
|
||||||
begin() const noexcept;
|
|
||||||
const_iterator
|
|
||||||
end() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ConstBufferSequence =
|
|
||||||
BufferSequence<boost::asio::const_buffer>;
|
|
||||||
|
|
||||||
using MutableBufferSequence =
|
|
||||||
BufferSequence<boost::asio::mutable_buffer>;
|
|
||||||
|
|
||||||
struct StreamHandler
|
|
||||||
{
|
|
||||||
StreamHandler(StreamHandler const&) = default;
|
|
||||||
void
|
|
||||||
operator()(boost::system::error_code ec,
|
|
||||||
std::size_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
using ReadHandler = StreamHandler;
|
|
||||||
using WriteHandler = StreamHandler;
|
|
||||||
|
|
||||||
} // concept
|
|
||||||
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html
|
|
||||||
//
|
|
||||||
/// Determine if `T` meets the requirements of `BufferSequence`.
|
|
||||||
template<class T, class BufferType>
|
|
||||||
class is_BufferSequence
|
|
||||||
{
|
|
||||||
template<class U, class R = std::is_convertible<
|
|
||||||
typename U::value_type, BufferType> >
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_base_of<
|
|
||||||
#if 0
|
|
||||||
std::bidirectional_iterator_tag,
|
|
||||||
typename std::iterator_traits<
|
|
||||||
typename U::const_iterator>::iterator_category>>
|
|
||||||
#else
|
|
||||||
// workaround:
|
|
||||||
// boost::asio::detail::consuming_buffers::const_iterator
|
|
||||||
// is not bidirectional
|
|
||||||
std::forward_iterator_tag,
|
|
||||||
typename std::iterator_traits<
|
|
||||||
typename U::const_iterator>::iterator_category>>
|
|
||||||
#endif
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = typename
|
|
||||||
std::is_convertible<decltype(
|
|
||||||
std::declval<U>().begin()),
|
|
||||||
typename U::const_iterator>::type>
|
|
||||||
static R check3(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check3(...);
|
|
||||||
using type3 = decltype(check3<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = typename std::is_convertible<decltype(
|
|
||||||
std::declval<U>().end()),
|
|
||||||
typename U::const_iterator>::type>
|
|
||||||
static R check4(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check4(...);
|
|
||||||
using type4 = decltype(check4<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
std::is_copy_constructible<T>::value &&
|
|
||||||
std::is_destructible<T>::value &&
|
|
||||||
type1::value && type2::value &&
|
|
||||||
type3::value && type4::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of `ConstBufferSequence`.
|
|
||||||
template<class T>
|
|
||||||
using is_ConstBufferSequence =
|
|
||||||
is_BufferSequence<T, boost::asio::const_buffer>;
|
|
||||||
static_assert(is_ConstBufferSequence<concept::ConstBufferSequence>::value, "");
|
|
||||||
static_assert(! is_ConstBufferSequence<int>::value, "");
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of `MutableBufferSequence`.
|
|
||||||
template<class C>
|
|
||||||
using is_MutableBufferSequence =
|
|
||||||
is_BufferSequence<C, boost::asio::mutable_buffer>;
|
|
||||||
static_assert(is_MutableBufferSequence<concept::MutableBufferSequence>::value, "");
|
|
||||||
static_assert(! is_MutableBufferSequence<int>::value, "");
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// Determine if `T` has the `get_io_service` member.
|
|
||||||
template<class T>
|
|
||||||
class has_get_io_service
|
|
||||||
{
|
|
||||||
template<class U, class R = typename std::is_same<
|
|
||||||
decltype(std::declval<U>().get_io_service()),
|
|
||||||
boost::asio::io_service&>>
|
|
||||||
static R check(int);
|
|
||||||
template <class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value = type::value;
|
|
||||||
};
|
|
||||||
static_assert(! has_get_io_service<int>::value, "");
|
|
||||||
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html
|
|
||||||
//
|
|
||||||
/// Determine if `T` meets the requirements of `AsyncReadStream`.
|
|
||||||
template<class T>
|
|
||||||
class is_AsyncReadStream
|
|
||||||
{
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().async_read_some(
|
|
||||||
std::declval<concept::MutableBufferSequence>(),
|
|
||||||
std::declval<concept::ReadHandler>()),
|
|
||||||
std::true_type{})>
|
|
||||||
static R check(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
has_get_io_service<T>::value && type::value;
|
|
||||||
};
|
|
||||||
static_assert(! is_AsyncReadStream<int>::value, "");
|
|
||||||
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html
|
|
||||||
//
|
|
||||||
/// Determine if `T` meets the requirements of `AsyncWriteStream`.
|
|
||||||
template<class T>
|
|
||||||
class is_AsyncWriteStream
|
|
||||||
{
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().async_write_some(
|
|
||||||
std::declval<concept::ConstBufferSequence>(),
|
|
||||||
std::declval<concept::WriteHandler>()),
|
|
||||||
std::true_type{})>
|
|
||||||
static R check(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
has_get_io_service<T>::value && type::value;
|
|
||||||
};
|
|
||||||
static_assert(! is_AsyncWriteStream<int>::value, "");
|
|
||||||
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html
|
|
||||||
//
|
|
||||||
/// Determine if `T` meets the requirements of `SyncReadStream`.
|
|
||||||
template<class T>
|
|
||||||
class is_SyncReadStream
|
|
||||||
{
|
|
||||||
using error_code =
|
|
||||||
boost::system::error_code;
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().read_some(
|
|
||||||
std::declval<concept::MutableBufferSequence>())),
|
|
||||||
std::size_t>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().read_some(
|
|
||||||
std::declval<concept::MutableBufferSequence>(),
|
|
||||||
std::declval<error_code&>())), std::size_t>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
type1::value && type2::value;
|
|
||||||
};
|
|
||||||
static_assert(! is_SyncReadStream<int>::value, "");
|
|
||||||
|
|
||||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html
|
|
||||||
//
|
|
||||||
/// Determine if `T` meets the requirements of `SyncWriterStream`.
|
|
||||||
template<class T>
|
|
||||||
class is_SyncWriteStream
|
|
||||||
{
|
|
||||||
using error_code =
|
|
||||||
boost::system::error_code;
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().write_some(
|
|
||||||
std::declval<concept::ConstBufferSequence>())),
|
|
||||||
std::size_t>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().write_some(
|
|
||||||
std::declval<concept::ConstBufferSequence>(),
|
|
||||||
std::declval<error_code&>())), std::size_t>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
type1::value && type2::value;
|
|
||||||
};
|
|
||||||
static_assert(! is_SyncWriteStream<int>::value, "");
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of `Stream`.
|
|
||||||
template<class T>
|
|
||||||
struct is_Stream
|
|
||||||
{
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
is_AsyncReadStream<T>::value &&
|
|
||||||
is_AsyncWriteStream<T>::value &&
|
|
||||||
is_SyncReadStream<T>::value &&
|
|
||||||
is_SyncWriteStream<T>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of `Streambuf`.
|
|
||||||
template<class T>
|
|
||||||
class is_Streambuf
|
|
||||||
{
|
|
||||||
template<class U, class R = std::integral_constant<
|
|
||||||
bool, is_MutableBufferSequence<decltype(
|
|
||||||
std::declval<U>().prepare(1))>::value>>
|
|
||||||
static R check1(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check1(...);
|
|
||||||
using type1 = decltype(check1<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::integral_constant<
|
|
||||||
bool, is_ConstBufferSequence<decltype(
|
|
||||||
std::declval<U>().data())>::value>>
|
|
||||||
static R check2(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check2(...);
|
|
||||||
using type2 = decltype(check2<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().commit(1), std::true_type{})>
|
|
||||||
static R check3(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check3(...);
|
|
||||||
using type3 = decltype(check3<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = decltype(
|
|
||||||
std::declval<U>().consume(1), std::true_type{})>
|
|
||||||
static R check4(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check4(...);
|
|
||||||
using type4 = decltype(check4<T>(0));
|
|
||||||
|
|
||||||
template<class U, class R = std::is_same<decltype(
|
|
||||||
std::declval<U>().size()), std::size_t>>
|
|
||||||
static R check5(int);
|
|
||||||
template<class>
|
|
||||||
static std::false_type check5(...);
|
|
||||||
using type5 = decltype(check5<T>(0));
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// `true` if `T` meets the requirements.
|
|
||||||
static bool const value =
|
|
||||||
type1::value && type2::value &&
|
|
||||||
type3::value && type4::value &&
|
|
||||||
type5::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of `CompletionHandler`.
|
|
||||||
template<class T, class Signature>
|
|
||||||
using is_Handler = std::integral_constant<bool,
|
|
||||||
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
|
||||||
detail::is_call_possible<T, Signature>::value>;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -16,6 +16,6 @@
|
|||||||
//
|
//
|
||||||
#define BEAST_VERSION 100000
|
#define BEAST_VERSION 100000
|
||||||
|
|
||||||
#define BEAST_VERSION_STRING "1.0.0-b2"
|
#define BEAST_VERSION_STRING "1.0.0-b3"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <beast/websocket/option.hpp>
|
#include <beast/websocket/option.hpp>
|
||||||
#include <beast/websocket/rfc6455.hpp>
|
#include <beast/websocket/rfc6455.hpp>
|
||||||
#include <beast/websocket/stream.hpp>
|
#include <beast/websocket/stream.hpp>
|
||||||
#include <beast/websocket/static_string.hpp>
|
|
||||||
#include <beast/websocket/teardown.hpp>
|
#include <beast/websocket/teardown.hpp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#ifndef BEAST_WSPROTO_DEBUG_H_INCLUDED
|
#ifndef BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||||
#define BEAST_WSPROTO_DEBUG_H_INCLUDED
|
#define BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||||
|
|
||||||
#include <beast/unit_test/suite.h>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -82,7 +81,7 @@ format(std::string s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // wsproto
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -53,6 +53,17 @@ little_uint32_to_native(void const* buf)
|
|||||||
(static_cast<std::uint64_t>(p[3])<<24);
|
(static_cast<std::uint64_t>(p[3])<<24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
native_to_little_uint32(std::uint32_t v, void* buf)
|
||||||
|
{
|
||||||
|
auto p = reinterpret_cast<std::uint8_t*>(buf);
|
||||||
|
p[0] = v & 0xff;
|
||||||
|
p[1] = (v >> 8) & 0xff;
|
||||||
|
p[2] = (v >> 16) & 0xff;
|
||||||
|
p[3] = (v >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // websocket
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
const char*
|
const char*
|
||||||
name() const noexcept override
|
name() const noexcept override
|
||||||
{
|
{
|
||||||
return "wsproto";
|
return "websocket";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
case error::request_invalid: return "upgrade request invalid";
|
case error::request_invalid: return "upgrade request invalid";
|
||||||
case error::request_denied: return "upgrade request denied";
|
case error::request_denied: return "upgrade request denied";
|
||||||
default:
|
default:
|
||||||
return "wsproto.error";
|
return "websocket error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
#define BEAST_WEBSOCKET_DETAIL_FRAME_HPP
|
#define BEAST_WEBSOCKET_DETAIL_FRAME_HPP
|
||||||
|
|
||||||
#include <beast/websocket/rfc6455.hpp>
|
#include <beast/websocket/rfc6455.hpp>
|
||||||
#include <beast/websocket/static_string.hpp>
|
|
||||||
#include <beast/websocket/detail/endian.hpp>
|
#include <beast/websocket/detail/endian.hpp>
|
||||||
#include <beast/websocket/detail/utf8_checker.hpp>
|
#include <beast/websocket/detail/utf8_checker.hpp>
|
||||||
#include <beast/consuming_buffers.hpp>
|
#include <beast/consuming_buffers.hpp>
|
||||||
#include <beast/static_streambuf.hpp>
|
#include <beast/static_streambuf.hpp>
|
||||||
|
#include <beast/static_string.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/endian/buffers.hpp>
|
#include <boost/endian/buffers.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -70,10 +70,9 @@ is_control(opcode op)
|
|||||||
// Returns `true` if a close code is valid
|
// Returns `true` if a close code is valid
|
||||||
inline
|
inline
|
||||||
bool
|
bool
|
||||||
is_valid(close_code code)
|
is_valid(close_code::value code)
|
||||||
{
|
{
|
||||||
auto const v = static_cast<
|
auto const v = code;
|
||||||
std::uint16_t>(code);
|
|
||||||
switch(v)
|
switch(v)
|
||||||
{
|
{
|
||||||
case 1000:
|
case 1000:
|
||||||
@@ -141,9 +140,7 @@ write(Streambuf& sb, frame_header const& fh)
|
|||||||
}
|
}
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
{
|
{
|
||||||
little_uint32_buf_t key(fh.key);
|
native_to_little_uint32(fh.key, &b[n]);
|
||||||
std::copy(key.data(),
|
|
||||||
key.data() + 4, &b[n]);
|
|
||||||
n += 4;
|
n += 4;
|
||||||
}
|
}
|
||||||
sb.commit(buffer_copy(
|
sb.commit(buffer_copy(
|
||||||
@@ -156,7 +153,7 @@ write(Streambuf& sb, frame_header const& fh)
|
|||||||
template<class Streambuf>
|
template<class Streambuf>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_fh1(frame_header& fh, Streambuf& sb,
|
read_fh1(frame_header& fh, Streambuf& sb,
|
||||||
role_type role, close_code& code)
|
role_type role, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
@@ -173,7 +170,8 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
|||||||
default:
|
default:
|
||||||
need = 0;
|
need = 0;
|
||||||
}
|
}
|
||||||
if((fh.mask = (b[1] & 0x80) != 0))
|
fh.mask = (b[1] & 0x80) != 0;
|
||||||
|
if(fh.mask)
|
||||||
need += 4;
|
need += 4;
|
||||||
fh.op = static_cast<opcode>(b[0] & 0x0f);
|
fh.op = static_cast<opcode>(b[0] & 0x0f);
|
||||||
fh.fin = (b[0] & 0x80) != 0;
|
fh.fin = (b[0] & 0x80) != 0;
|
||||||
@@ -232,7 +230,7 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
|||||||
template<class Streambuf>
|
template<class Streambuf>
|
||||||
void
|
void
|
||||||
read_fh2(frame_header& fh, Streambuf& sb,
|
read_fh2(frame_header& fh, Streambuf& sb,
|
||||||
role_type role, close_code& code)
|
role_type role, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
@@ -303,7 +301,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
void
|
void
|
||||||
read(ping_payload_type& data,
|
read(ping_payload_type& data,
|
||||||
Buffers const& bs, close_code& code)
|
Buffers const& bs, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
@@ -320,7 +318,7 @@ read(ping_payload_type& data,
|
|||||||
template<class Buffers>
|
template<class Buffers>
|
||||||
void
|
void
|
||||||
read(close_reason& cr,
|
read(close_reason& cr,
|
||||||
Buffers const& bs, close_code& code)
|
Buffers const& bs, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
@@ -343,15 +341,7 @@ read(close_reason& cr,
|
|||||||
{
|
{
|
||||||
std::uint8_t b[2];
|
std::uint8_t b[2];
|
||||||
buffer_copy(buffer(b), cb);
|
buffer_copy(buffer(b), cb);
|
||||||
#if 0
|
cr.code = big_uint16_to_native(&b[0]);
|
||||||
// Causes strict-aliasing warning in gcc
|
|
||||||
cr.code = static_cast<close_code>(
|
|
||||||
reinterpret_cast<
|
|
||||||
big_uint16_buf_t const*>(&b[0])->value());
|
|
||||||
#else
|
|
||||||
cr.code = static_cast<close_code>(
|
|
||||||
big_uint16_to_native(&b[0]));
|
|
||||||
#endif
|
|
||||||
cb.consume(2);
|
cb.consume(2);
|
||||||
n -= 2;
|
n -= 2;
|
||||||
if(! is_valid(cr.code))
|
if(! is_valid(cr.code))
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
invokable() = default;
|
invokable() = default;
|
||||||
invokable(invokable const&) = delete;
|
|
||||||
invokable& operator=(invokable const&) = delete;
|
|
||||||
|
|
||||||
invokable(invokable&& other)
|
invokable(invokable&& other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ class maskgen_t
|
|||||||
public:
|
public:
|
||||||
using result_type = typename std::mt19937::result_type;
|
using result_type = typename std::mt19937::result_type;
|
||||||
|
|
||||||
maskgen_t(maskgen_t const&) = delete;
|
|
||||||
maskgen_t& operator=(maskgen_t const&) = delete;
|
|
||||||
|
|
||||||
maskgen_t();
|
maskgen_t();
|
||||||
|
|
||||||
result_type
|
result_type
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ protected:
|
|||||||
|
|
||||||
template<class = void>
|
template<class = void>
|
||||||
void
|
void
|
||||||
prepare_fh(close_code& code);
|
prepare_fh(close_code::value& code);
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class Streambuf>
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -73,12 +73,6 @@ class utf8_checker_t
|
|||||||
std::uint32_t codepoint_ = 0;
|
std::uint32_t codepoint_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
utf8_checker_t() = default;
|
|
||||||
utf8_checker_t(utf8_checker_t&&) = default;
|
|
||||||
utf8_checker_t(utf8_checker_t const&) = default;
|
|
||||||
utf8_checker_t& operator=(utf8_checker_t&&) = default;
|
|
||||||
utf8_checker_t& operator=(utf8_checker_t const&) = default;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define BEAST_WEBSOCKET_ERROR_HPP
|
#define BEAST_WEBSOCKET_ERROR_HPP
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <boost/system/system_error.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
@@ -16,7 +17,7 @@ namespace websocket {
|
|||||||
/// The type of error used by functions and completion handlers.
|
/// The type of error used by functions and completion handlers.
|
||||||
using error_code = boost::system::error_code;
|
using error_code = boost::system::error_code;
|
||||||
|
|
||||||
/// Error values
|
/// Error codes returned from @ref stream operations.
|
||||||
enum class error
|
enum class error
|
||||||
{
|
{
|
||||||
/// Both sides performed a WebSocket close
|
/// Both sides performed a WebSocket close
|
||||||
@@ -50,8 +51,10 @@ enum class error
|
|||||||
request_denied
|
request_denied
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
error_code
|
error_code
|
||||||
make_error_code(error e);
|
make_error_code(error e);
|
||||||
|
#endif
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -9,10 +9,11 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP
|
#define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP
|
||||||
|
|
||||||
#include <beast/websocket/impl/response_op.ipp>
|
#include <beast/websocket/impl/response_op.ipp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/prepare_buffers.hpp>
|
#include <beast/prepare_buffers.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
|
||||||
#include <beast/http/read.hpp>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -32,7 +33,7 @@ class stream<NextLayer>::accept_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
http::request<http::empty_body> req;
|
http::request_v1<http::empty_body> req;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
@@ -124,7 +125,7 @@ operator()(error_code const& ec,
|
|||||||
case 0:
|
case 0:
|
||||||
// read message
|
// read message
|
||||||
d.state = 1;
|
d.state = 1;
|
||||||
http::async_read(d.ws.next_layer_,
|
http::async_read(d.ws.next_layer(),
|
||||||
d.ws.stream_.buffer(), d.req,
|
d.ws.stream_.buffer(), d.req,
|
||||||
std::move(*this));
|
std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ class stream<NextLayer>::close_op
|
|||||||
close_reason cr;
|
close_reason cr;
|
||||||
Handler h;
|
Handler h;
|
||||||
fb_type fb;
|
fb_type fb;
|
||||||
fmb_type fmb;
|
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
@@ -176,8 +175,8 @@ stream<NextLayer>::close_op<Handler>::operator()(
|
|||||||
d.ws.error_ = true;
|
d.ws.error_ = true;
|
||||||
if(d.ws.wr_block_ == &d)
|
if(d.ws.wr_block_ == &d)
|
||||||
d.ws.wr_block_ = nullptr;
|
d.ws.wr_block_ = nullptr;
|
||||||
d.h(ec);
|
|
||||||
d.ws.rd_op_.maybe_invoke();
|
d.ws.rd_op_.maybe_invoke();
|
||||||
|
d.h(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -33,8 +33,8 @@ class stream<NextLayer>::handshake_op
|
|||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
Handler h;
|
Handler h;
|
||||||
std::string key;
|
std::string key;
|
||||||
http::request<http::empty_body> req;
|
http::request_v1<http::empty_body> req;
|
||||||
http::response<http::string_body> resp;
|
http::response_v1<http::string_body> resp;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ stream<NextLayer>::handshake_op<
|
|||||||
case 1:
|
case 1:
|
||||||
// read http response
|
// read http response
|
||||||
d.state = 2;
|
d.state = 2;
|
||||||
http::async_read(d.ws.next_layer_,
|
http::async_read(d.ws.next_layer(),
|
||||||
d.ws.stream_.buffer(), d.resp,
|
d.ws.stream_.buffer(), d.resp,
|
||||||
std::move(*this));
|
std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ class stream<NextLayer>::read_frame_op
|
|||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
frame_info& fi;
|
frame_info& fi;
|
||||||
Streambuf& sb;
|
Streambuf& sb;
|
||||||
smb_type smb;
|
|
||||||
Handler h;
|
Handler h;
|
||||||
fb_type fb;
|
fb_type fb;
|
||||||
fmb_type fmb;
|
boost::optional<smb_type> smb;
|
||||||
|
boost::optional<fmb_type> fmb;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
d.cont = d.cont || again;
|
d.cont = d.cont || again;
|
||||||
close_code code;
|
close_code::value code = close_code::none;
|
||||||
while(! ec && d.state != 99)
|
while(! ec && d.state != 99)
|
||||||
{
|
{
|
||||||
switch(d.state)
|
switch(d.state)
|
||||||
@@ -161,7 +161,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
d.smb = d.sb.prepare(
|
d.smb = d.sb.prepare(
|
||||||
detail::clamp(d.ws.rd_need_));
|
detail::clamp(d.ws.rd_need_));
|
||||||
d.ws.stream_.async_read_some(
|
d.ws.stream_.async_read_some(
|
||||||
d.smb, std::move(*this));
|
*d.smb, std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -176,7 +176,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
{
|
{
|
||||||
d.ws.rd_need_ -= bytes_transferred;
|
d.ws.rd_need_ -= bytes_transferred;
|
||||||
auto const pb = prepare_buffers(
|
auto const pb = prepare_buffers(
|
||||||
bytes_transferred, d.smb);
|
bytes_transferred, *d.smb);
|
||||||
if(d.ws.rd_fh_.mask)
|
if(d.ws.rd_fh_.mask)
|
||||||
detail::mask_inplace(pb, d.ws.rd_key_);
|
detail::mask_inplace(pb, d.ws.rd_key_);
|
||||||
if(d.ws.rd_opcode_ == opcode::text)
|
if(d.ws.rd_opcode_ == opcode::text)
|
||||||
@@ -195,7 +195,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
d.state = 4;
|
d.state = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// call handler
|
// call handler
|
||||||
case 4:
|
case 4:
|
||||||
d.state = 99;
|
d.state = 99;
|
||||||
@@ -252,7 +252,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
d.fmb = d.fb.prepare(static_cast<
|
d.fmb = d.fb.prepare(static_cast<
|
||||||
std::size_t>(d.ws.rd_fh_.len));
|
std::size_t>(d.ws.rd_fh_.len));
|
||||||
boost::asio::async_read(d.ws.stream_,
|
boost::asio::async_read(d.ws.stream_,
|
||||||
d.fmb, std::move(*this));
|
*d.fmb, std::move(*this));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d.state = 8;
|
d.state = 8;
|
||||||
@@ -276,7 +276,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
case 7:
|
case 7:
|
||||||
if(d.ws.rd_fh_.mask)
|
if(d.ws.rd_fh_.mask)
|
||||||
detail::mask_inplace(
|
detail::mask_inplace(
|
||||||
d.fmb, d.ws.rd_key_);
|
*d.fmb, d.ws.rd_key_);
|
||||||
d.fb.commit(bytes_transferred);
|
d.fb.commit(bytes_transferred);
|
||||||
d.state = 8;
|
d.state = 8;
|
||||||
break;
|
break;
|
||||||
@@ -396,8 +396,8 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
// teardown
|
// teardown
|
||||||
case 11:
|
case 11:
|
||||||
d.state = 12;
|
d.state = 12;
|
||||||
wsproto_helpers::call_async_teardown(
|
websocket_helpers::call_async_teardown(
|
||||||
d.ws.next_layer_, std::move(*this));
|
d.ws.next_layer(), std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
@@ -482,8 +482,8 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
// teardown
|
// teardown
|
||||||
case 19:
|
case 19:
|
||||||
d.state = 20;
|
d.state = 20;
|
||||||
wsproto_helpers::call_async_teardown(
|
websocket_helpers::call_async_teardown(
|
||||||
d.ws.next_layer_, std::move(*this));
|
d.ws.next_layer(), std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 20:
|
case 20:
|
||||||
@@ -497,8 +497,8 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
d.ws.error_ = true;
|
d.ws.error_ = true;
|
||||||
if(d.ws.wr_block_ == &d)
|
if(d.ws.wr_block_ == &d)
|
||||||
d.ws.wr_block_ = nullptr;
|
d.ws.wr_block_ = nullptr;
|
||||||
d.h(ec);
|
|
||||||
d.ws.wr_op_.maybe_invoke();
|
d.ws.wr_op_.maybe_invoke();
|
||||||
|
d.h(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
|
#define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
|
||||||
|
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -27,7 +28,7 @@ class stream<NextLayer>::response_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
http::response<http::string_body> resp;
|
http::response_v1<http::string_body> resp;
|
||||||
Handler h;
|
Handler h;
|
||||||
error_code final_ec;
|
error_code final_ec;
|
||||||
bool cont;
|
bool cont;
|
||||||
@@ -36,7 +37,7 @@ class stream<NextLayer>::response_op
|
|||||||
template<class DeducedHandler,
|
template<class DeducedHandler,
|
||||||
class Body, class Headers>
|
class Body, class Headers>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||||
http::message<true, Body, Headers> const& req,
|
http::request_v1<Body, Headers> const& req,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, resp(ws_.build_response(req))
|
, resp(ws_.build_response(req))
|
||||||
@@ -113,7 +114,7 @@ operator()(error_code ec, bool again)
|
|||||||
case 0:
|
case 0:
|
||||||
// send response
|
// send response
|
||||||
d.state = 1;
|
d.state = 1;
|
||||||
http::async_write(d.ws.next_layer_,
|
http::async_write(d.ws.next_layer(),
|
||||||
d.resp, std::move(*this));
|
d.resp, std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user