Skip to content
Snippets Groups Projects
Commit 6e379f64 authored by Benny Baumann's avatar Benny Baumann
Browse files

chg: Make the connection_client class a template

parent ba885f32
No related branches found
No related tags found
1 merge request!1First unit tests
......@@ -13,7 +13,8 @@
namespace rmrf::net {
class connection_client : public std::enable_shared_from_this<connection_client> {
template<class client>
class connection_client : public std::enable_shared_from_this<client> {
public:
/**
* This function type accepts a reference to the incomming data string which it may not alter
......
......@@ -38,61 +38,4 @@ std::string::size_type default_eol_search(
return std::string::npos;
}
connection_line_buffer::connection_line_buffer(
std::shared_ptr<connection_client> c,
found_next_line_cb_t found_next_line_cb_,
std::string::size_type max_line_size,
eol_search_t search_lb
) :
search(search_lb),
client(c),
found_next_line_cb(found_next_line_cb_),
max(max_line_size),
data("")
{
this->client->set_incomming_data_callback(
[this](const std::string& data_in) {
conn_data_in_cb(data_in);
});
}
connection_line_buffer::connection_line_buffer(
std::shared_ptr<connection_client> c,
found_next_line_cb_t found_next_line_cb_,
std::string::size_type max_line_size
) :
connection_line_buffer{c, found_next_line_cb_, max_line_size, &default_eol_search}
{}
void connection_line_buffer::conn_data_in_cb(const std::string &data_in) {
// Iterate throug the incomming data as long as we find line breaks
for (std::string::size_type strpos = 0, nextpos = -1; strpos != std::string::npos; strpos = nextpos++) {
// Search for the next line break
nextpos = this->search(data_in, strpos);
// Advance, if the line would be empty
if (nextpos == strpos) {
nextpos = this->search(data_in, ++strpos);
}
if (nextpos == std::string::npos) {
// If we didn't find one we store the remaining data in the buffer
this->data += data_in.substr(strpos, data_in.length() - strpos);
break;
} else {
// If we find one we send the buffer plus the incomming data up to the line break to the callback
const std::string data_to_send = this->data + data_in.substr(strpos, nextpos - strpos);
this->found_next_line_cb(data_to_send, true);
// and clear the buffer
this->data = std::string("");
}
}
if (this->data.length() > this->max) {
this->found_next_line_cb(this->data, false);
this->data = std::string("");
}
}
}
......@@ -10,6 +10,7 @@
#include <functional>
#include <memory>
#include <string>
#include <sstream>
#include "net/connection_client.hpp"
......@@ -58,6 +59,7 @@ std::string::size_type default_eol_search(const std::string& data, std::string::
* @see rmrf::net::default_eol_search
* @see rmrf::net::eol_search_t
*/
template<class client_type>
class connection_line_buffer {
public:
/**
......@@ -72,10 +74,11 @@ public:
private:
const eol_search_t search;
std::shared_ptr<connection_client> client;
std::shared_ptr<connection_client<client_type>> client;
found_next_line_cb_t found_next_line_cb;
std::string::size_type max;
std::string data;
std::ostringstream data_buffer;
size_t buffer_length;
public:
/**
......@@ -86,7 +89,7 @@ public:
* @param max_line_size The maximum line length to aquire prior to collection abort and transmission of the incomplete line
* @param search_lb The callback to use for line break detection
*/
connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size, eol_search_t search_lb);
connection_line_buffer(std::shared_ptr<connection_client<client_type>> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size, eol_search_t search_lb);
/**
* This constructor creates a new buffer based on a given client, an input callback and the maximum line size.
......@@ -96,10 +99,81 @@ public:
* @param found_next_line_cb_ The callback to be called when a complete new line arrived
* @param max_line_size The maximum line length to aquire prior to collection abort and transmission of the incomplete line
*/
connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size);
connection_line_buffer(std::shared_ptr<connection_client<client_type>> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size);
private:
void conn_data_in_cb(const std::string& data_in);
void clear();
};
template <class client_type>
connection_line_buffer<client_type>::connection_line_buffer(
std::shared_ptr<connection_client<client_type>> c,
found_next_line_cb_t found_next_line_cb_,
std::string::size_type max_line_size,
eol_search_t search_lb
) :
search(search_lb),
client(c),
found_next_line_cb(found_next_line_cb_),
max(max_line_size),
data_buffer(std::ostringstream::ate),
buffer_length{0}
{
this->client->set_incomming_data_callback(
[this](const std::string& data_in) {
conn_data_in_cb(data_in);
});
}
template <class client_type>
connection_line_buffer<client_type>::connection_line_buffer(
std::shared_ptr<connection_client<client_type>> c,
found_next_line_cb_t found_next_line_cb_,
std::string::size_type max_line_size
) :
connection_line_buffer{c, found_next_line_cb_, max_line_size, &default_eol_search}
{}
template <class client_type>
void connection_line_buffer<client_type>::clear() {
this->data_buffer.str(std::string());
this->data_buffer.clear();
this->buffer_length = 0;
}
template <class client_type>
void connection_line_buffer<client_type>::conn_data_in_cb(const std::string& data_in) {
// Iterate throug the incomming data as long as we find line breaks
for (std::string::size_type strpos = 0, nextpos = -1; strpos != std::string::npos; strpos = nextpos++) {
// Search for the next line break
nextpos = this->search(data_in, strpos);
// Advance, if the line would be empty
if (nextpos == strpos) {
nextpos = this->search(data_in, ++strpos);
}
if (nextpos == std::string::npos) {
// If we didn't find one we store the remaining data in the buffer
const auto length = data_in.length() - strpos;
this->data_buffer << data_in.substr(strpos, length);
this->buffer_length += length;
break;
} else {
// If we find one we send the buffer plus the incomming data up to the line break to the callback
const std::string data_to_send = this->data_buffer.str() + data_in.substr(strpos, nextpos - strpos);
this->found_next_line_cb(data_to_send, true);
// and clear the buffer
this->clear();
}
}
if (this->buffer_length > this->max) {
this->found_next_line_cb(this->data_buffer.str(), false);
this->clear();
}
}
}
......@@ -32,7 +32,7 @@ enum class exit_status_t : uint16_t {
* @author doralitze BenBe
* @brief A raw TCP client.
*/
class tcp_client : public connection_client, std::enable_shared_from_this<tcp_client> {
class tcp_client : public connection_client<tcp_client> {
public:
/**
* A callback for the destructor must match this definition.
......
......@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(Default_EoL_Search_Test) {
BOOST_AUTO_TEST_CASE(Connection_Line_Buffer_Test) {
mut_send_stage = 0;
auto ll_client = std::make_shared<loopback_connection_client>(mut_send_data_cb, false);
connection_line_buffer clb(ll_client, next_line_cb, 150);
connection_line_buffer<loopback_connection_client> clb(ll_client, next_line_cb, 150);
if constexpr (display_dbg_msg) std::cout << "Testing legit lines" << std::endl;
......
......@@ -10,9 +10,9 @@ namespace rmrf::test {
/**
* Use this class to mock a connection client.
*/
class loopback_connection_client : public rmrf::net::connection_client {
class loopback_connection_client : public rmrf::net::connection_client<loopback_connection_client> {
private:
const rmrf::net::connection_client::incomming_data_cb send_data_cb;
const incomming_data_cb send_data_cb;
std::vector<std::string> data_archive;
const bool echo_data_transfer;
......@@ -22,10 +22,10 @@ public:
* send data.
*/
loopback_connection_client(
rmrf::net::connection_client::incomming_data_cb send_data_cb_,
const incomming_data_cb& send_data_cb_,
bool echo_data
) :
rmrf::net::connection_client{},
rmrf::net::connection_client<loopback_connection_client>{},
send_data_cb(send_data_cb_),
data_archive{},
echo_data_transfer(echo_data)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment