Skip to content

Commit 2ed9c92

Browse files
author
me
committed
added dynamic_buffer so you can read into std::vector or std::string, possibly other things in the future
1 parent 874aaeb commit 2ed9c92

File tree

6 files changed

+122
-63
lines changed

6 files changed

+122
-63
lines changed

examples/client_ws_awaitable.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ using namespace std::chrono_literals;
3434
//----------------------------------------------------------------------------------------------------------------
3535
//----------------------------------------------------------------------------------------------------------------
3636

37-
awaitable_strand read_write_one(auto& sock, std::string_view host, std::vector<char>& msg)
37+
awaitable_strand read_write_one(auto& sock, std::string_view host, std::string& msg)
3838
{
3939
constexpr bool is_text{false};
4040
co_await http::async_ws_handshake(sock, host, "/ws");
@@ -50,7 +50,7 @@ awaitable_strand ws_session(std::string_view host, uint16_t port, std::string_vi
5050
// Objects
5151
http_socket sock(tcp_socket(co_await boost::asio::this_coro::executor), false);
5252
tcp::resolver resolver(sock.get_executor());
53-
std::vector<char> buf(begin(msg), end(msg));
53+
std::string buf(msg);
5454

5555
// Async IO
5656
co_await boost::asio::async_connect(sock.lowest_layer(), co_await resolver.async_resolve(host, std::to_string(port)), boost::asio::cancel_after(5s));
@@ -77,7 +77,7 @@ awaitable_strand ws_ssl_session(std::string_view host, uint16_t port, std::strin
7777

7878
https_socket sock(tls_socket(co_await boost::asio::this_coro::executor, ssl), false);
7979
tcp::resolver resolver(sock.get_executor());
80-
std::vector<char> buf(begin(msg), end(msg));
80+
std::string buf(msg);
8181

8282
// Async IO
8383
co_await boost::asio::async_connect(sock.lowest_layer(), co_await resolver.async_resolve(host, std::to_string(port)), boost::asio::cancel_after(5s));

examples/client_ws_coro.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ using namespace std::chrono_literals;
3737
//----------------------------------------------------------------------------------------------------------------
3838

3939
template<class Sock>
40-
void read_write_one(Sock& sock, std::string_view host, std::vector<char>& msg, yield_context_strand yield)
40+
void read_write_one(Sock& sock, std::string_view host, std::string& msg, yield_context_strand yield)
4141
{
4242
constexpr bool is_text{false};
4343
http::async_ws_handshake(sock, host, "/ws", yield);
@@ -51,9 +51,9 @@ void ws_session(std::string_view host, uint16_t port, std::string_view msg, yiel
5151
try
5252
{
5353
// Objects
54-
http_socket sock(tcp_socket(yield.get_executor()), false);
55-
tcp::resolver resolver(sock.get_executor());
56-
std::vector<char> buf(begin(msg), end(msg));
54+
http_socket sock(tcp_socket(yield.get_executor()), false);
55+
tcp::resolver resolver(sock.get_executor());
56+
std::string buf(msg);
5757

5858
// Async IO
5959
boost::asio::async_connect(sock.lowest_layer(), resolver.async_resolve(host, std::to_string(port), yield), boost::asio::cancel_after(5s, yield));
@@ -78,9 +78,9 @@ void ws_ssl_session(std::string_view host, uint16_t port, std::string_view msg,
7878
ssl.set_verify_callback([](bool preverified, boost::asio::ssl::verify_context& ctx) {return true;});
7979
ssl.set_verify_mode(boost::asio::ssl::verify_peer);
8080

81-
https_socket sock(tls_socket(yield.get_executor(), ssl), false);
82-
tcp::resolver resolver(sock.get_executor());
83-
std::vector<char> buf(begin(msg), end(msg));
81+
https_socket sock(tls_socket(yield.get_executor(), ssl), false);
82+
tcp::resolver resolver(sock.get_executor());
83+
std::string buf(msg);
8484

8585
// Async IO
8686
boost::asio::async_connect(sock.lowest_layer(), resolver.async_resolve(host, std::to_string(port), yield), boost::asio::cancel_after(5s, yield));

examples/unit_tests/async.cpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ TEST_SUITE("[ASYNC]")
178178
std::string text;
179179
std::vector<char> data_peer;
180180
std::vector<char> data_client;
181+
std::string text_peer;
182+
std::string text_client;
181183

182184
std::mt19937 eng(std::random_device{}());
183185
std::uniform_int_distribution<unsigned int> d{0, 255};
@@ -202,13 +204,11 @@ TEST_SUITE("[ASYNC]")
202204
http::async_ws_read(peer, data_peer, [&](boost::system::error_code ec, bool is_text) {
203205
REQUIRE(!bool(ec));
204206
REQUIRE(!is_text);
205-
REQUIRE(data_peer.size() == data.size());
206-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(data)));
207-
http::async_ws_read(peer, data_peer, [&](boost::system::error_code ec, bool is_text) {
207+
REQUIRE(data_peer == data);
208+
http::async_ws_read(peer, text_peer, [&](boost::system::error_code ec, bool is_text) {
208209
REQUIRE(!bool(ec));
209210
REQUIRE(is_text);
210-
REQUIRE(data_peer.size() == text.size());
211-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(text)));
211+
REQUIRE(text_peer == text);
212212
http::async_ws_read(peer, data_peer, [&](boost::system::error_code ec, bool is_text) {
213213
REQUIRE(ec == http::ws_going_away);
214214
});
@@ -226,7 +226,7 @@ TEST_SUITE("[ASYNC]")
226226
REQUIRE(!bool(ec));
227227
http::async_ws_write(client, boost::asio::buffer(data), false, [&](boost::system::error_code ec, std::size_t) {
228228
REQUIRE(!bool(ec));
229-
http::async_ws_write(client, boost::asio::buffer(text), true, [&](boost::system::error_code ec, std::size_t) {
229+
http::async_ws_write(client, boost::asio::buffer(text), true, [&](boost::system::error_code ec, std::size_t) {
230230
REQUIRE(!bool(ec));
231231
http::async_ws_close(client, http::ws_going_away, [&](boost::system::error_code ec) {
232232
REQUIRE(!bool(ec));
@@ -258,12 +258,10 @@ TEST_SUITE("[ASYNC]")
258258
co_await http::async_ws_accept(peer, req);
259259
is_text = co_await http::async_ws_read(peer, data_peer);
260260
REQUIRE(!is_text);
261-
REQUIRE(data_peer.size() == data.size());
262-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(data)));
263-
is_text = co_await http::async_ws_read(peer, data_peer);
261+
REQUIRE(data_peer == data);
262+
is_text = co_await http::async_ws_read(peer, text_peer);
264263
REQUIRE(is_text);
265-
REQUIRE(data_peer.size() == text.size());
266-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(text)));
264+
REQUIRE(text_peer == text);
267265
auto [ec, is_text2] = co_await http::async_ws_read(peer, data_peer, as_tuple(deferred));
268266
REQUIRE(ec == http::ws_going_away);
269267
};
@@ -300,12 +298,10 @@ TEST_SUITE("[ASYNC]")
300298
http::async_ws_accept(peer, req, yield);
301299
is_text = http::async_ws_read(peer, data_peer, yield);
302300
REQUIRE(!is_text);
303-
REQUIRE(data_peer.size() == data.size());
304-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(data)));
305-
is_text = http::async_ws_read(peer, data_peer, yield);
301+
REQUIRE(data_peer == data);
302+
is_text = http::async_ws_read(peer, text_peer, yield);
306303
REQUIRE(is_text);
307-
REQUIRE(data_peer.size() == text.size());
308-
REQUIRE(std::equal(begin(data_peer), end(data_peer), begin(text)));
304+
REQUIRE(text_peer == text);
309305
boost::system::error_code ec{};
310306
is_text = http::async_ws_read(peer, data_peer, yield[ec]);
311307
REQUIRE(ec == http::ws_going_away);
@@ -364,13 +360,11 @@ TEST_SUITE("[ASYNC]")
364360
http::async_ws_read(client, data_client, [&](boost::system::error_code ec, bool is_text) {
365361
REQUIRE(!bool(ec));
366362
REQUIRE(!is_text);
367-
REQUIRE(data_client.size() == data.size());
368-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(data)));
369-
http::async_ws_read(client, data_client, [&](boost::system::error_code ec, bool is_text) {
363+
REQUIRE(data_client == data);
364+
http::async_ws_read(client, text_client, [&](boost::system::error_code ec, bool is_text) {
370365
REQUIRE(!bool(ec));
371366
REQUIRE(is_text);
372-
REQUIRE(data_client.size() == text.size());
373-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(text)));
367+
REQUIRE(text_client == text);
374368
http::async_ws_read(client, data_client, [&](boost::system::error_code ec, bool is_text) {
375369
REQUIRE(ec == http::ws_going_away);
376370
});
@@ -410,12 +404,10 @@ TEST_SUITE("[ASYNC]")
410404
co_await http::async_ws_handshake(client, "localhost", "/ws");
411405
is_text = co_await http::async_ws_read(client, data_client);
412406
REQUIRE(!is_text);
413-
REQUIRE(data_client.size() == data.size());
414-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(data)));
415-
is_text = co_await http::async_ws_read(client, data_client);
407+
REQUIRE(data_client == data);
408+
is_text = co_await http::async_ws_read(client, text_client);
416409
REQUIRE(is_text);
417-
REQUIRE(data_client.size() == text.size());
418-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(text)));
410+
REQUIRE(text_client == text);
419411
auto [ec, is_text2] = co_await http::async_ws_read(client, data_client, as_tuple(deferred));
420412
REQUIRE(ec == http::ws_going_away);
421413
};
@@ -452,12 +444,10 @@ TEST_SUITE("[ASYNC]")
452444
http::async_ws_handshake(client, "localhost", "/ws", yield);
453445
is_text = http::async_ws_read(client, data_client, yield);
454446
REQUIRE(!is_text);
455-
REQUIRE(data_client.size() == data.size());
456-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(data)));
457-
is_text = http::async_ws_read(client, data_client, yield);
447+
REQUIRE(data_client == data);
448+
is_text = http::async_ws_read(client, text_client, yield);
458449
REQUIRE(is_text);
459-
REQUIRE(data_client.size() == text.size());
460-
REQUIRE(std::equal(begin(data_client), end(data_client), begin(text)));
450+
REQUIRE(text_client == text);
461451
boost::system::error_code ec{};
462452
is_text = http::async_ws_read(client, data_client, yield[ec]);
463453
REQUIRE(ec == http::ws_going_away);

src/http.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,38 @@ namespace http
811811
return ret;
812812
}
813813

814+
//----------------------------------------------------------------------------------------------------------------
815+
816+
void dynamic_buffer::clear()
817+
{
818+
clear_(ptr_);
819+
}
820+
821+
size_t dynamic_buffer::size() const
822+
{
823+
return size_(ptr_);
824+
}
825+
826+
void dynamic_buffer::resize(size_t n)
827+
{
828+
resize_(ptr_, n);
829+
}
830+
831+
void dynamic_buffer::append(const char* data, size_t ndata)
832+
{
833+
append_(ptr_, data, ndata);
834+
}
835+
836+
void* dynamic_buffer::data()
837+
{
838+
return data_(ptr_);
839+
}
840+
841+
boost::asio::const_buffer dynamic_buffer::buffer()
842+
{
843+
return boost::asio::const_buffer(data(), size());
844+
}
845+
814846
//----------------------------------------------------------------------------------------------------------------
815847

816848
static char from_hex(char ch) {return std::isdigit(ch) ? ch - '0' : std::tolower(ch) - 'a' + 10;}
@@ -1417,7 +1449,7 @@ namespace http
14171449

14181450
//----------------------------------------------------------------------------------------------------------------
14191451

1420-
bool websocket_parser::parse(std::vector<char>& msg, std::string& buf, std::error_code& ec)
1452+
bool websocket_parser::parse(dynamic_buffer msg, std::string& buf, std::error_code& ec)
14211453
{
14221454
while (!buf.empty() && !ec && state != done)
14231455
{
@@ -1538,7 +1570,7 @@ namespace http
15381570
}
15391571

15401572
// Add to message
1541-
msg.insert(end(msg), begin(buf), begin(buf) + paylen);
1573+
msg.append(&buf[0], paylen);
15421574
buf.erase(begin(buf), begin(buf) + paylen);
15431575
state = is_last ? done : header_frame;
15441576
}

src/http.h

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,43 @@ namespace http
519519
std::string base64_encode(const size_t ndata, const uint8_t* data);
520520
std::vector<uint8_t> base64_decode(std::string_view data);
521521

522+
//----------------------------------------------------------------------------------------------------------------
523+
524+
class dynamic_buffer
525+
{
526+
private:
527+
void* ptr_ = nullptr;
528+
void (*clear_)(void*) = nullptr;
529+
void (*resize_)(void*, size_t) = nullptr;
530+
size_t (*size_)(const void*) = nullptr;
531+
void* (*data_)(void*) = nullptr;
532+
void (*append_)(void*, const char*, size_t) = nullptr;
533+
534+
public:
535+
dynamic_buffer() = delete;
536+
537+
template<class T, std::enable_if_t<!std::is_same_v<T, dynamic_buffer>, int> = 0>
538+
dynamic_buffer(T& buf) noexcept
539+
: ptr_{&buf},
540+
clear_{[](void* self) {reinterpret_cast<T*>(self)->clear();}},
541+
resize_{[](void* self, size_t n) {reinterpret_cast<T*>(self)->resize(n);}},
542+
size_{[](const void* self) { return reinterpret_cast<const T*>(self)->size();}},
543+
data_{[](void* self) -> void* { return reinterpret_cast<T*>(self)->data();}},
544+
append_{[](void* self, const char* data, size_t ndata){
545+
T& me = *reinterpret_cast<T*>(self);
546+
me.insert(end(me), data, data + ndata);
547+
}}
548+
{
549+
}
550+
551+
void clear();
552+
size_t size() const;
553+
void resize(size_t n);
554+
void* data();
555+
auto buffer() -> boost::asio::const_buffer;
556+
void append(const char* data, size_t ndata);
557+
};
558+
522559
//----------------------------------------------------------------------------------------------------------------
523560

524561
struct query_param
@@ -620,7 +657,7 @@ namespace http
620657
enum {header_frame, header_extra, body, done} state{header_frame};
621658

622659
public:
623-
bool parse(std::vector<char>& msg, std::string& buf, std::error_code& ec);
660+
bool parse(dynamic_buffer msg, std::string& buf, std::error_code& ec);
624661
websocket_opcode get_opcode() const;
625662
bool is_server() const;
626663
};

0 commit comments

Comments
 (0)