diff --git a/Makefile.am b/Makefile.am index eef62f5d..b2b25462 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,15 +42,15 @@ libaedis_a_SOURCES += $(top_srcdir)/src/aedis.cpp libaedis_a_CPPFLAGS = $(MY_CPPFLAGS) noinst_PROGRAMS = -noinst_PROGRAMS += async_basic -async_basic_SOURCES = $(top_srcdir)/examples/async_basic.cpp -async_basic_CPPFLAGS = $(MY_CPPFLAGS) -async_basic_LDADD = $(MY_LDADD) +noinst_PROGRAMS += pubsub +pubsub_SOURCES = $(top_srcdir)/examples/pubsub.cpp +pubsub_CPPFLAGS = $(MY_CPPFLAGS) +pubsub_LDADD = $(MY_LDADD) -noinst_PROGRAMS += hello -hello_SOURCES = $(top_srcdir)/examples/hello.cpp -hello_CPPFLAGS = $(MY_CPPFLAGS) -hello_LDADD = $(MY_LDADD) +noinst_PROGRAMS += ping +ping_SOURCES = $(top_srcdir)/examples/ping.cpp +ping_CPPFLAGS = $(MY_CPPFLAGS) +ping_LDADD = $(MY_LDADD) noinst_PROGRAMS += test test_SOURCES = $(top_srcdir)/tests/general.cpp diff --git a/examples/hello.cpp b/examples/ping.cpp similarity index 59% rename from examples/hello.cpp rename to examples/ping.cpp index 6276a9de..bea495d3 100644 --- a/examples/hello.cpp +++ b/examples/ping.cpp @@ -9,31 +9,21 @@ #include +#include "types.hpp" +#include "utils.ipp" + /** A very simple example showing how to * * 1. Connect to the redis server. - * 2. Send a ping - * 3. and quit. + * 2. Send a ping. + * 3. Wait for a pong and quit. * - * Notice that in this example we are sending all commands in the same request - * instead of waiting the response of each command. + * Notice that in this example we are sending all commands in the + * same request instead of waiting the response of each command. */ using namespace aedis; -using tcp_socket = net::use_awaitable_t<>::as_default_on_t; -using tcp_resolver = net::use_awaitable_t<>::as_default_on_t; - -net::awaitable make_connection() -{ - auto ex = co_await net::this_coro::executor; - tcp_resolver resolver{ex}; - auto const res = co_await resolver.async_resolve("127.0.0.1", "6379"); - tcp_socket socket{ex}; - co_await net::async_connect(socket, res); - co_return std::move(socket); -} - net::awaitable ping() { auto socket = co_await make_connection(); @@ -48,7 +38,10 @@ net::awaitable ping() for (;;) { resp3::response resp; co_await cs.async_consume(socket, requests, resp); - std::cout << requests.front().elements.front() << "\n" << resp << std::endl; + + std::cout + << requests.front().elements.front() << "\n" + << resp << std::endl; } } diff --git a/examples/async_basic.cpp b/examples/pubsub.cpp similarity index 78% rename from examples/async_basic.cpp rename to examples/pubsub.cpp index bd4ea284..b54d1f0f 100644 --- a/examples/async_basic.cpp +++ b/examples/pubsub.cpp @@ -9,25 +9,19 @@ #include -using namespace aedis; +#include "utils.ipp" -using tcp_socket = net::use_awaitable_t<>::as_default_on_t; -using tcp_resolver = net::use_awaitable_t<>::as_default_on_t; +using namespace aedis; net::awaitable example() { - auto ex = co_await net::this_coro::executor; - tcp_resolver resolver{ex}; - auto const res = co_await resolver.async_resolve("127.0.0.1", "6379"); - tcp_socket socket{ex}; - co_await net::async_connect(socket, res); + auto socket = co_await make_connection(); std::queue requests; requests.push({}); requests.back().hello(); resp3::consumer cs; - for (;;) { resp3::response resp; co_await cs.async_consume(socket, requests, resp); diff --git a/examples/types.hpp b/examples/types.hpp new file mode 100644 index 00000000..79930427 --- /dev/null +++ b/examples/types.hpp @@ -0,0 +1,13 @@ +/* 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 + +using tcp_socket = aedis::net::use_awaitable_t<>::as_default_on_t; +using tcp_resolver = aedis::net::use_awaitable_t<>::as_default_on_t; diff --git a/examples/utils.hpp b/examples/utils.ipp similarity index 55% rename from examples/utils.hpp rename to examples/utils.ipp index cd57d6ea..14fa648d 100644 --- a/examples/utils.hpp +++ b/examples/utils.ipp @@ -5,35 +5,22 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#pragma once - #include -#include "type.hpp" -#include "command.hpp" -#include "response.hpp" +#include -namespace aedis { +#include "types.hpp" -template -void print(Iter begin, Iter end, char const* p) +aedis::net::awaitable make_connection() { - if (p) - std::cout << p << ": "; - for (; begin != end; ++begin) - std::cout << *begin << " "; - std::cout << std::endl; + auto ex = co_await aedis::net::this_coro::executor; + tcp_resolver resolver{ex}; + auto const res = co_await resolver.async_resolve("127.0.0.1", "6379"); + tcp_socket socket{ex}; + co_await aedis::net::async_connect(socket, res); + co_return std::move(socket); } -template -void print(Range const& v, char const* p = nullptr) -{ - using std::cbegin; - using std::cend; - print(cbegin(v), cend(v), p); -} - -inline void print_command_raw(std::string const& data, int n) { for (int i = 0; i < n; ++i) { @@ -49,4 +36,3 @@ void print_command_raw(std::string const& data, int n) } } -} // aedis diff --git a/include/aedis/resp3/impl/request.ipp b/include/aedis/resp3/impl/request.ipp index 9de38bf9..ffccce1b 100644 --- a/include/aedis/resp3/impl/request.ipp +++ b/include/aedis/resp3/impl/request.ipp @@ -25,11 +25,11 @@ bool prepare_next(std::queue& reqs) return false; } -std::ostream& operator<<(std::ostream& os, request::element const& r) +std::ostream& operator<<(std::ostream& os, request::element const& e) { - os << r.cmd; - if (!std::empty(r.key)) - os << "(" << r.key << ")"; + os << e.cmd; + if (!std::empty(e.key)) + os << "(" << e.key << ")"; return os; } diff --git a/include/aedis/resp3/impl/response.ipp b/include/aedis/resp3/impl/response.ipp index 3e49c0cb..fbcf461d 100644 --- a/include/aedis/resp3/impl/response.ipp +++ b/include/aedis/resp3/impl/response.ipp @@ -28,22 +28,54 @@ bool operator==(response::node const& a, response::node const& b) std::ostream& operator<<(std::ostream& os, response::node const& o) { std::string res; - res += std::to_string(o.depth); - res += '\t'; - res += to_string(o.data_type); - res += '\t'; - res += o.data; + o.dump(response::node::dump_format::clean, 3, res); os << res; return os; } std::ostream& operator<<(std::ostream& os, response const& r) { - for (auto const& n : r.data_) - os << n << "\n"; - + os << r.dump(); return os; } +void response::node::dump(dump_format format, int indent, std::string& out) const +{ + switch (format) { + case response::node::dump_format::raw: + { + out += std::to_string(depth); + out += '\t'; + out += to_string(data_type); + out += '\t'; + out += data; + } break; + + case response::node::dump_format::clean: + { + std::string prefix(indent * depth, ' '); + out += prefix; + out += data; + } break; + + default: { + } + } +} + +std::string +response::dump(node::dump_format format, int indent) const +{ + std::string res; + for (auto const& n : data_) { + if (n.size > 1) + continue; + n.dump(format, indent, res); + res += '\n'; + } + + return res; +} + } // resp3 } // aedis diff --git a/include/aedis/resp3/response.hpp b/include/aedis/resp3/response.hpp index 0c9dfeb7..6114df5c 100644 --- a/include/aedis/resp3/response.hpp +++ b/include/aedis/resp3/response.hpp @@ -21,6 +21,7 @@ public: /** Represents a node in the response tree. */ struct node { + enum class dump_format {raw, clean}; /// The number of children node is parent of. std::size_t size; @@ -32,6 +33,9 @@ public: /// The data. For aggregate data types this is always empty. std::string data; + + /// Converts the node to a string and appends to out. + void dump(dump_format format, int indent, std::string& out) const; }; using storage_type = std::vector; @@ -102,6 +106,12 @@ public: * Expects a non-empty response. */ auto get_type() const noexcept { return data_.front().data_type; } + + /** Converts the string to string. + */ + std::string + dump(node::dump_format format = node::dump_format::clean, + int indent = 3) const; }; /// Equality comparison for a node.