diff --git a/Makefile b/Makefile index cbe75f78..e5225ed8 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ exec_prefix = $(prefix) libdir = $(exec_prefix)/lib #CXX = /opt/gcc-10.2.0/bin/g++-10.2.0 -VPATH = ./include/aedis/ +VPATH = ./src/ CPPFLAGS = CPPFLAGS += -std=c++20 -Wall #-Werror @@ -21,7 +21,7 @@ CPPFLAGS += -D BOOST_ASIO_NO_DEPRECATED CPPFLAGS += -D BOOST_ASIO_NO_TS_EXECUTORS CPPFLAGS += -g -#CPPFLAGS += -fsanitize=address +CPPFLAGS += -fsanitize=address CPPFLAGS += -O0 LDFLAGS += -pthread @@ -34,16 +34,12 @@ examples += async_low_level tests = tests += general -objs = -objs += response_buffers.o -objs += connection.o -objs += command.o -objs += type.o +aedis_obj = +aedis_obj += aedis.o remove = -remove += aedis.a -remove += $(objs) remove += $(examples) +remove += $(aedis_obj) remove += $(tests) remove += $(addprefix examples/, $(addsuffix .o, $(examples))) remove += $(addsuffix .o, $(tests)) @@ -58,14 +54,11 @@ Makefile.dep: -include Makefile.dep -aedis.a: $(objs) - ar rsv $@ $^ +$(examples): % : examples/%.o $(aedis_obj) + $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) $(aedis_obj) -$(examples): % : examples/%.o aedis.a - $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) aedis.a - -$(tests): % : tests/%.cpp aedis.a - $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) aedis.a +$(tests): % : tests/%.cpp $(aedis_obj) + $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) $(aedis_obj) .PHONY: check check: $(tests) @@ -73,12 +66,10 @@ check: $(tests) .PHONY: install install: - install --mode=444 -D include/aedis/*.hpp --target-directory $(incdir) - install --mode=444 -D aedis.a --target-directory $(libdir) + install --mode=444 -D include/aedis/* --target-directory $(incdir) uninstall: rm -rf $(incdir) - rm -rf $(libdir)/aedis.a .PHONY: clean clean: diff --git a/examples/async_basic.cpp b/examples/async_basic.cpp index edb7ad27..9f9d7736 100644 --- a/examples/async_basic.cpp +++ b/examples/async_basic.cpp @@ -40,10 +40,8 @@ public: int main() { net::io_context ioc {1}; - net::ip::tcp::resolver resolver{ioc}; - auto const results = resolver.resolve("127.0.0.1", "6379"); auto conn = std::make_shared(ioc); receiver recv{conn}; - conn->start(recv, results); + conn->start(recv); ioc.run(); } diff --git a/include/aedis/aedis.hpp b/include/aedis/aedis.hpp index 22e70620..344f5630 100644 --- a/include/aedis/aedis.hpp +++ b/include/aedis/aedis.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/aedis/command.hpp b/include/aedis/command.hpp index 821b3443..93236218 100644 --- a/include/aedis/command.hpp +++ b/include/aedis/command.hpp @@ -73,6 +73,7 @@ enum class command , none }; +char const* to_string(command c); std::ostream& operator<<(std::ostream& os, command c); } // aedis diff --git a/include/aedis/command.cpp b/include/aedis/command.ipp similarity index 100% rename from include/aedis/command.cpp rename to include/aedis/command.ipp diff --git a/include/aedis/connection.hpp b/include/aedis/connection.hpp index 4a39f1d6..84849ed5 100644 --- a/include/aedis/connection.hpp +++ b/include/aedis/connection.hpp @@ -19,6 +19,12 @@ namespace aedis { class connection : public std::enable_shared_from_this { +public: + struct config { + std::string host; + std::string port; + }; + private: net::steady_timer timer_; net::ip::tcp::socket socket_; @@ -26,27 +32,23 @@ private: resp::response_buffers resps_; request_queue reqs_; bool reconnect_ = false; + config conf_; void reset(); - - net::awaitable - worker_coro( - receiver_base& recv, - boost::asio::ip::tcp::resolver::results_type const& results); + net::awaitable worker_coro(receiver_base& recv); public: - connection(net::io_context& ioc); + connection( + net::io_context& ioc, + config const& conf = config {"127.0.0.1", "6379"}); - void - start( - receiver_base& recv, - boost::asio::ip::tcp::resolver::results_type const& results); + void start(receiver_base& recv); template void send(Filler filler) { queue_writer(reqs_, filler, timer_); } - void enable_reconnect() { reconnect_ = false; } + void enable_reconnect() noexcept; }; } // aedis diff --git a/include/aedis/connection.cpp b/include/aedis/connection.ipp similarity index 76% rename from include/aedis/connection.cpp rename to include/aedis/connection.ipp index 75e70aa1..5f9aae19 100644 --- a/include/aedis/connection.cpp +++ b/include/aedis/connection.ipp @@ -11,9 +11,10 @@ namespace aedis { -connection::connection(net::io_context& ioc) +connection::connection(net::io_context& ioc, config const& conf) : timer_{ioc} , socket_{ioc} +, conf_{conf} { reqs_.push({}); reqs_.front().req.hello(); @@ -27,14 +28,13 @@ void connection::reset() reqs_.front().req.hello(); } - -net::awaitable -connection::worker_coro( - receiver_base& recv, - boost::asio::ip::tcp::resolver::results_type const& results) +net::awaitable connection::worker_coro(receiver_base& recv) { auto ex = co_await net::this_coro::executor; + net::ip::tcp::resolver resolver{ex}; + auto const res = resolver.resolve(conf_.host, conf_.port); + net::steady_timer timer {ex}; std::chrono::seconds wait_interval {1}; @@ -42,7 +42,7 @@ connection::worker_coro( do { co_await async_connect( socket_, - results, + res, net::redirect_error(net::use_awaitable, ec)); if (ec) { @@ -69,16 +69,18 @@ connection::worker_coro( } while (reconnect_); } -void -connection::start( - receiver_base& recv, - boost::asio::ip::tcp::resolver::results_type const& results) +void connection::start(receiver_base& recv) { auto self = this->shared_from_this(); net::co_spawn( socket_.get_executor(), - [self, &recv, &results] () mutable { return self->worker_coro(recv, results); }, + [self, &recv] () mutable { return self->worker_coro(recv); }, net::detached); } +void connection::enable_reconnect() noexcept +{ + reconnect_ = false; +} + } // aedis diff --git a/include/aedis/parser.hpp b/include/aedis/parser.hpp index 245926f3..729bedbf 100644 --- a/include/aedis/parser.hpp +++ b/include/aedis/parser.hpp @@ -7,217 +7,56 @@ #pragma once -#include -#include -#include -#include -#include -#include +#include -#include "type.hpp" +#include "response_base.hpp" namespace aedis { namespace resp { -// Converts a decimal number in ascii format to an integer. -inline -long long length(char const* p) -{ - long long len = 0; - while (*p != '\r') { - len = (10 * len) + (*p - '0'); - p++; - } - return len; -} - -enum class bulk_type -{ blob_error -, verbatim_string -, blob_string -, streamed_string_part -, none -}; - -template class parser { -public: private: - Response* res_; + enum class bulk_type + { blob_error + , verbatim_string + , blob_string + , streamed_string_part + , none + }; + + response_base* res_; int depth_; int sizes_[6]; // Streaming will require a bigger integer. bulk_type bulk_; int bulk_length_; - void init(Response* res) - { - res_ = res; - depth_ = 0; - sizes_[0] = 2; - sizes_[1] = 1; - sizes_[2] = 1; - sizes_[3] = 1; - sizes_[4] = 1; - sizes_[5] = 1; - sizes_[6] = 1; - bulk_ = bulk_type::none; - bulk_length_ = std::numeric_limits::max(); - } - - auto on_array_impl(char const* data, int m = 1) - { - auto const l = length(data + 1); - if (l == 0) { - --sizes_[depth_]; - return l; - } - - auto const size = m * l; - sizes_[++depth_] = size; - return size; - } - - void on_array(char const* data) - { res_->select_array(on_array_impl(data, 1)); } - - void on_push(char const* data) - { res_->select_push(on_array_impl(data, 1)); } - - void on_set(char const* data) - { res_->select_set(on_array_impl(data, 1)); } - - void on_map(char const* data) - { res_->select_map(on_array_impl(data, 2)); } - - void on_attribute(char const* data) - { res_->select_attribute(on_array_impl(data, 2)); } - - void on_null() - { - res_->on_null(); - --sizes_[depth_]; - } - - auto handle_simple_string(char const* data, std::size_t n) - { - --sizes_[depth_]; - return std::string_view {data + 1, n - 3}; - } - - void on_simple_string(char const* data, std::size_t n) - { res_->on_simple_string(handle_simple_string(data, n)); } - - void on_simple_error(char const* data, std::size_t n) - { res_->on_simple_error(handle_simple_string(data, n)); } - - void on_number(char const* data, std::size_t n) - { res_->on_number(handle_simple_string(data, n)); } - - void on_double(char const* data, std::size_t n) - { res_->on_double(handle_simple_string(data, n)); } - - void on_boolean(char const* data, std::size_t n) - { res_->on_bool(handle_simple_string(data, n)); } - - void on_big_number(char const* data, std::size_t n) - { res_->on_big_number(handle_simple_string(data, n)); } - - void on_bulk(bulk_type b, std::string_view s = {}) - { - switch (b) { - case bulk_type::blob_error: res_->on_blob_error(s); break; - case bulk_type::verbatim_string: res_->on_verbatim_string(s); break; - case bulk_type::blob_string: res_->on_blob_string(s); break; - case bulk_type::streamed_string_part: - { - if (std::empty(s)) { - sizes_[depth_] = 1; - } else { - res_->on_streamed_string_part(s); - } - } break; - default: assert(false); - } - - --sizes_[depth_]; - } - - auto on_blob_error_impl(char const* data, bulk_type b) - { - bulk_length_ = length(data + 1); - return b; - } - - auto on_streamed_string_size(char const* data) - { return on_blob_error_impl(data, bulk_type::streamed_string_part); } - - auto on_blob_error(char const* data) - { return on_blob_error_impl(data, bulk_type::blob_error); } - - auto on_verbatim_string(char const* data) - { return on_blob_error_impl(data, bulk_type::verbatim_string); } - - auto on_blob_string(char const* data) - { - if (*(data + 1) == '?') { - sizes_[++depth_] = std::numeric_limits::max(); - return bulk_type::none; - } - - return on_blob_error_impl(data, bulk_type::blob_string); - } + void init(response_base* res); + long long on_array_impl(char const* data, int m = 1); + void on_array(char const* data) { res_->select_array(on_array_impl(data, 1)); } + void on_push(char const* data) { res_->select_push(on_array_impl(data, 1)); } + void on_set(char const* data) { res_->select_set(on_array_impl(data, 1)); } + void on_map(char const* data) { res_->select_map(on_array_impl(data, 2)); } + void on_attribute(char const* data) { res_->select_attribute(on_array_impl(data, 2)); } + void on_null(); + void on_simple_string(char const* data, std::size_t n) { res_->on_simple_string(handle_simple_string(data, n)); } + void on_simple_error(char const* data, std::size_t n) { res_->on_simple_error(handle_simple_string(data, n)); } + void on_number(char const* data, std::size_t n) { res_->on_number(handle_simple_string(data, n)); } + void on_double(char const* data, std::size_t n) { res_->on_double(handle_simple_string(data, n)); } + void on_boolean(char const* data, std::size_t n) { res_->on_bool(handle_simple_string(data, n)); } + void on_big_number(char const* data, std::size_t n) { res_->on_big_number(handle_simple_string(data, n)); } + void on_bulk(bulk_type b, std::string_view s = {}); + bulk_type on_blob_error_impl(char const* data, bulk_type b); + bulk_type on_streamed_string_size(char const* data) { return on_blob_error_impl(data, bulk_type::streamed_string_part); } + bulk_type on_blob_error(char const* data) { return on_blob_error_impl(data, bulk_type::blob_error); } + bulk_type on_verbatim_string(char const* data) { return on_blob_error_impl(data, bulk_type::verbatim_string); } + bulk_type on_blob_string(char const* data); + std::string_view handle_simple_string(char const* data, std::size_t n); public: - parser(Response* res) - { init(res); } - - std::size_t advance(char const* data, std::size_t n) - { - auto next = bulk_type::none; - if (bulk_ != bulk_type::none) { - n = bulk_length_ + 2; - on_bulk(bulk_, {data, (std::size_t)bulk_length_}); - } else { - if (sizes_[depth_] != 0) { - switch (*data) { - case '!': next = on_blob_error(data); break; - case '=': next = on_verbatim_string(data); break; - case '$': next = on_blob_string(data); break; - case ';': next = on_streamed_string_size(data); break; - case '-': on_simple_error(data, n); break; - case ':': on_number(data, n); break; - case ',': on_double(data, n); break; - case '#': on_boolean(data, n); break; - case '(': on_big_number(data, n); break; - case '+': on_simple_string(data, n); break; - case '_': on_null(); break; - case '>': on_push(data); break; - case '~': on_set(data); break; - case '*': on_array(data); break; - case '|': on_attribute(data); break; - case '%': on_map(data); break; - default: assert(false); - } - } else { - } - } - - while (sizes_[depth_] == 0) { - res_->pop(); - --sizes_[--depth_]; - } - - bulk_ = next; - return n; - } - - auto done() const noexcept - { return depth_ == 0 && bulk_ == bulk_type::none; } - - auto bulk() const noexcept - { return bulk_; } - - auto bulk_length() const noexcept - { return bulk_length_; } + parser(response_base* res); + std::size_t advance(char const* data, std::size_t n); + auto done() const noexcept { return depth_ == 0 && bulk_ == bulk_type::none; } + auto bulk() const noexcept { return bulk_; } + auto bulk_length() const noexcept { return bulk_length_; } }; } // resp diff --git a/include/aedis/parser.ipp b/include/aedis/parser.ipp new file mode 100644 index 00000000..045b45f5 --- /dev/null +++ b/include/aedis/parser.ipp @@ -0,0 +1,151 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "parser.hpp" + +//#include +//#include +//#include +//#include +//#include +//#include + +namespace aedis { namespace resp { + +// Converts a decimal number in ascii format to an integer. +long long length(char const* p) +{ + long long len = 0; + while (*p != '\r') { + len = (10 * len) + (*p - '0'); + p++; + } + return len; +} + +parser::parser(response_base* res) + { init(res); } + +void parser::init(response_base* res) +{ + res_ = res; + depth_ = 0; + sizes_[0] = 2; + sizes_[1] = 1; + sizes_[2] = 1; + sizes_[3] = 1; + sizes_[4] = 1; + sizes_[5] = 1; + sizes_[6] = 1; + bulk_ = bulk_type::none; + bulk_length_ = std::numeric_limits::max(); +} + +long long parser::on_array_impl(char const* data, int m) +{ + auto const l = length(data + 1); + if (l == 0) { + --sizes_[depth_]; + return l; + } + + auto const size = m * l; + sizes_[++depth_] = size; + return size; +} + +void parser::on_null() +{ + res_->on_null(); + --sizes_[depth_]; +} + +std::string_view +parser::handle_simple_string(char const* data, std::size_t n) +{ + --sizes_[depth_]; + return std::string_view {data + 1, n - 3}; +} + +void parser::on_bulk(parser::bulk_type b, std::string_view s) +{ + switch (b) { + case bulk_type::blob_error: res_->on_blob_error(s); break; + case bulk_type::verbatim_string: res_->on_verbatim_string(s); break; + case bulk_type::blob_string: res_->on_blob_string(s); break; + case bulk_type::streamed_string_part: + { + if (std::empty(s)) { + sizes_[depth_] = 1; + } else { + res_->on_streamed_string_part(s); + } + } break; + default: assert(false); + } + + --sizes_[depth_]; +} + +parser::bulk_type parser::on_blob_error_impl(char const* data, parser::bulk_type b) +{ + bulk_length_ = length(data + 1); + return b; +} + +parser::bulk_type parser::on_blob_string(char const* data) +{ + if (*(data + 1) == '?') { + sizes_[++depth_] = std::numeric_limits::max(); + return bulk_type::none; + } + + return on_blob_error_impl(data, bulk_type::blob_string); +} + +std::size_t parser::advance(char const* data, std::size_t n) +{ + auto next = bulk_type::none; + if (bulk_ != bulk_type::none) { + n = bulk_length_ + 2; + on_bulk(bulk_, {data, (std::size_t)bulk_length_}); + } else { + if (sizes_[depth_] != 0) { + switch (*data) { + case '!': next = on_blob_error(data); break; + case '=': next = on_verbatim_string(data); break; + case '$': next = on_blob_string(data); break; + case ';': next = on_streamed_string_size(data); break; + case '-': on_simple_error(data, n); break; + case ':': on_number(data, n); break; + case ',': on_double(data, n); break; + case '#': on_boolean(data, n); break; + case '(': on_big_number(data, n); break; + case '+': on_simple_string(data, n); break; + case '_': on_null(); break; + case '>': on_push(data); break; + case '~': on_set(data); break; + case '*': on_array(data); break; + case '|': on_attribute(data); break; + case '%': on_map(data); break; + default: assert(false); + } + } else { + } + } + + while (sizes_[depth_] == 0) { + res_->pop(); + --sizes_[--depth_]; + } + + bulk_ = next; + return n; +} + +} // resp +} // aedis diff --git a/include/aedis/read.hpp b/include/aedis/read.hpp index c8be3496..1891253d 100644 --- a/include/aedis/read.hpp +++ b/include/aedis/read.hpp @@ -25,6 +25,7 @@ #include "type.hpp" #include "parser.hpp" #include "request.hpp" +#include "response_base.hpp" #include "response_buffers.hpp" namespace aedis { namespace resp { @@ -32,19 +33,16 @@ namespace aedis { namespace resp { // The parser supports up to 5 levels of nested structures. The first // element in the sizes stack is a sentinel and must be different from // 1. -template < - class AsyncReadStream, - class Storage, - class Response> +template class parse_op { private: AsyncReadStream& stream_; Storage* buf_ = nullptr; - parser parser_; + parser parser_; int start_ = 1; public: - parse_op(AsyncReadStream& stream, Storage* buf, Response* res) + parse_op(AsyncReadStream& stream, Storage* buf, resp::response_base* res) : stream_ {stream} , buf_ {buf} , parser_ {res} @@ -57,7 +55,7 @@ public: { switch (start_) { for (;;) { - if (parser_.bulk() == bulk_type::none) { + if (parser_.bulk() == parser::bulk_type::none) { case 1: start_ = 0; net::async_read_until( @@ -105,20 +103,17 @@ public: } }; -template < - class SyncReadStream, - class Storage, - class Response> +template auto read( SyncReadStream& stream, Storage& buf, - Response& res, + resp::response_base& res, boost::system::error_code& ec) { - parser p {&res}; + parser p {&res}; std::size_t n = 0; do { - if (p.bulk() == bulk_type::none) { + if (p.bulk() == parser::bulk_type::none) { n = net::read_until(stream, net::dynamic_buffer(buf), "\r\n", ec); if (ec || n < 3) return n; @@ -142,15 +137,12 @@ auto read( return n; } -template< - class SyncReadStream, - class Storage, - class Response> +template std::size_t read( SyncReadStream& stream, Storage& buf, - Response& res) + resp::response_base& res) { boost::system::error_code ec; auto const n = read(stream, buf, res, ec); @@ -164,28 +156,25 @@ read( template < class AsyncReadStream, class Storage, - class Response, class CompletionToken = net::default_completion_token_t > auto async_read( AsyncReadStream& stream, Storage& buffer, - Response& res, + resp::response_base& res, CompletionToken&& token = net::default_completion_token_t{}) { return net::async_compose < CompletionToken , void(boost::system::error_code) - >(parse_op {stream, &buffer, &res}, + >(parse_op {stream, &buffer, &res}, token, stream); } -template < - class AsyncReadStream, - class Storage> +template class type_op { private: AsyncReadStream& stream_; @@ -255,19 +244,7 @@ struct queue_elem { using request_queue = std::queue; // Returns true when a new request can be sent to redis. -inline -bool queue_pop(request_queue& reqs) -{ - assert(!std::empty(reqs)); - assert(!std::empty(reqs.front().req.cmds)); - reqs.front().req.cmds.pop(); - if (std::empty(reqs.front().req.cmds)) { - reqs.pop(); - return true; - } - - return false; -} +bool queue_pop(request_queue& reqs); template < class AsyncReadWriteStream, diff --git a/include/aedis/read.ipp b/include/aedis/read.ipp new file mode 100644 index 00000000..7d66c05e --- /dev/null +++ b/include/aedis/read.ipp @@ -0,0 +1,26 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "read.hpp" + +namespace aedis { + +bool queue_pop(request_queue& reqs) +{ + assert(!std::empty(reqs)); + assert(!std::empty(reqs.front().req.cmds)); + + reqs.front().req.cmds.pop(); + if (std::empty(reqs.front().req.cmds)) { + reqs.pop(); + return true; + } + + return false; +} + +} // aedis diff --git a/include/aedis/receiver_base.hpp b/include/aedis/receiver_base.hpp index b68dacc3..35e4139a 100644 --- a/include/aedis/receiver_base.hpp +++ b/include/aedis/receiver_base.hpp @@ -12,7 +12,7 @@ #include "type.hpp" #include "utils.hpp" -#include "response.hpp" +#include "responses.hpp" #include "request.hpp" namespace aedis { diff --git a/include/aedis/response_base.hpp b/include/aedis/response_base.hpp new file mode 100644 index 00000000..509dcf1d --- /dev/null +++ b/include/aedis/response_base.hpp @@ -0,0 +1,57 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace aedis { namespace resp { + +class response_base { +protected: + virtual void on_simple_string_impl(std::string_view s) { throw std::runtime_error("on_simple_string_impl: Has not been overridden."); } + virtual void on_simple_error_impl(std::string_view s) { throw std::runtime_error("on_simple_error_impl: Has not been overridden."); } + virtual void on_number_impl(std::string_view s) { throw std::runtime_error("on_number_impl: Has not been overridden."); } + virtual void on_double_impl(std::string_view s) { throw std::runtime_error("on_double_impl: Has not been overridden."); } + virtual void on_null_impl() { throw std::runtime_error("on_null_impl: Has not been overridden."); } + virtual void on_bool_impl(std::string_view s) { throw std::runtime_error("on_bool_impl: Has not been overridden."); } + virtual void on_big_number_impl(std::string_view s) { throw std::runtime_error("on_big_number_impl: Has not been overridden."); } + virtual void on_verbatim_string_impl(std::string_view s = {}) { throw std::runtime_error("on_verbatim_string_impl: Has not been overridden."); } + virtual void on_blob_string_impl(std::string_view s = {}) { throw std::runtime_error("on_blob_string_impl: Has not been overridden."); } + virtual void on_blob_error_impl(std::string_view s = {}) { throw std::runtime_error("on_blob_error_impl: Has not been overridden."); } + virtual void on_streamed_string_part_impl(std::string_view s = {}) { throw std::runtime_error("on_streamed_string_part: Has not been overridden."); } + virtual void select_array_impl(int n) { throw std::runtime_error("select_array_impl: Has not been overridden."); } + virtual void select_set_impl(int n) { throw std::runtime_error("select_set_impl: Has not been overridden."); } + virtual void select_map_impl(int n) { throw std::runtime_error("select_map_impl: Has not been overridden."); } + virtual void select_push_impl(int n) { throw std::runtime_error("select_push_impl: Has not been overridden."); } + virtual void select_attribute_impl(int n) { throw std::runtime_error("select_attribute_impl: Has not been overridden."); } + +public: + virtual void pop() {} + void select_attribute(int n) { select_attribute_impl(n);} + void select_push(int n) { select_push_impl(n);} + void select_array(int n) { select_array_impl(n);} + void select_set(int n) { select_set_impl(n);} + void select_map(int n) { select_map_impl(n);} + void on_simple_error(std::string_view s) { on_simple_error_impl(s); } + void on_blob_error(std::string_view s = {}) { on_blob_error_impl(s); } + void on_null() { on_null_impl(); } + void on_simple_string(std::string_view s) { on_simple_string_impl(s); } + void on_number(std::string_view s) { on_number_impl(s); } + void on_double(std::string_view s) { on_double_impl(s); } + void on_bool(std::string_view s) { on_bool_impl(s); } + void on_big_number(std::string_view s) { on_big_number_impl(s); } + void on_verbatim_string(std::string_view s = {}) { on_verbatim_string_impl(s); } + void on_blob_string(std::string_view s = {}) { on_blob_string_impl(s); } + void on_streamed_string_part(std::string_view s = {}) { on_streamed_string_part_impl(s); } + virtual ~response_base() {} +}; + +} // resp +} // aedis + diff --git a/include/aedis/response_buffers.cpp b/include/aedis/response_buffers.ipp similarity index 100% rename from include/aedis/response_buffers.cpp rename to include/aedis/response_buffers.ipp diff --git a/include/aedis/response_types.hpp b/include/aedis/response_types.hpp index 5852cc3f..b0d552fb 100644 --- a/include/aedis/response_types.hpp +++ b/include/aedis/response_types.hpp @@ -7,7 +7,7 @@ #pragma once -#include "response.hpp" +#include "responses.hpp" namespace aedis { namespace resp { diff --git a/include/aedis/response.hpp b/include/aedis/responses.hpp similarity index 79% rename from include/aedis/response.hpp rename to include/aedis/responses.hpp index 67bc02be..4f4aa54a 100644 --- a/include/aedis/response.hpp +++ b/include/aedis/responses.hpp @@ -21,6 +21,7 @@ #include "type.hpp" #include "command.hpp" #include "resp_types.hpp" +#include "response_base.hpp" #include @@ -39,46 +40,6 @@ inline void from_string_view(std::string_view s, std::string& r) { r = s; } -class response_base { -protected: - virtual void on_simple_string_impl(std::string_view s) { throw std::runtime_error("on_simple_string_impl: Has not been overridden."); } - virtual void on_simple_error_impl(std::string_view s) { throw std::runtime_error("on_simple_error_impl: Has not been overridden."); } - virtual void on_number_impl(std::string_view s) { throw std::runtime_error("on_number_impl: Has not been overridden."); } - virtual void on_double_impl(std::string_view s) { throw std::runtime_error("on_double_impl: Has not been overridden."); } - virtual void on_null_impl() { throw std::runtime_error("on_null_impl: Has not been overridden."); } - virtual void on_bool_impl(std::string_view s) { throw std::runtime_error("on_bool_impl: Has not been overridden."); } - virtual void on_big_number_impl(std::string_view s) { throw std::runtime_error("on_big_number_impl: Has not been overridden."); } - virtual void on_verbatim_string_impl(std::string_view s = {}) { throw std::runtime_error("on_verbatim_string_impl: Has not been overridden."); } - virtual void on_blob_string_impl(std::string_view s = {}) { throw std::runtime_error("on_blob_string_impl: Has not been overridden."); } - virtual void on_blob_error_impl(std::string_view s = {}) { throw std::runtime_error("on_blob_error_impl: Has not been overridden."); } - virtual void on_streamed_string_part_impl(std::string_view s = {}) { throw std::runtime_error("on_streamed_string_part: Has not been overridden."); } - virtual void select_array_impl(int n) { throw std::runtime_error("select_array_impl: Has not been overridden."); } - virtual void select_set_impl(int n) { throw std::runtime_error("select_set_impl: Has not been overridden."); } - virtual void select_map_impl(int n) { throw std::runtime_error("select_map_impl: Has not been overridden."); } - virtual void select_push_impl(int n) { throw std::runtime_error("select_push_impl: Has not been overridden."); } - virtual void select_attribute_impl(int n) { throw std::runtime_error("select_attribute_impl: Has not been overridden."); } - -public: - virtual void pop() {} - void select_attribute(int n) { select_attribute_impl(n);} - void select_push(int n) { select_push_impl(n);} - void select_array(int n) { select_array_impl(n);} - void select_set(int n) { select_set_impl(n);} - void select_map(int n) { select_map_impl(n);} - void on_simple_error(std::string_view s) { on_simple_error_impl(s); } - void on_blob_error(std::string_view s = {}) { on_blob_error_impl(s); } - void on_null() { on_null_impl(); } - void on_simple_string(std::string_view s) { on_simple_string_impl(s); } - void on_number(std::string_view s) { on_number_impl(s); } - void on_double(std::string_view s) { on_double_impl(s); } - void on_bool(std::string_view s) { on_bool_impl(s); } - void on_big_number(std::string_view s) { on_big_number_impl(s); } - void on_verbatim_string(std::string_view s = {}) { on_verbatim_string_impl(s); } - void on_blob_string(std::string_view s = {}) { on_blob_string_impl(s); } - void on_streamed_string_part(std::string_view s = {}) { on_streamed_string_part_impl(s); } - virtual ~response_base() {} -}; - class response_ignore : public response_base { private: void on_simple_string_impl(std::string_view s) override {} diff --git a/include/aedis/src.hpp b/include/aedis/src.hpp new file mode 100644 index 00000000..bf67d5d3 --- /dev/null +++ b/include/aedis/src.hpp @@ -0,0 +1,15 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include diff --git a/include/aedis/type.cpp b/include/aedis/type.ipp similarity index 100% rename from include/aedis/type.cpp rename to include/aedis/type.ipp diff --git a/src/aedis.cpp b/src/aedis.cpp new file mode 100644 index 00000000..88ef7672 --- /dev/null +++ b/src/aedis.cpp @@ -0,0 +1 @@ +#include diff --git a/tests/general.cpp b/tests/general.cpp index c896d8b3..6888ec16 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -682,7 +682,7 @@ int main(int argc, char* argv[]) auto conn = std::make_shared(ioc); test_receiver recv{conn}; - conn->start(recv, results); + conn->start(recv); ioc.run(); }