diff --git a/CHANGELOG b/CHANGELOG index a467786b..48e29388 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,10 +4,8 @@ * Use beast::error_code instead of nested types * Tidy up use of GENERATING_DOCS * Remove obsolete RFC2616 functions -* Add HTTP field value parser containers: - - ext_list - - param_list - - token_list +* Add message swap members and free functions +* Add HTTP field value parser containers: ext_list, param_list, token_list API Changes: diff --git a/TODO.txt b/TODO.txt index 2efbbb77..3b66fc11 100644 --- a/TODO.txt +++ b/TODO.txt @@ -44,3 +44,5 @@ HTTP: * Custom HTTP error codes for various situations * Branch prediction hints in parser * Check basic_parser_v1 against rfc7230 for leading message whitespace +* Fix the order of message constructor parameters: + body first then headers (since body is constructed with arguments more often) diff --git a/doc/quickref.xml b/doc/quickref.xml index 8aec0524..929876ff 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -56,6 +56,7 @@ parse prepare read + swap write Constants diff --git a/include/beast/http/message.hpp b/include/beast/http/message.hpp index 04c77037..6c1a57c9 100644 --- a/include/beast/http/message.hpp +++ b/include/beast/http/message.hpp @@ -24,12 +24,30 @@ struct request_fields { std::string method; std::string url; + +protected: + void + swap(request_fields& other) + { + using std::swap; + swap(method, other.method); + swap(url, other.url); + } }; struct response_fields { int status; std::string reason; + +protected: + void + swap(response_fields& other) + { + using std::swap; + swap(status, other.status); + swap(reason, other.reason); + } }; } // detail @@ -125,7 +143,14 @@ struct message { } + /// Swap this message for another message. + void + swap(message& other); + private: + using base = typename std::conditional::type; + template message(std::piecewise_construct_t, std::tuple& tu, beast::detail::index_sequence) @@ -145,6 +170,27 @@ private: } }; +template +void +message:: +swap(message& other) +{ + using std::swap; + base::swap(other); + swap(headers, other.headers); + swap(body, other.body); +} + +/// Swap one message for another message. +template +inline +void +swap(message& lhs, + message& rhs) +{ + lhs.swap(rhs); +} + /// A typical HTTP request template>> diff --git a/include/beast/http/message_v1.hpp b/include/beast/http/message_v1.hpp index fb700b81..68abc68c 100644 --- a/include/beast/http/message_v1.hpp +++ b/include/beast/http/message_v1.hpp @@ -48,8 +48,32 @@ struct message_v1 : message std::forward(argn)...) { } + + /// Swap this message for another message. + void + swap(message_v1& other); }; +template +void +message_v1:: +swap(message_v1& other) +{ + using std::swap; + message::swap(other); + swap(version, other.version); +} + +/// Swap one message for another message. +template +inline +void +swap(message_v1& lhs, + message_v1& rhs) +{ + lhs.swap(rhs); +} + /// A typical HTTP/1 request template>> diff --git a/test/http/message.cpp b/test/http/message.cpp index 6d46ed47..3c549248 100644 --- a/test/http/message.cpp +++ b/test/http/message.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -126,9 +127,30 @@ public: } } + void testSwap() + { + message m1; + message m2; + m1.url = "u"; + m1.body = "1"; + m1.headers.insert("h", "v"); + m2.method = "G"; + m2.body = "2"; + swap(m1, m2); + expect(m1.method == "G"); + expect(m2.method.empty()); + expect(m1.url.empty()); + expect(m2.url == "u"); + expect(m1.body == "2"); + expect(m2.body == "1"); + expect(! m1.headers.exists("h")); + expect(m2.headers.exists("h")); + } + void run() override { testConstruction(); + testSwap(); } }; diff --git a/test/http/message_v1.cpp b/test/http/message_v1.cpp index d86097dd..a8954c68 100644 --- a/test/http/message_v1.cpp +++ b/test/http/message_v1.cpp @@ -8,6 +8,8 @@ // Test that header file is self-contained. #include +#include +#include #include #include @@ -78,10 +80,36 @@ public: expect(! is_keep_alive(m)); } + void testSwap() + { + message_v1 m1; + message_v1 m2; + m1.status = 200; + m1.version = 10; + m1.body = "1"; + m1.headers.insert("h", "v"); + m2.status = 404; + m2.reason = "OK"; + m2.body = "2"; + m2.version = 11; + swap(m1, m2); + expect(m1.status == 404); + expect(m2.status == 200); + expect(m1.reason == "OK"); + expect(m2.reason.empty()); + expect(m1.version == 11); + expect(m2.version == 10); + expect(m1.body == "2"); + expect(m2.body == "1"); + expect(! m1.headers.exists("h")); + expect(m2.headers.exists("h")); + } + void run() override { testFreeFunctions(); testPrepare(); + testSwap(); } };