make stack_allocator::format_string() grow the buffer for large strings
This commit is contained in:
parent
507fffe872
commit
eb5f29a79c
|
@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libtorrent/stack_allocator.hpp"
|
#include "libtorrent/stack_allocator.hpp"
|
||||||
|
#include <cstdarg> // for va_list, va_copy, va_end
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
namespace aux {
|
namespace aux {
|
||||||
|
@ -56,28 +57,44 @@ namespace aux {
|
||||||
|
|
||||||
allocation_slot stack_allocator::format_string(char const* fmt, va_list v)
|
allocation_slot stack_allocator::format_string(char const* fmt, va_list v)
|
||||||
{
|
{
|
||||||
int const ret = int(m_storage.size());
|
int const pos = int(m_storage.size());
|
||||||
int const max_size = 1024;
|
int len = 512;
|
||||||
m_storage.resize(ret + max_size);
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
m_storage.resize(pos + len + 1);
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_copy(args, v);
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
||||||
#endif
|
#endif
|
||||||
int const len = std::vsnprintf(m_storage.data() + ret, max_size, fmt, v);
|
int const ret = std::vsnprintf(m_storage.data() + pos, static_cast<std::size_t>(len + 1), fmt, args);
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (len < 0)
|
va_end(args);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
m_storage.resize(ret);
|
m_storage.resize(pos);
|
||||||
return copy_string("(format error)");
|
return copy_string("(format error)");
|
||||||
}
|
}
|
||||||
|
if (ret > len)
|
||||||
|
{
|
||||||
|
// try again
|
||||||
|
len = ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// +1 is to include the 0-terminator
|
// +1 is to include the 0-terminator
|
||||||
m_storage.resize(ret + std::min(len, max_size) + 1);
|
m_storage.resize(pos + len + 1);
|
||||||
return allocation_slot(ret);
|
return allocation_slot(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocation_slot stack_allocator::copy_buffer(span<char const> buf)
|
allocation_slot stack_allocator::copy_buffer(span<char const> buf)
|
||||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
#include "libtorrent/stack_allocator.hpp"
|
#include "libtorrent/stack_allocator.hpp"
|
||||||
#include "libtorrent/string_view.hpp"
|
#include "libtorrent/string_view.hpp"
|
||||||
|
#include <cstdarg> // for va_list, va_start, va_end
|
||||||
|
|
||||||
using lt::aux::stack_allocator;
|
using lt::aux::stack_allocator;
|
||||||
using lt::aux::allocation_slot;
|
using lt::aux::allocation_slot;
|
||||||
|
@ -107,3 +108,34 @@ TORRENT_TEST(swap)
|
||||||
TEST_CHECK(a2.ptr(idx1) == "testing"_sv);
|
TEST_CHECK(a2.ptr(idx1) == "testing"_sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TORRENT_FORMAT(2,3)
|
||||||
|
allocation_slot format_string_helper(stack_allocator& stack, char const* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list v;
|
||||||
|
va_start(v, fmt);
|
||||||
|
auto const ret = stack.format_string(fmt, v);
|
||||||
|
va_end(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(format_string_long)
|
||||||
|
{
|
||||||
|
stack_allocator a;
|
||||||
|
std::string long_string;
|
||||||
|
for (int i = 0; i < 1024; ++i) long_string += "foobar-";
|
||||||
|
auto const idx = format_string_helper(a, "%s", long_string.c_str());
|
||||||
|
|
||||||
|
TEST_EQUAL(a.ptr(idx), long_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(format_string)
|
||||||
|
{
|
||||||
|
stack_allocator a;
|
||||||
|
auto const idx = format_string_helper(a, "%d", 10);
|
||||||
|
|
||||||
|
TEST_EQUAL(a.ptr(idx), "10"_sv);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue