mirror of
https://github.com/monero-project/monero.git
synced 2026-04-28 11:53:17 -07:00
Merge pull request #10366
baa631f Improve unpack reserve handling (Lee Clagett)
This commit is contained in:
@@ -30,11 +30,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "serialization/serialization.h"
|
||||||
|
|
||||||
namespace serialization
|
namespace serialization
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -76,7 +80,26 @@ namespace serialization
|
|||||||
template<typename... C>
|
template<typename... C>
|
||||||
void do_reserve(const C&...) {}
|
void do_reserve(const C&...) {}
|
||||||
template<typename C>
|
template<typename C>
|
||||||
auto do_reserve(C &c, std::size_t N) -> decltype(c.reserve(N)) { return c.reserve(N); }
|
auto do_reserve(C &c, std::size_t N, std::size_t B) -> decltype(c.reserve(N))
|
||||||
|
{
|
||||||
|
using T = typename C::value_type;
|
||||||
|
|
||||||
|
static constexpr std::size_t max_compression_ratio =
|
||||||
|
is_blob_type<T>::type::value ? 1 :
|
||||||
|
use_container_varint<T>() ? sizeof(T) :
|
||||||
|
(std::is_same<T, char>::value || std::is_same<T, unsigned char>::value) ? 1:
|
||||||
|
4; // default
|
||||||
|
|
||||||
|
// max compression ratio for upfront memory usage
|
||||||
|
B /= sizeof(T);
|
||||||
|
B = std::max(std::size_t(1), B);
|
||||||
|
if (std::numeric_limits<std::size_t>::max() / max_compression_ratio <= B)
|
||||||
|
B = std::numeric_limits<std::size_t>::max();
|
||||||
|
else
|
||||||
|
B *= max_compression_ratio;
|
||||||
|
|
||||||
|
return c.reserve(std::min(N, B));
|
||||||
|
}
|
||||||
|
|
||||||
// The value_type of STL map-like containers come in the form std::pair<const K, V>.
|
// The value_type of STL map-like containers come in the form std::pair<const K, V>.
|
||||||
// Since we can't {de}serialize const types in this lib, we must convert this to std::pair<K, V>
|
// Since we can't {de}serialize const types in this lib, we must convert this to std::pair<K, V>
|
||||||
@@ -104,7 +127,7 @@ bool do_serialize_container(Archive<false> &ar, C &v)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::serialization::detail::do_reserve(v, cnt);
|
::serialization::detail::do_reserve(v, cnt, ar.remaining_bytes());
|
||||||
|
|
||||||
for (size_t i = 0; i < cnt; i++) {
|
for (size_t i = 0; i < cnt; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
|
|||||||
@@ -372,6 +372,20 @@ TEST(Serialization, serializes_vector_int64_as_fixed_int)
|
|||||||
ASSERT_EQ(57, blob.size());
|
ASSERT_EQ(57, blob.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Serialization, deserializes_vector_reserve)
|
||||||
|
{
|
||||||
|
std::vector<int64_t> v;
|
||||||
|
string blob;
|
||||||
|
|
||||||
|
tools::write_varint(std::back_inserter(blob), unsigned(100));
|
||||||
|
blob.append(std::string(100, 0));
|
||||||
|
|
||||||
|
ASSERT_LT(v.capacity(), 20);
|
||||||
|
ASSERT_FALSE(serialization::parse_binary(blob, v));
|
||||||
|
ASSERT_LT(v.capacity(), 100); // could fail if lib allocates more in reserve call
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
Reference in New Issue
Block a user