From 48a647a1696e3029eed2fdd68fa9a691b9c79f10 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 24 Sep 2016 06:10:54 -0700 Subject: [PATCH] String view entry (#1147) make entry support string_view in its interface, and make it efficient when in in C++14 --- ChangeLog | 1 + include/libtorrent/announce_entry.hpp | 2 +- include/libtorrent/create_torrent.hpp | 2 +- include/libtorrent/entry.hpp | 37 ++++++++--- include/libtorrent/kademlia/put_data.hpp | 2 +- src/announce_entry.cpp | 4 +- src/create_torrent.cpp | 4 +- src/entry.cpp | 78 ++++++++++-------------- src/kademlia/put_data.cpp | 8 +-- test/test_bdecode.cpp | 26 ++++++++ 10 files changed, 97 insertions(+), 67 deletions(-) diff --git a/ChangeLog b/ChangeLog index 376501a1d..03c9aeca8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * use string_view in entry interface * deprecate "send_stats" property on trackers (since lt_tracker extension has been removed) * remove deprecate session_settings API (use settings_pack instead) diff --git a/include/libtorrent/announce_entry.hpp b/include/libtorrent/announce_entry.hpp index a2d6be3ed..866aa19e4 100644 --- a/include/libtorrent/announce_entry.hpp +++ b/include/libtorrent/announce_entry.hpp @@ -47,7 +47,7 @@ namespace libtorrent struct TORRENT_EXPORT announce_entry { // constructs a tracker announce entry with ``u`` as the URL. - announce_entry(std::string const& u); + announce_entry(std::string u); announce_entry(); ~announce_entry(); announce_entry(announce_entry const&) = default; diff --git a/include/libtorrent/create_torrent.hpp b/include/libtorrent/create_torrent.hpp index ed15b9c84..e81a3b698 100644 --- a/include/libtorrent/create_torrent.hpp +++ b/include/libtorrent/create_torrent.hpp @@ -240,7 +240,7 @@ namespace libtorrent // tracker less torrent. It can be used by clients to bootstrap their DHT node from. // The node is a hostname and a port number where there is a DHT node running. // You can have any number of DHT nodes in a torrent. - void add_node(std::pair const& node); + void add_node(std::pair node); // Adds a tracker to the torrent. This is not strictly required, but most torrents // use a tracker as their main source of peers. The url should be an http:// or udp:// diff --git a/include/libtorrent/entry.hpp b/include/libtorrent/entry.hpp index d1225afb0..0b6474ef9 100644 --- a/include/libtorrent/entry.hpp +++ b/include/libtorrent/entry.hpp @@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/assert.hpp" #include "libtorrent/error_code.hpp" #include "libtorrent/span.hpp" +#include "libtorrent/string_view.hpp" namespace libtorrent { @@ -82,6 +83,21 @@ namespace libtorrent #endif struct bdecode_node; +#if __cplusplus > 201103 + namespace aux + { + // this enables us to compare a string_view against the std::string that's + // held by the std::map + struct strview_less + { + using is_transparent = std::true_type; + template + bool operator()(T1 const& rhs, T2 const& lhs) const + { return rhs < lhs; } + }; + }; +#endif + // The ``entry`` class represents one node in a bencoded hierarchy. It works as a // variant type, it can be either a list, a dictionary (``std::map``), an integer // or a string. @@ -92,7 +108,11 @@ namespace libtorrent // the key is always a string. If a generic entry would be allowed // as a key, sorting would become a problem (e.g. to compare a string // to a list). The definition doesn't mention such a limit though. +#if __cplusplus <= 201103 typedef std::map dictionary_type; +#else + typedef std::map dictionary_type; +#endif typedef std::string string_type; typedef std::vector list_type; typedef std::int64_t integer_type; @@ -119,6 +139,7 @@ namespace libtorrent entry(span); template ::value + || std::is_same::value || std::is_same::value>::type> entry(U v) : m_type(undefined_t) @@ -250,21 +271,17 @@ namespace libtorrent // The const version of ``operator[]`` will only return a reference to an // existing element at the given key. If the key is not found, it will // throw ``system_error``. - entry& operator[](char const* key); - entry& operator[](std::string const& key); - const entry& operator[](char const* key) const; - const entry& operator[](std::string const& key) const; + entry& operator[](string_view key); + const entry& operator[](string_view key) const; // These functions requires the entry to be a dictionary, if it isn't // they will throw ``system_error``. // // They will look for an element at the given key in the dictionary, if - // the element cannot be found, they will return 0. If an element with - // the given key is found, the return a pointer to it. - entry* find_key(char const* key); - entry const* find_key(char const* key) const; - entry* find_key(std::string const& key); - entry const* find_key(std::string const& key) const; + // the element cannot be found, they will return nullptr. If an element + // with the given key is found, the return a pointer to it. + entry* find_key(string_view key); + entry const* find_key(string_view key) const; // returns a pretty-printed string representation // of the bencoded structure, with JSON-style syntax diff --git a/include/libtorrent/kademlia/put_data.hpp b/include/libtorrent/kademlia/put_data.hpp index bb9208835..7f5b78300 100644 --- a/include/libtorrent/kademlia/put_data.hpp +++ b/include/libtorrent/kademlia/put_data.hpp @@ -65,7 +65,7 @@ protected: put_callback m_put_callback; item m_data; - bool m_done; + bool m_done = false; }; struct put_data_observer : traversal_observer diff --git a/src/announce_entry.cpp b/src/announce_entry.cpp index 56ae2395c..11d1804a6 100644 --- a/src/announce_entry.cpp +++ b/src/announce_entry.cpp @@ -47,8 +47,8 @@ namespace libtorrent tracker_retry_delay_max = 60 * 60 }; - announce_entry::announce_entry(std::string const& u) - : url(u) + announce_entry::announce_entry(std::string u) + : url(std::move(u)) , fails(0) , updating(false) , source(0) diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 29ffd225e..61dd54fdb 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -705,9 +705,9 @@ namespace libtorrent m_filehashes[index] = h; } - void create_torrent::add_node(std::pair const& node) + void create_torrent::add_node(std::pair node) { - m_nodes.push_back(node); + m_nodes.emplace_back(std::move(node)); } void create_torrent::add_url_seed(string_view url) diff --git a/src/entry.cpp b/src/entry.cpp index 2e020c923..5376d176c 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -89,64 +89,52 @@ namespace libtorrent } } - entry& entry::operator[](char const* key) + entry& entry::operator[](string_view key) { +#if __cplusplus <= 201103 + dictionary_type::iterator i = dict().find(key.to_string()); +#else dictionary_type::iterator i = dict().find(key); +#endif if (i != dict().end()) return i->second; dictionary_type::iterator ret = dict().insert( - std::pair(key, entry())).first; + std::make_pair(key.to_string(), entry())).first; return ret->second; } - entry& entry::operator[](std::string const& key) - { - dictionary_type::iterator i = dict().find(key); - if (i != dict().end()) return i->second; - dictionary_type::iterator ret = dict().insert( - std::make_pair(key, entry())).first; - return ret->second; - } - - entry* entry::find_key(char const* key) - { - dictionary_type::iterator i = dict().find(key); - if (i == dict().end()) return nullptr; - return &i->second; - } - - entry const* entry::find_key(char const* key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) return nullptr; - return &i->second; - } - - entry* entry::find_key(std::string const& key) - { - dictionary_type::iterator i = dict().find(key); - if (i == dict().end()) return nullptr; - return &i->second; - } - - entry const* entry::find_key(std::string const& key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) return nullptr; - return &i->second; - } - - const entry& entry::operator[](char const* key) const - { - return (*this)[std::string(key)]; - } - - const entry& entry::operator[](std::string const& key) const + const entry& entry::operator[](string_view key) const { +#if __cplusplus <= 201103 + dictionary_type::const_iterator i = dict().find(key.to_string()); +#else dictionary_type::const_iterator i = dict().find(key); +#endif if (i == dict().end()) throw_error(); return i->second; } + entry* entry::find_key(string_view key) + { +#if __cplusplus <= 201103 + dictionary_type::iterator i = dict().find(key.to_string()); +#else + dictionary_type::iterator i = dict().find(key); +#endif + if (i == dict().end()) return nullptr; + return &i->second; + } + + entry const* entry::find_key(string_view key) const + { +#if __cplusplus <= 201103 + dictionary_type::const_iterator i = dict().find(key.to_string()); +#else + dictionary_type::const_iterator i = dict().find(key); +#endif + if (i == dict().end()) return nullptr; + return &i->second; + } + entry::data_type entry::type() const { #if TORRENT_USE_ASSERTS diff --git a/src/kademlia/put_data.cpp b/src/kademlia/put_data.cpp index ab9d144d7..a0c175496 100644 --- a/src/kademlia/put_data.cpp +++ b/src/kademlia/put_data.cpp @@ -41,9 +41,7 @@ namespace libtorrent { namespace dht put_data::put_data(node& dht_node, put_callback const& callback) : traversal_algorithm(dht_node, (node_id::min)()) , m_put_callback(callback) - , m_done(false) -{ -} +{} char const* put_data::name() const { return "put_data"; } @@ -51,7 +49,7 @@ void put_data::start() { // router nodes must not be added to puts init(); - bool is_done = add_requests(); + bool const is_done = add_requests(); if (is_done) done(); } @@ -66,7 +64,7 @@ void put_data::set_targets(std::vector> const #if TORRENT_USE_ASSERTS o->m_in_constructor = false; #endif - m_results.push_back(o); + m_results.push_back(std::move(o)); } } diff --git a/test/test_bdecode.cpp b/test/test_bdecode.cpp index 742f955cc..c59025cf0 100644 --- a/test/test_bdecode.cpp +++ b/test/test_bdecode.cpp @@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "test.hpp" #include "libtorrent/bdecode.hpp" +#include "libtorrent/entry.hpp" using namespace libtorrent; @@ -51,6 +52,31 @@ TORRENT_TEST(integer) TEST_EQUAL(e.int_value(), 12453); } +TORRENT_TEST(construct_string) +{ + entry e(std::string("abc123")); + TEST_EQUAL(e.string(), "abc123"); +} + +TORRENT_TEST(construct_string_literal) +{ + entry e("abc123"); + TEST_EQUAL(e.string(), "abc123"); +} + + +TORRENT_TEST(construct_string_view) +{ + entry e(string_view("abc123")); + TEST_EQUAL(e.string(), "abc123"); +} + +TORRENT_TEST(construct_integer) +{ + entry e(4); + TEST_EQUAL(e.integer(), 4); +} + // test string TORRENT_TEST(string) {