Span conversion (#944)

complete http_parser transition to use span. make xml_parse use span. remove buffer::interval. convert some of receive buffer management to use span<>
This commit is contained in:
Arvid Norberg 2016-07-26 02:15:31 -04:00 committed by GitHub
parent 680a09cfa5
commit 634c2bce60
15 changed files with 108 additions and 146 deletions

View File

@ -286,7 +286,7 @@ namespace libtorrent
, char const* target, int target_size) const;
// helper to cut down on boilerplate
void rc4_decrypt(char* pos, int len);
void rc4_decrypt(span<char> buf);
#endif
public:

View File

@ -75,43 +75,8 @@ class buffer
{
public:
// TODO: 3 remove interval and const_interval
struct interval
{
interval()
: begin(0)
, end(0)
{}
interval(char* b, char* e)
: begin(b)
, end(e)
{}
char operator[](int index) const
{
TORRENT_ASSERT(begin + index < end);
return begin[index];
}
int left() const
{
TORRENT_ASSERT(end >= begin);
TORRENT_ASSERT(end - begin < (std::numeric_limits<int>::max)());
return int(end - begin);
}
char* begin;
char* end;
};
struct const_interval
{
const_interval(interval const& i)
: begin(i.begin)
, end(i.end)
{}
const_interval(char const* b, char const* e)
: begin(b)
, end(e)

View File

@ -85,6 +85,7 @@ namespace libtorrent
void pop_front(int bytes_to_pop);
//TODO: 3 use span<> instead of (buffer,s)
void append_buffer(char* buffer, int s, int used_size
, free_buffer_fun destructor, void* userdata
, block_cache_reference ref = block_cache_reference());

View File

@ -74,7 +74,7 @@ namespace libtorrent
std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; }
std::string const& message() const { return m_server_message; }
buffer::const_interval get_body() const;
span<char const> get_body() const;
bool header_finished() const { return m_state == read_body; }
bool finished() const { return m_finished; }
std::tuple<int, int> incoming(span<char const> recv_buffer

View File

@ -89,8 +89,9 @@ struct TORRENT_EXTRA_EXPORT receive_buffer
buffer::const_interval get() const;
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
// returns the entire buffer
buffer::interval mutable_buffer();
// returns the buffer from the current packet start position to the last
// received byte (possibly part of another packet)
span<char> mutable_buffer();
// returns the last 'bytes' from the receive buffer
aux::mutable_buffer mutable_buffer(int bytes);
@ -107,6 +108,9 @@ struct TORRENT_EXTRA_EXPORT receive_buffer
void check_invariant() const
{
TORRENT_ASSERT(m_recv_end >= m_recv_start);
TORRENT_ASSERT(m_recv_end <= int(m_recv_buffer.size()));
TORRENT_ASSERT(m_recv_start <= int(m_recv_buffer.size()));
TORRENT_ASSERT(m_recv_start + m_recv_pos <= int(m_recv_buffer.size()));
}
#endif
@ -116,7 +120,7 @@ private:
// m_recv_buffer.data() (start of actual receive buffer)
// |
// | m_recv_start (tart of current packet)
// | m_recv_start (start of current packet)
// | |
// | | m_recv_pos (number of bytes consumed
// | | | by upper layer, from logical receive buffer)
@ -167,7 +171,7 @@ struct crypto_receive_buffer
: m_connection_buffer(next)
{}
buffer::interval mutable_buffer() { return m_connection_buffer.mutable_buffer(); }
span<char> mutable_buffer() { return m_connection_buffer.mutable_buffer(); }
bool packet_finished() const;

View File

@ -33,17 +33,18 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_XML_PARSE_HPP
#define TORRENT_XML_PARSE_HPP
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <cctype>
#include <cstring>
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/function.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/span.hpp"
namespace libtorrent
{
@ -68,7 +69,8 @@ namespace libtorrent
// val is attribute value
// neither string is 0-terminated, but their lengths are specified via
// name_len and val_len respectively
TORRENT_EXTRA_EXPORT void xml_parse(char const* p, char const* end
// TODO: 3 use span<> for the callback
TORRENT_EXTRA_EXPORT void xml_parse(span<char const> input
, boost::function<void(int,char const*,int,char const*,int)> callback);
}

View File

@ -700,20 +700,19 @@ namespace libtorrent
return -1;
}
void bt_peer_connection::rc4_decrypt(char* const pos, int const len)
void bt_peer_connection::rc4_decrypt(span<char> buf)
{
int consume = 0;
int produce = len;
int produce = int(buf.size());
int packet_size = 0;
aux::mutable_buffer vec(pos, len);
m_rc4->decrypt(vec, consume, produce, packet_size);
m_rc4->decrypt(buf, consume, produce, packet_size);
}
namespace {
void regular_c_free(char* buf, void* /* userdata */
, block_cache_reference /* ref */)
{
::free(buf);
std::free(buf);
}
}
@ -728,7 +727,7 @@ namespace libtorrent
{
// if we're encrypting this buffer, we need to make a copy
// since we'll mutate it
char* buf = static_cast<char*>(malloc(size));
char* buf = static_cast<char*>(std::malloc(size));
std::memcpy(buf, buffer, size);
append_send_buffer(buf, size, &regular_c_free, nullptr);
destructor(const_cast<char*>(buffer), userdata, ref);
@ -2735,9 +2734,7 @@ namespace libtorrent
}
// verify constant
buffer::interval wr_recv_buf = m_recv_buffer.mutable_buffer();
rc4_decrypt(wr_recv_buf.begin + 20, 8);
wr_recv_buf.begin += 28;
rc4_decrypt(m_recv_buffer.mutable_buffer().subspan(20, 8));
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
if (!std::equal(sh_vc, sh_vc + 8, recv_buffer.begin + 20))
@ -2781,7 +2778,7 @@ namespace libtorrent
return;
}
std::fill(m_sync_vc.get(), m_sync_vc.get() + 8, 0);
rc4_decrypt(m_sync_vc.get(), 8);
rc4_decrypt({m_sync_vc.get(), 8});
}
TORRENT_ASSERT(m_sync_vc.get());
@ -2839,8 +2836,10 @@ namespace libtorrent
if (!m_recv_buffer.packet_finished()) return;
buffer::interval wr_buf = m_recv_buffer.mutable_buffer();
rc4_decrypt(wr_buf.begin, m_recv_buffer.packet_size());
// TODO: 3 this is weird buffer handling
span<char> const buf = m_recv_buffer.mutable_buffer();
TORRENT_ASSERT(buf.size() >= m_recv_buffer.packet_size());
rc4_decrypt({buf.data(), size_t(m_recv_buffer.packet_size())});
recv_buffer = m_recv_buffer.get();
@ -2944,8 +2943,10 @@ namespace libtorrent
int const pad_size = is_outgoing() ? m_recv_buffer.packet_size() : m_recv_buffer.packet_size() - 2;
buffer::interval wr_buf = m_recv_buffer.mutable_buffer();
rc4_decrypt(wr_buf.begin, m_recv_buffer.packet_size());
// TODO: 3 this is weird buffer handling
span<char> const buf = m_recv_buffer.mutable_buffer();
TORRENT_ASSERT(buf.size() >= m_recv_buffer.packet_size());
rc4_decrypt({buf.data(), size_t(m_recv_buffer.packet_size())});
recv_buffer = m_recv_buffer.get();
@ -3003,8 +3004,10 @@ namespace libtorrent
if (!m_recv_buffer.packet_finished()) return;
// ia is always rc4, so decrypt it
buffer::interval wr_buf = m_recv_buffer.mutable_buffer();
rc4_decrypt(wr_buf.begin, m_recv_buffer.packet_size());
// TODO: 3 this is weird buffer handling
span<char> const buf = m_recv_buffer.mutable_buffer();
TORRENT_ASSERT(buf.size() >= m_recv_buffer.packet_size());
rc4_decrypt({buf.data(), size_t(m_recv_buffer.packet_size())});
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION"
@ -3033,13 +3036,13 @@ namespace libtorrent
// decrypt remaining received bytes
if (m_rc4_encrypted)
{
buffer::interval wr_buf = m_recv_buffer.mutable_buffer();
wr_buf.begin += m_recv_buffer.packet_size();
rc4_decrypt(wr_buf.begin, wr_buf.left());
span<char> const remaining = m_recv_buffer.mutable_buffer()
.subspan(m_recv_buffer.packet_size());
rc4_decrypt(remaining);
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION"
, "decrypted remaining %d bytes", wr_buf.left());
, "decrypted remaining %d bytes", int(remaining.size()));
#endif
}
m_rc4.reset();

View File

@ -622,6 +622,7 @@ void http_connection::on_connect(error_code const& e)
}
}
// TODO: 3 use span<char> instead of data, size
void http_connection::callback(error_code e, char* data, int size)
{
if (m_bottled && m_called) return;
@ -720,14 +721,13 @@ void http_connection::on_read(error_code const& e
{
error_code ec = boost::asio::error::eof;
TORRENT_ASSERT(bytes_transferred == 0);
char* data = nullptr;
std::size_t size = 0;
span<char> body;
if (m_bottled && m_parser.header_finished())
{
data = &m_recvbuffer[0] + m_parser.body_start();
size = m_parser.get_body().left();
body = span<char>(m_recvbuffer.data() + m_parser.body_start()
, m_parser.get_body().size());
}
callback(ec, data, int(size));
callback(ec, body.data(), int(body.size()));
return;
}
@ -802,7 +802,9 @@ void http_connection::on_read(error_code const& e
{
error_code ec;
m_timer.cancel(ec);
callback(e, &m_recvbuffer[0] + m_parser.body_start(), m_parser.get_body().left());
span<char> body(m_recvbuffer.data() + m_parser.body_start()
, m_parser.get_body().size());
callback(e, body.data(), int(body.size()));
}
}
else

View File

@ -518,18 +518,16 @@ restart_response:
return false;
}
buffer::const_interval http_parser::get_body() const
span<char const> http_parser::get_body() const
{
TORRENT_ASSERT(m_state == read_body);
std::int64_t last_byte = m_chunked_encoding && !m_chunked_ranges.empty()
? (std::min)(m_chunked_ranges.back().second, m_recv_pos)
: m_content_length < 0
? m_recv_pos : (std::min)(m_body_start_pos + m_content_length, m_recv_pos);
std::int64_t const received = m_recv_pos - m_body_start_pos;
TORRENT_ASSERT(last_byte >= m_body_start_pos);
return buffer::const_interval(m_recv_buffer.data()
+ m_body_start_pos
, m_recv_buffer.data() + last_byte);
std::int64_t const body_length = m_chunked_encoding && !m_chunked_ranges.empty()
? (std::min)(m_chunked_ranges.back().second - m_body_start_pos, received)
: m_content_length < 0 ? received : (std::min)(m_content_length, received);
return m_recv_buffer.subspan(m_body_start_pos, body_length);
}
void http_parser::reset()
@ -563,7 +561,7 @@ restart_response:
// the offsets in the array are from the start of the
// buffer, not start of the body, so subtract the size
// of the HTTP header from them
int offset = body_start();
int const offset = body_start();
std::vector<std::pair<std::int64_t, std::int64_t> > const& c = chunks();
for (std::vector<std::pair<std::int64_t, std::int64_t> >::const_iterator i = c.begin()
, end(c.end()); i != end; ++i)

View File

@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include <libtorrent/receive_buffer.hpp>
#include <libtorrent/invariant_check.hpp>
namespace libtorrent {
@ -41,6 +42,7 @@ int receive_buffer::max_receive() const
boost::asio::mutable_buffer receive_buffer::reserve(int size)
{
INVARIANT_CHECK;
TORRENT_ASSERT(size > 0);
TORRENT_ASSERT(m_recv_pos >= 0);
@ -64,6 +66,7 @@ boost::asio::mutable_buffer receive_buffer::reserve(int size)
void receive_buffer::grow(int const limit)
{
INVARIANT_CHECK;
int const current_size = int(m_recv_buffer.size());
TORRENT_ASSERT(current_size < std::numeric_limits<int>::max() / 3);
@ -83,6 +86,7 @@ void receive_buffer::grow(int const limit)
int receive_buffer::advance_pos(int bytes)
{
INVARIANT_CHECK;
int const limit = m_packet_size > m_recv_pos ? m_packet_size - m_recv_pos : m_packet_size;
int const sub_transferred = (std::min)(bytes, limit);
m_recv_pos += sub_transferred;
@ -94,6 +98,7 @@ int receive_buffer::advance_pos(int bytes)
// offset = the offset into the receive buffer where to remove `size` bytes
void receive_buffer::cut(int const size, int const packet_size, int const offset)
{
INVARIANT_CHECK;
TORRENT_ASSERT(packet_size > 0);
TORRENT_ASSERT(int(m_recv_buffer.size()) >= size);
TORRENT_ASSERT(int(m_recv_buffer.size()) >= m_recv_pos);
@ -136,37 +141,28 @@ buffer::const_interval receive_buffer::get() const
if (m_recv_buffer.empty())
{
TORRENT_ASSERT(m_recv_pos == 0);
return buffer::interval(nullptr,nullptr);
return buffer::const_interval(nullptr,nullptr);
}
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()) - m_recv_start);
TORRENT_ASSERT(m_recv_start + m_recv_pos <= m_recv_buffer.size());
return buffer::const_interval(&m_recv_buffer[0] + m_recv_start
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
, &m_recv_buffer[0] + m_recv_start + m_recv_pos);
}
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
buffer::interval receive_buffer::mutable_buffer()
span<char> receive_buffer::mutable_buffer()
{
if (m_recv_buffer.empty())
{
TORRENT_ASSERT(m_recv_pos == 0);
return buffer::interval(nullptr,nullptr);
}
int const rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
return buffer::interval(&m_recv_buffer[0] + m_recv_start
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
INVARIANT_CHECK;
return span<char>(m_recv_buffer).subspan(m_recv_start, m_recv_pos);
}
aux::mutable_buffer receive_buffer::mutable_buffer(int const bytes)
{
INVARIANT_CHECK;
// bytes is the number of bytes we just received, and m_recv_pos has
// already been adjusted for these bytes. The receive pos immediately
// before we received these bytes was (m_recv_pos - bytes)
int const last_recv_pos = m_recv_pos - bytes;
TORRENT_ASSERT(bytes <= m_recv_pos);
return aux::mutable_buffer(&m_recv_buffer[0] + m_recv_start
+ last_recv_pos, bytes);
return span<char>(m_recv_buffer).subspan(m_recv_start + m_recv_pos - bytes, bytes);
}
#endif
@ -176,6 +172,7 @@ aux::mutable_buffer receive_buffer::mutable_buffer(int const bytes)
// enough of it lately.
void receive_buffer::normalize(int force_shrink)
{
INVARIANT_CHECK;
TORRENT_ASSERT(m_recv_end >= m_recv_start);
m_watermark.add_sample(std::max(m_recv_end, m_packet_size));
@ -218,6 +215,7 @@ void receive_buffer::normalize(int force_shrink)
void receive_buffer::reset(int packet_size)
{
INVARIANT_CHECK;
TORRENT_ASSERT(m_recv_buffer.size() >= m_recv_end);
TORRENT_ASSERT(packet_size > 0);
if (m_recv_end > m_packet_size)

View File

@ -940,8 +940,7 @@ void upnp::on_upnp_xml(error_code const& e
}
parse_state s;
xml_parse(p.get_body().begin, p.get_body().end
, std::bind(&find_control_url, _1, _2, _3, boost::ref(s)));
xml_parse(p.get_body(), std::bind(&find_control_url, _1, _2, _3, boost::ref(s)));
if (s.control_url.empty())
{
#ifndef TORRENT_DISABLE_LOGGING
@ -1231,14 +1230,14 @@ void upnp::on_upnp_get_ip_address_response(error_code const& e
// </s:Body>
// </s:Envelope>
span<char const> body = p.get_body();
#ifndef TORRENT_DISABLE_LOGGING
log("get external IP address response: %s"
, std::string(p.get_body().begin, p.get_body().end).c_str());
, std::string(body.data(), body.size()).c_str());
#endif
ip_address_parse_state s;
xml_parse(const_cast<char*>(p.get_body().begin), const_cast<char*>(p.get_body().end)
, std::bind(&find_ip_address, _1, _2, boost::ref(s)));
xml_parse(body, std::bind(&find_ip_address, _1, _2, boost::ref(s)));
#ifndef TORRENT_DISABLE_LOGGING
if (s.error_code != -1)
{
@ -1335,9 +1334,8 @@ void upnp::on_upnp_map_response(error_code const& e
// since those might contain valid UPnP error codes
error_code_parse_state s;
xml_parse(const_cast<char*>(p.get_body().begin)
, const_cast<char*>(p.get_body().end)
, std::bind(&find_error_code, _1, _2, boost::ref(s)));
span<char const> body = p.get_body();
xml_parse(body, std::bind(&find_error_code, _1, _2, boost::ref(s)));
if (s.error_code != -1)
{
@ -1380,7 +1378,7 @@ void upnp::on_upnp_map_response(error_code const& e
#ifndef TORRENT_DISABLE_LOGGING
log("map response: %s"
, std::string(p.get_body().begin, p.get_body().end).c_str());
, std::string(body.data(), body.size()).c_str());
#endif
if (s.error_code == -1)
@ -1468,17 +1466,16 @@ void upnp::on_upnp_unmap_response(error_code const& e
else
{
#ifndef TORRENT_DISABLE_LOGGING
span<char const> body = p.get_body();
log("unmap response: %s"
, std::string(p.get_body().begin, p.get_body().end).c_str());
, std::string(body.data(), body.size()).c_str());
#endif
}
error_code_parse_state s;
if (p.header_finished())
{
xml_parse(const_cast<char*>(p.get_body().begin)
, const_cast<char*>(p.get_body().end)
, std::bind(&find_error_code, _1, _2, boost::ref(s)));
xml_parse(p.get_body(), std::bind(&find_error_code, _1, _2, boost::ref(s)));
}
int const proto = m_mappings[mapping].protocol;

View File

@ -95,10 +95,7 @@ namespace libtorrent { namespace
struct ut_metadata_plugin final
: torrent_plugin
{
explicit ut_metadata_plugin(torrent& t)
: m_torrent(t)
// , m_metadata_progress(0)
, m_metadata_size(0)
explicit ut_metadata_plugin(torrent& t) : m_torrent(t)
{
// initialize m_metadata_size
if (m_torrent.valid_metadata())
@ -137,9 +134,9 @@ namespace libtorrent { namespace
return m_metadata_size;
}
buffer::const_interval metadata() const
span<char const> metadata() const
{
if (!m_torrent.need_loaded()) return buffer::const_interval(nullptr, nullptr);
if (!m_torrent.need_loaded()) return span<char const>();
TORRENT_ASSERT(m_torrent.valid_metadata());
if (!m_metadata)
{
@ -148,8 +145,7 @@ namespace libtorrent { namespace
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
== m_torrent.torrent_file().info_hash());
}
return buffer::const_interval(m_metadata.get(), m_metadata.get()
+ m_metadata_size);
return span<char const>(m_metadata.get(), m_metadata_size);
}
bool received_metadata(ut_metadata_peer_plugin& source
@ -159,16 +155,7 @@ namespace libtorrent { namespace
// we should request.
// returns -1 if we should hold off the request
int metadata_request(bool has_metadata);
/*
// this is called from the peer_connection for
// each piece of metadata it receives
void metadata_progress(int total_size, int received)
{
m_metadata_progress += received;
m_metadata_size = total_size;
m_torrent.set_progress_ppm(std::int64_t(m_metadata_progress) * 1000000 / m_metadata_size);
}
*/
void on_piece_pass(int) override
{
// if we became a seed, copy the metadata from
@ -194,8 +181,7 @@ namespace libtorrent { namespace
// it is mutable because it's generated lazily
mutable boost::shared_array<char> m_metadata;
// int m_metadata_progress;
mutable int m_metadata_size;
mutable int m_metadata_size = 0;
struct metadata_piece
{
@ -300,7 +286,7 @@ namespace libtorrent { namespace
// unloaded torrents don't have any metadata. Since we're
// about to send the metadata, we need it to be loaded
if (!m_tp.need_loaded()) return;
metadata = m_tp.metadata().begin + offset;
metadata = m_tp.metadata().data() + offset;
metadata_piece_size = (std::min)(
int(m_tp.get_metadata_size() - offset), 16 * 1024);
TORRENT_ASSERT(metadata_piece_size > 0);

View File

@ -37,9 +37,11 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
TORRENT_EXTRA_EXPORT void xml_parse(char const* p, char const* end
TORRENT_EXTRA_EXPORT void xml_parse(span<char const> input
, boost::function<void(int,char const*,int,char const*,int)> callback)
{
char const* p = input.data();
char const* end = input.data() + input.size();
for(;p != end; ++p)
{
char const* start = p;

View File

@ -88,7 +88,8 @@ TORRENT_TEST(http_parser)
TEST_CHECK(received == std::make_tuple(4, 64, false));
TEST_CHECK(parser.finished());
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end, "test"));
span<char const> body = parser.get_body();
TEST_CHECK(std::equal(body.begin(), body.end(), "test"));
TEST_CHECK(parser.header("content-type") == "text/plain");
TEST_CHECK(atoi(parser.header("content-length").c_str()) == 4);
@ -109,7 +110,7 @@ TORRENT_TEST(http_parser)
received = feed_bytes(parser, upnp_response);
TEST_CHECK(received == std::make_tuple(0, int(strlen(upnp_response)), false));
TEST_CHECK(parser.get_body().left() == 0);
TEST_CHECK(parser.get_body().empty());
TEST_CHECK(parser.header("st") == "upnp:rootdevice");
TEST_CHECK(parser.header("location")
== "http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc");
@ -130,7 +131,7 @@ TORRENT_TEST(http_parser)
received = feed_bytes(parser, http1_response);
TEST_CHECK(received == std::make_tuple(0, int(strlen(http1_response)), false));
TEST_CHECK(parser.get_body().left() == 0);
TEST_CHECK(parser.get_body().empty());
TEST_CHECK(parser.header("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
TEST_EQUAL(parser.connection_close(), true);
@ -146,7 +147,7 @@ TORRENT_TEST(http_parser)
received = feed_bytes(parser, close_response);
TEST_CHECK(received == std::make_tuple(0, int(strlen(close_response)), false));
TEST_CHECK(parser.get_body().left() == 0);
TEST_CHECK(parser.get_body().empty());
TEST_CHECK(parser.header("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
TEST_EQUAL(parser.connection_close(), true);
@ -162,7 +163,7 @@ TORRENT_TEST(http_parser)
received = feed_bytes(parser, keep_alive_response);
TEST_CHECK(received == std::make_tuple(0, int(strlen(keep_alive_response)), false));
TEST_CHECK(parser.get_body().left() == 0);
TEST_CHECK(parser.get_body().empty());
TEST_CHECK(parser.header("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
TEST_EQUAL(parser.connection_close(), false);
@ -226,7 +227,7 @@ TORRENT_TEST(http_parser)
std::printf("payload: %d protocol: %d\n", std::get<0>(received), std::get<1>(received));
TEST_CHECK(received == std::make_tuple(20, int(strlen(chunked_test)) - 20, false));
TEST_CHECK(parser.finished());
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end
TEST_CHECK(std::equal(parser.get_body().begin(), parser.get_body().end()
, "4\r\ntest\r\n10\r\n0123456789abcdef"));
TEST_CHECK(parser.header("test-header") == "foobar");
TEST_CHECK(parser.header("content-type") == "text/plain");
@ -249,7 +250,7 @@ TORRENT_TEST(http_parser)
received = feed_bytes(parser, tracker_response);
TEST_CHECK(received == std::make_tuple(5, int(strlen(tracker_response) - 5), false));
TEST_CHECK(parser.get_body().left() == 5);
TEST_CHECK(parser.get_body().size() == 5);
parser.reset();
@ -469,8 +470,9 @@ TORRENT_TEST(chunked_encoding)
TEST_CHECK(parser.finished());
char mutable_buffer[100];
memcpy(mutable_buffer, parser.get_body().begin, parser.get_body().left());
int len = parser.collapse_chunk_headers(mutable_buffer, parser.get_body().left());
span<char const> body = parser.get_body();
memcpy(mutable_buffer, body.begin(), body.size());
int const len = parser.collapse_chunk_headers(mutable_buffer, int(body.size()));
TEST_CHECK(std::equal(mutable_buffer, mutable_buffer + len, "test12340123456789abcdef"));
}

View File

@ -264,11 +264,15 @@ void parser_callback(std::string& out, int token, char const* s, int len
TEST_CHECK(val == nullptr);
}
}
span<char const> str(char const* in)
{
return span<char const>(in, strlen(in));
}
void test_parse(char const* in, char const* expected)
{
std::string out;
xml_parse(in, in + strlen(in), std::bind(&parser_callback
xml_parse(str(in), std::bind(&parser_callback
, boost::ref(out), _1, _2, _3, _4, _5));
std::fprintf(stderr, "in: %s\n out: %s\nexpected: %s\n"
, in, out.c_str(), expected);
@ -278,8 +282,7 @@ void test_parse(char const* in, char const* expected)
TORRENT_TEST(upnp_parser1)
{
parse_state xml_s;
xml_parse(upnp_xml, upnp_xml + sizeof(upnp_xml)
, std::bind(&find_control_url, _1, _2, _3, boost::ref(xml_s)));
xml_parse(upnp_xml, std::bind(&find_control_url, _1, _2, _3, boost::ref(xml_s)));
std::cerr << "namespace " << xml_s.service_type << std::endl;
std::cerr << "url_base: " << xml_s.url_base << std::endl;
@ -293,8 +296,7 @@ TORRENT_TEST(upnp_parser1)
TORRENT_TEST(upnp_parser2)
{
parse_state xml_s;
xml_parse(upnp_xml2, upnp_xml2 + sizeof(upnp_xml2)
, std::bind(&find_control_url, _1, _2, _3, boost::ref(xml_s)));
xml_parse(upnp_xml2, std::bind(&find_control_url, _1, _2, _3, boost::ref(xml_s)));
std::cerr << "namespace " << xml_s.service_type << std::endl;
std::cerr << "url_base: " << xml_s.url_base << std::endl;