diff --git a/ChangeLog b/ChangeLog index 52b08acac..651de45c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -48,6 +48,7 @@ release 0.14.2 * fixed typo in python binding (torrent_handle::piece_prioritize should be torrent_handle::piece_priorities) * fixed race condition when saving DHT state + * fixed bugs related to lexical_cast being locale dependent release 0.14.1 diff --git a/include/libtorrent/escape_string.hpp b/include/libtorrent/escape_string.hpp index 660dd4d08..9f141a923 100644 --- a/include/libtorrent/escape_string.hpp +++ b/include/libtorrent/escape_string.hpp @@ -34,11 +34,16 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_ESCAPE_STRING_HPP_INCLUDED #include +#include #include +#include #include "libtorrent/config.hpp" +#include "libtorrent/size_type.hpp" namespace libtorrent { + boost::array::digits10> to_string(size_type n); + std::string TORRENT_EXPORT unescape_string(std::string const& s); std::string TORRENT_EXPORT escape_string(const char* str, int len); std::string TORRENT_EXPORT escape_path(const char* str, int len); diff --git a/include/libtorrent/size_type.hpp b/include/libtorrent/size_type.hpp index 6020a5ac3..ce5e1e1f9 100644 --- a/include/libtorrent/size_type.hpp +++ b/include/libtorrent/size_type.hpp @@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { typedef boost::int64_t size_type; + typedef boost::uint64_t unsigned_size_type; } diff --git a/src/escape_string.cpp b/src/escape_string.cpp index 386354fe3..533b95634 100644 --- a/src/escape_string.cpp +++ b/src/escape_string.cpp @@ -39,13 +39,35 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include +#include #include "libtorrent/assert.hpp" +#include "libtorrent/escape_string.hpp" namespace libtorrent { + + // lexical_cast's result depends on the locale. We need + // a well defined result + boost::array::digits10> to_string(size_type n) + { + boost::array::digits10> ret; + char *p = &ret.back();; + *p = '\0'; + unsigned_size_type un = n; + if (n < 0) un = -un; + do { + *--p = '0' + un % 10; + un /= 10; + } while (un); + if (n < 0) *--p = '-'; + std::memmove(&ret.front(), p, sizeof(ret.elems)); + return ret; + } + std::string unescape_string(std::string const& s) { std::string ret; diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 9dec182a7..cda88d8dd 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/connection_queue.hpp" #include -#include #include #include @@ -118,7 +117,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri sendbuffer = headers.str(); m_url = url; - start(hostname, boost::lexical_cast(port), timeout, prio + start(hostname, to_string(port).elems, timeout, prio , ps, ssl, handle_redirects, bind_addr); } diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index e8cc4254d..389e0895c 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -196,17 +196,17 @@ namespace libtorrent request += "?info_hash="; request += escape_string((char const*)&t->torrent_file().info_hash()[0], 20); request += "&piece="; - request += boost::lexical_cast(r.piece); + request += to_string(r.piece).elems; // if we're requesting less than an entire piece we need to // add ranges if (r.start > 0 || r.length != t->torrent_file().piece_size(r.piece)) { request += "&ranges="; - request += boost::lexical_cast(r.start); + request += to_string(r.start).elems; request += "-"; // TODO: are ranges inclusive? - request += boost::lexical_cast(r.start + r.length); + request += to_string(r.start + r.length).elems; } request += " HTTP/1.1\r\n"; @@ -318,8 +318,8 @@ namespace libtorrent && m_parser.status_code() < 400)) { t->remove_web_seed(m_url, web_seed_entry::http_seed); - std::string error_msg = boost::lexical_cast(m_parser.status_code()) - + " " + m_parser.message(); + std::string error_msg = to_string(m_parser.status_code()).elems + + (" " + m_parser.message()); if (m_ses.m_alerts.should_post()) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index c22c99b33..b6fd393af 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -129,16 +129,16 @@ namespace libtorrent reinterpret_cast(tracker_req().pid.begin()), 20); url += "&port="; - url += boost::lexical_cast(tracker_req().listen_port); + url += to_string(tracker_req().listen_port).elems; url += "&uploaded="; - url += boost::lexical_cast(tracker_req().uploaded); + url += to_string(tracker_req().uploaded).elems; url += "&downloaded="; - url += boost::lexical_cast(tracker_req().downloaded); + url += to_string(tracker_req().downloaded).elems; url += "&left="; - url += boost::lexical_cast(tracker_req().left); + url += to_string(tracker_req().left).elems; if (tracker_req().event != tracker_request::none) { @@ -155,8 +155,7 @@ namespace libtorrent url += "&compact=1"; url += "&numwant="; - url += boost::lexical_cast( - (std::min)(tracker_req().num_want, 999)); + url += to_string((std::min)(tracker_req().num_want, 999)).elems; if (settings.announce_ip != address()) { diff --git a/src/logger.cpp b/src/logger.cpp index 944e559ae..154415498 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include -#include #include #include @@ -214,7 +213,7 @@ namespace error_code ec; return boost::shared_ptr(new logger_peer_plugin( pc->remote().address().to_string(ec) + "_" - + boost::lexical_cast(pc->remote().port()) + ".log")); + + to_string(pc->remote().port()).elems + ".log")); } }; diff --git a/src/lt_trackers.cpp b/src/lt_trackers.cpp index 3805309ba..1c0214027 100644 --- a/src/lt_trackers.cpp +++ b/src/lt_trackers.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include -#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index 17f143c50..1061a822d 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include -#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index ff7787559..23bcf6004 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -161,7 +161,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING error_code ec; m_logger = m_ses.create_log(m_remote.address().to_string(ec) + "_" - + boost::lexical_cast(m_remote.port()), m_ses.listen_port()); + + to_string(m_remote.port()).elems, m_ses.listen_port()); (*m_logger) << "*** OUTGOING CONNECTION\n"; #endif #ifdef TORRENT_DEBUG @@ -272,7 +272,7 @@ namespace libtorrent error_code ec; TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec); m_logger = m_ses.create_log(remote().address().to_string(ec) + "_" - + boost::lexical_cast(remote().port()), m_ses.listen_port()); + + to_string(remote().port()).elems, m_ses.listen_port()); (*m_logger) << "*** INCOMING CONNECTION\n"; #endif diff --git a/src/smart_ban.cpp b/src/smart_ban.cpp index 759377ed8..8e7bc90b4 100644 --- a/src/smart_ban.cpp +++ b/src/smart_ban.cpp @@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/torrent.cpp b/src/torrent.cpp index 6f0099544..23229c5f1 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -49,7 +49,6 @@ POSSIBILITY OF SUCH DAMAGE. #pragma warning(push, 1) #endif -#include #include #include #include @@ -1244,7 +1243,7 @@ namespace libtorrent // assume this is because we got a hostname instead of // an ip address from the tracker - tcp::resolver::query q(i->ip, boost::lexical_cast(i->port)); + tcp::resolver::query q(i->ip, to_string(i->port).elems); m_host_resolver.async_resolve(q, bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid)); } @@ -2611,8 +2610,7 @@ namespace libtorrent || ps.type == proxy_settings::http_pw) { // use proxy - tcp::resolver::query q(ps.hostname - , boost::lexical_cast(ps.port)); + tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); m_host_resolver.async_resolve(q, bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, web)); } @@ -2630,7 +2628,7 @@ namespace libtorrent return; } - tcp::resolver::query q(hostname, boost::lexical_cast(port)); + tcp::resolver::query q(hostname, to_string(port).elems); m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, web , tcp::endpoint())); @@ -2694,7 +2692,7 @@ namespace libtorrent return; } - tcp::resolver::query q(hostname, boost::lexical_cast(port)); + tcp::resolver::query q(hostname, to_string(port).elems); m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, web, a)); } @@ -3657,6 +3655,8 @@ namespace libtorrent int torrent::disconnect_peers(int num) { + INVARIANT_CHECK; + int ret = 0; // buils a list of all connected peers and sort it by 'disconnectability'. std::vector peers(m_connections.size()); diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 1a6efdab4..cbb28eec4 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -46,7 +46,6 @@ POSSIBILITY OF SUCH DAMAGE. #pragma warning(push, 1) #endif -#include #include #include #include diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 14189eaf3..cc13e42f4 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -44,7 +44,6 @@ POSSIBILITY OF SUCH DAMAGE. #pragma warning(push, 1) #endif -#include #include #include #include diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 435a3a2ca..bb371bf86 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2007, Arvid Norberg, Magnus Jonsson +Copyright (c) 2007, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,9 +32,9 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/udp_socket.hpp" #include "libtorrent/connection_queue.hpp" +#include "libtorrent/escape_string.hpp" #include #include -#include #include #if BOOST_VERSION < 103500 #include @@ -394,8 +394,7 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps) || ps.type == proxy_settings::socks5_pw) { // connect to socks5 server and open up the UDP tunnel - tcp::resolver::query q(ps.hostname - , boost::lexical_cast(ps.port)); + tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); m_resolver.async_resolve(q, boost::bind( &udp_socket::on_name_lookup, this, _1, _2)); } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 209e970f7..2458d1b2b 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -56,6 +56,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/udp_tracker_connection.hpp" #include "libtorrent/io.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/escape_string.hpp" namespace { @@ -69,7 +70,6 @@ namespace } using boost::bind; -using boost::lexical_cast; namespace libtorrent { @@ -114,7 +114,7 @@ namespace libtorrent session_settings const& settings = m_ses.settings(); - udp::resolver::query q(hostname, boost::lexical_cast(port)); + udp::resolver::query q(hostname, to_string(port).elems); m_name_lookup.async_resolve(q , boost::bind( &udp_tracker_connection::name_lookup, self(), _1, _2)); diff --git a/src/upnp.cpp b/src/upnp.cpp index f4de70d85..147acff2b 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/xml_parse.hpp" #include "libtorrent/connection_queue.hpp" #include "libtorrent/enum_net.hpp" +#include "libtorrent/escape_string.hpp" #include #include @@ -661,7 +662,7 @@ void upnp::update_map(rootdevice& d, int i) , boost::ref(d), i, _5), true , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + d.upnp_connection->start(d.hostname, to_string(d.port).elems , seconds(10), 1); } else if (m.action == mapping_t::action_delete) @@ -671,7 +672,7 @@ void upnp::update_map(rootdevice& d, int i) , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2 , boost::ref(d), i, _5), true , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + d.upnp_connection->start(d.hostname, to_string(d.port).elems , seconds(10), 1); } @@ -899,7 +900,7 @@ void upnp::on_upnp_xml(error_code const& e boost::tie(protocol, auth, d.hostname, d.port, d.path, error) = parse_url_components(d.url); d.control_url = protocol + "://" + d.hostname + ":" - + boost::lexical_cast(d.port) + s.control_url; + + to_string(d.port).elems + s.control_url; } std::stringstream msg; @@ -1136,7 +1137,7 @@ void upnp::return_error(int mapping, int code) error_code_t* e = std::lower_bound(error_codes, end, tmp , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); std::string error_string = "UPnP mapping error "; - error_string += boost::lexical_cast(code); + error_string += to_string(code).elems; if (e != end && e->code == code) { error_string += ": "; diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index cc3bb8cce..0e2122ed5 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include -#include #ifdef _MSC_VER #pragma warning(pop) diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index f763bbda6..42c728c7e 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -230,11 +230,9 @@ namespace libtorrent request += "\r\nProxy-Connection: keep-alive"; } request += "\r\nRange: bytes="; - request += boost::lexical_cast(size_type(r.piece) - * info.piece_length() + r.start); + request += to_string(size_type(r.piece) * info.piece_length() + r.start).elems; request += "-"; - request += boost::lexical_cast(r.piece - * info.piece_length() + r.start + r.length - 1); + request += to_string(r.piece * info.piece_length() + r.start + r.length - 1).elems; if (m_first_request || using_proxy) request += "\r\nConnection: keep-alive"; request += "\r\n\r\n"; @@ -287,9 +285,9 @@ namespace libtorrent request += "\r\nProxy-Connection: keep-alive"; } request += "\r\nRange: bytes="; - request += boost::lexical_cast(f.offset); + request += to_string(f.offset).elems; request += "-"; - request += boost::lexical_cast(f.offset + f.size - 1); + request += to_string(f.offset + f.size - 1).elems; if (m_first_request || using_proxy) request += "\r\nConnection: keep-alive"; request += "\r\n\r\n"; @@ -384,8 +382,8 @@ namespace libtorrent t->retry_web_seed(m_url, web_seed_entry::url_seed); } t->remove_web_seed(m_url, web_seed_entry::url_seed); - std::string error_msg = boost::lexical_cast(m_parser.status_code()) - + " " + m_parser.message(); + std::string error_msg = to_string(m_parser.status_code()).elems + + (" " + m_parser.message()); if (m_ses.m_alerts.should_post()) { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index aeec79bec..8d75df0da 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -347,6 +347,15 @@ int test_main() { using namespace libtorrent; + // test itoa + + TEST_CHECK(to_string(345).elems == std::string("345")); + TEST_CHECK(to_string(-345).elems == std::string("-345")); + TEST_CHECK(to_string(0).elems == std::string("0")); + TEST_CHECK(to_string(1000000000).elems == std::string("1000000000")); + + // test url parsing + TEST_CHECK(parse_url_components("http://foo:bar@host.com:80/path/to/file") == make_tuple("http", "foo:bar", "host.com", 80, "/path/to/file", (char const*)0));