make the print function for entry actually be json-like. when logging bencode entries, print it all on a single line. add test for entry print function

This commit is contained in:
arvidn 2018-08-26 22:15:05 +02:00 committed by Arvid Norberg
parent 269b71324e
commit 7c837be651
4 changed files with 135 additions and 49 deletions

View File

@ -256,6 +256,7 @@ namespace libtorrent
// returns a pretty-printed string representation
// of the bencoded structure, with JSON-style syntax
std::string to_string() const;
std::string to_string(bool single_line) const;
protected:
@ -265,7 +266,7 @@ namespace libtorrent
private:
void to_string_impl(std::string& out, int indent) const;
void to_string_impl(std::string& out, int indent, bool single_line) const;
#if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIRED
// workaround for msvc-bug.

View File

@ -1814,7 +1814,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::incoming_message, "EXTENDED_HANDSHAKE"
, "%s", print_entry(root).c_str());
, "%s", print_entry(root, true).c_str());
#endif
for (extension_list_t::iterator i = m_extensions.begin();
@ -2355,7 +2355,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::outgoing_message, "EXTENDED_HANDSHAKE"
, "%s", handshake.to_string().c_str());
, "%s", handshake.to_string(true).c_str());
#endif
}
#endif

View File

@ -653,83 +653,87 @@ namespace libtorrent
std::string entry::to_string() const
{
std::string ret;
to_string_impl(ret, 0);
to_string_impl(ret, 0, false);
return ret;
}
void entry::to_string_impl(std::string& out, int indent) const
std::string entry::to_string(bool single_line) const
{
std::string ret;
to_string_impl(ret, 0, single_line);
return ret;
}
namespace {
bool is_binary(std::string const& str)
{
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
{
if (!is_print(static_cast<unsigned char>(*i)))
return true;
}
return false;
}
void add_indent(std::string& out, int const indent)
{
out.resize(out.size() + indent, ' ');
}
}
void entry::to_string_impl(std::string& out, int const indent
, bool const single_line) const
{
TORRENT_ASSERT(indent >= 0);
for (int i = 0; i < indent; ++i) out += " ";
switch (m_type)
{
case int_t:
out += libtorrent::to_string(integer()).elems;
out += "\n";
break;
case string_t:
{
bool binary_string = false;
for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
{
if (!is_print(static_cast<unsigned char>(*i)))
{
binary_string = true;
break;
}
}
if (binary_string)
{
out += to_hex(string());
out += "\n";
}
else
{
out += string();
out += "\n";
}
out += "'";
if (is_binary(string())) out += to_hex(string());
else out += string();
out += "'";
} break;
case list_t:
{
out += "list\n";
out += single_line ? "[ " : "[\n";
bool first = true;
for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
{
i->to_string_impl(out, indent+1);
if (!first) out += single_line ? ", " : ",\n";
first = false;
if (!single_line) add_indent(out, indent+1);
i->to_string_impl(out, indent+1, single_line);
}
out += " ]";
} break;
case dictionary_t:
{
out += "dictionary\n";
out += single_line ? "{ " : "{\n";
bool first = true;
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
{
bool binary_string = false;
for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k)
{
if (!is_print(static_cast<unsigned char>(*k)))
{
binary_string = true;
break;
}
}
for (int j = 0; j < indent+1; ++j) out += " ";
out += "[";
if (binary_string) out += to_hex(i->first);
if (!first) out += single_line ? ", " : ",\n";
first = false;
if (!single_line) add_indent(out, indent+1);
out += "'";
if (is_binary(i->first)) out += to_hex(i->first);
else out += i->first;
out += "]";
out += "': ";
if (i->second.type() != entry::string_t
&& i->second.type() != entry::int_t)
out += "\n";
else out += " ";
i->second.to_string_impl(out, indent+2);
i->second.to_string_impl(out, indent+2, single_line);
}
out += " }";
} break;
case preformatted_t:
out += "<preformatted>\n";
out += "<preformatted>";
break;
case undefined_t:
default:
out += "<uninitialized>\n";
out += "<uninitialized>";
}
}
}

View File

@ -134,6 +134,87 @@ TORRENT_TEST(undefined_node2)
TEST_EQUAL(encode(e), "d4:info0:e");
}
TORRENT_TEST(print_dict_single_line)
{
entry e;
e["foo"] = "bar";
e["bar"] = "foo";
TEST_EQUAL(e.to_string(true), "{ 'bar': 'foo', 'foo': 'bar' }");
}
TORRENT_TEST(print_dict)
{
entry e;
e["foo"] = "bar";
e["bar"] = "foo";
TEST_EQUAL(e.to_string(), "{\n 'bar': 'foo',\n 'foo': 'bar' }");
}
TORRENT_TEST(print_list_single_line)
{
entry e;
e.list().push_back(entry("foo"));
e.list().push_back(entry("bar"));
TEST_EQUAL(e.to_string(true), "[ 'foo', 'bar' ]");
}
TORRENT_TEST(print_list)
{
entry e;
e.list().push_back(entry("foo"));
e.list().push_back(entry("bar"));
TEST_EQUAL(e.to_string(), "[\n 'foo',\n 'bar' ]");
}
TORRENT_TEST(print_int_single_line)
{
entry e(1337);
TEST_EQUAL(e.to_string(true), "1337");
}
TORRENT_TEST(print_int)
{
entry e(1337);
TEST_EQUAL(e.to_string(), "1337");
}
TORRENT_TEST(print_string_single_line)
{
entry e("foobar");
TEST_EQUAL(e.to_string(true), "'foobar'");
}
TORRENT_TEST(print_string)
{
entry e("foobar");
TEST_EQUAL(e.to_string(), "'foobar'");
}
TORRENT_TEST(print_deep_dict_single_line)
{
entry e;
e["strings"].list().push_back(entry("foo"));
e["strings"].list().push_back(entry("bar"));
e["ints"].list().push_back(entry(1));
e["ints"].list().push_back(entry(2));
e["ints"].list().push_back(entry(3));
e["a"] = "foobar";
TEST_EQUAL(e.to_string(true), "{ 'a': 'foobar', 'ints': [ 1, 2, 3 ], 'strings': [ 'foo', 'bar' ] }");
}
TORRENT_TEST(print_deep_dict)
{
entry e;
e["strings"].list().push_back(entry("foo"));
e["strings"].list().push_back(entry("bar"));
e["ints"].list().push_back(entry(1));
e["ints"].list().push_back(entry(2));
e["ints"].list().push_back(entry(3));
e["a"] = "foobar";
TEST_EQUAL(e.to_string(), "{\n 'a': 'foobar',\n 'ints': [\n 1,\n 2,\n 3 ],\n 'strings': [\n 'foo',\n 'bar' ] }");
}
#ifndef TORRENT_NO_DEPRECATE
TORRENT_TEST(lazy_entry)
{