Fix String::Data::reserve on big endian platforms, and document String::Data
reserve was not ensuring the capacity would be pair, which is needed on big endian machines, as we use its least significant bit to flag short string optimizations. On little endian the bit we use is the 8th most significant (the least significant bit of the last byte), so we were not hitting any problems. Fixes #828
This commit is contained in:
parent
1b9eb2c6ba
commit
e701254b02
|
@ -17,6 +17,7 @@ String::Data::Data(const char* data, size_t size, size_t capacity)
|
||||||
if (capacity & 1)
|
if (capacity & 1)
|
||||||
++capacity;
|
++capacity;
|
||||||
|
|
||||||
|
kak_assert(capacity < Long::max_capacity);
|
||||||
l.ptr = Alloc{}.allocate(capacity+1);
|
l.ptr = Alloc{}.allocate(capacity+1);
|
||||||
l.size = size;
|
l.size = size;
|
||||||
l.capacity = capacity;
|
l.capacity = capacity;
|
||||||
|
@ -71,6 +72,10 @@ void String::Data::reserve(size_t new_capacity)
|
||||||
if (is_long())
|
if (is_long())
|
||||||
new_capacity = std::max(l.capacity * 2, new_capacity);
|
new_capacity = std::max(l.capacity * 2, new_capacity);
|
||||||
|
|
||||||
|
if (new_capacity & 1)
|
||||||
|
++new_capacity;
|
||||||
|
|
||||||
|
kak_assert(new_capacity < Long::max_capacity);
|
||||||
char* new_ptr = Alloc{}.allocate(new_capacity+1);
|
char* new_ptr = Alloc{}.allocate(new_capacity+1);
|
||||||
if (copy)
|
if (copy)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,12 +130,22 @@ public:
|
||||||
static const String ms_empty;
|
static const String ms_empty;
|
||||||
static constexpr const char* option_type_name = "str";
|
static constexpr const char* option_type_name = "str";
|
||||||
|
|
||||||
|
// String data storage using small string optimization.
|
||||||
|
//
|
||||||
|
// the LSB of the last byte is used to flag if we are using the small buffer
|
||||||
|
// or an allocated one. On big endian systems that means the allocated
|
||||||
|
// capacity must be pair, on little endian systems that means the allocated
|
||||||
|
// capacity cannot use its most significant byte, so we effectively limit
|
||||||
|
// capacity to 2^24 on 32bit arch, and 2^60 on 64.
|
||||||
union Data
|
union Data
|
||||||
{
|
{
|
||||||
using Alloc = Allocator<char, MemoryDomain::String>;
|
using Alloc = Allocator<char, MemoryDomain::String>;
|
||||||
|
|
||||||
struct Long
|
struct Long
|
||||||
{
|
{
|
||||||
|
static constexpr size_t max_capacity =
|
||||||
|
(size_t)1 << 8 * (sizeof(size_t) - 1);
|
||||||
|
|
||||||
char* ptr;
|
char* ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user