forked from premiere/premiere-libtorrent
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 <cstdarg> // for va_list, va_copy, va_end
|
||||
|
||||
namespace libtorrent {
|
||||
namespace aux {
|
||||
|
@ -56,28 +57,44 @@ namespace aux {
|
|||
|
||||
allocation_slot stack_allocator::format_string(char const* fmt, va_list v)
|
||||
{
|
||||
int const ret = int(m_storage.size());
|
||||
int const max_size = 1024;
|
||||
m_storage.resize(ret + max_size);
|
||||
int const pos = int(m_storage.size());
|
||||
int len = 512;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
m_storage.resize(pos + len + 1);
|
||||
|
||||
va_list args;
|
||||
va_copy(args, v);
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
||||
#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__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
if (len < 0)
|
||||
va_end(args);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
m_storage.resize(ret);
|
||||
m_storage.resize(pos);
|
||||
return copy_string("(format error)");
|
||||
}
|
||||
if (ret > len)
|
||||
{
|
||||
// try again
|
||||
len = ret;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// +1 is to include the 0-terminator
|
||||
m_storage.resize(ret + std::min(len, max_size) + 1);
|
||||
return allocation_slot(ret);
|
||||
m_storage.resize(pos + len + 1);
|
||||
return allocation_slot(pos);
|
||||
}
|
||||
|
||||
allocation_slot stack_allocator::copy_buffer(span<char const> buf)
|
||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "test.hpp"
|
||||
#include "libtorrent/stack_allocator.hpp"
|
||||
#include "libtorrent/string_view.hpp"
|
||||
#include <cstdarg> // for va_list, va_start, va_end
|
||||
|
||||
using lt::aux::stack_allocator;
|
||||
using lt::aux::allocation_slot;
|
||||
|
@ -107,3 +108,34 @@ TORRENT_TEST(swap)
|
|||
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