Utils: Fix long small string

We used only 6 bit to save the short size but for SmallString with a size
over 64 it is not enough. So we have now to use a uint16 instead of a
uint8 if the size if over 64.

Change-Id: I53558e492b6cb40b739b23a8af83d192a2e11bd2
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-01-31 12:18:08 +01:00
parent 729c535376
commit a0c69c517c
7 changed files with 61 additions and 19 deletions

View File

@@ -28,6 +28,7 @@
#include <QtGlobal>
#include <cstdint>
#include <type_traits>
#ifdef Q_CC_MSVC
# define ALIGNAS_16
@@ -41,7 +42,19 @@ namespace Internal {
using size_type = std::size_t;
template <uint MaximumShortStringDataAreaSize>
template<bool Bool>
struct block_type
{
using type = uint8_t;
};
template<>
struct block_type<false> {
using type = uint16_t;
};
template <uint MaximumShortStringDataAreaSize,
typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
struct AllocatedLayout {
struct Data {
char *pointer;
@@ -49,12 +62,13 @@ struct AllocatedLayout {
size_type capacity;
} data;
char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
std::uint8_t shortStringSize: 6;
std::uint8_t isReadOnlyReference : 1;
std::uint8_t isReference : 1;
BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
BlockType isReadOnlyReference : 1;
BlockType isReference : 1;
};
template <uint MaximumShortStringDataAreaSize>
template <uint MaximumShortStringDataAreaSize,
typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
struct ReferenceLayout {
struct Data {
const char *pointer;
@@ -62,23 +76,28 @@ struct ReferenceLayout {
size_type capacity;
} data;
char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
std::uint8_t shortStringSize: 6;
std::uint8_t isReadOnlyReference : 1;
std::uint8_t isReference : 1;
BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
BlockType isReadOnlyReference : 1;
BlockType isReference : 1;
};
template <uint MaximumShortStringDataAreaSize>
template <uint MaximumShortStringDataAreaSize,
typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
struct ShortStringLayout {
char string[MaximumShortStringDataAreaSize];
std::uint8_t shortStringSize: 6;
std::uint8_t isReadOnlyReference : 1;
std::uint8_t isReference : 1;
BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
BlockType isReadOnlyReference : 1;
BlockType isReference : 1;
};
template <uint MaximumShortStringDataAreaSize>
struct ALIGNAS_16 StringDataLayout {
static_assert( MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
static_assert(((MaximumShortStringDataAreaSize + 1) % 16) == 0, "Size + 1 must be dividable by 16!");
static_assert(MaximumShortStringDataAreaSize < 64
? ((MaximumShortStringDataAreaSize + 1) % 16) == 0
: ((MaximumShortStringDataAreaSize + 2) % 16) == 0,
"Size + 1 must be dividable by 16 if under 64 and Size + 2 must be dividable by 16 if over 64!");
StringDataLayout() noexcept = default;
constexpr StringDataLayout(const char *string,
@@ -117,6 +136,14 @@ struct ALIGNAS_16 StringDataLayout {
#endif
}
constexpr static
size_type shortStringCapacity() noexcept
{
return MaximumShortStringDataAreaSize < 64
? MaximumShortStringDataAreaSize - 1
: MaximumShortStringDataAreaSize - 2;
}
union {
AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
ReferenceLayout<MaximumShortStringDataAreaSize> reference;