aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/utils/smallstring.h28
-rw-r--r--src/libs/utils/smallstringiterator.h9
-rw-r--r--src/libs/utils/smallstringlayout.h176
-rw-r--r--src/libs/utils/smallstringliteral.h8
-rw-r--r--src/libs/utils/smallstringview.h6
-rw-r--r--tests/unit/unittest/smallstring-test.cpp15
6 files changed, 157 insertions, 85 deletions
diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index b945a0f2fe..e8827c3f7b 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -93,9 +93,9 @@ public:
if (Q_LIKELY(capacity <= shortStringCapacity())) {
std::memcpy(m_data.shortString.string, string, size);
m_data.shortString.string[size] = 0;
- m_data.shortString.shortStringSize = uchar(size);
- m_data.shortString.isReference = false;
- m_data.shortString.isReadOnlyReference = false;
+ m_data.shortString.control.setShortStringSize(size);
+ m_data.shortString.control.setIsShortString(true);
+ m_data.shortString.control.setIsReadOnlyReference(false);
} else {
m_data.allocated.data.pointer = Memory::allocate(capacity + 1);
std::memcpy(m_data.allocated.data.pointer, string, size);
@@ -178,7 +178,7 @@ public:
BasicSmallString(BasicSmallString &&other) noexcept
: m_data(other.m_data)
{
- other.m_data = Internal::StringDataLayout<Size>();
+ other.m_data.reset();
}
BasicSmallString &operator=(BasicSmallString &&other) noexcept
@@ -413,7 +413,7 @@ public:
if (!isShortString())
return m_data.allocated.data.size;
- return m_data.shortString.shortStringSize;
+ return m_data.shortString.control.shortStringSize();
}
size_type capacity() const noexcept
@@ -532,9 +532,10 @@ public:
return size;
}
+ constexpr
size_type shortStringSize() const
{
- return m_data.shortString.shortStringSize;
+ return m_data.shortString.control.shortStringSize();
}
static
@@ -628,16 +629,19 @@ public:
}
unittest_public:
+ constexpr
bool isShortString() const noexcept
{
- return !m_data.shortString.isReference;
+ return m_data.shortString.control.isShortString();
}
+ constexpr
bool isReadOnlyReference() const noexcept
{
- return m_data.shortString.isReadOnlyReference;
+ return m_data.shortString.control.isReadOnlyReference();
}
+ constexpr
bool hasAllocatedMemory() const noexcept
{
return !isShortString() && !isReadOnlyReference();
@@ -712,9 +716,9 @@ private:
m_data.allocated.data.pointer[size] = 0;
m_data.allocated.data.size = size;
m_data.allocated.data.capacity = capacity;
- m_data.allocated.shortStringSize = 0;
- m_data.allocated.isReference = true;
- m_data.allocated.isReadOnlyReference = false;
+ m_data.shortString.control.setShortStringSize(0);
+ m_data.shortString.control.setIsReference(true);
+ m_data.shortString.control.setIsReadOnlyReference(false);
}
char &at(size_type index)
@@ -852,7 +856,7 @@ private:
void setSize(size_type size)
{
if (isShortString())
- m_data.shortString.shortStringSize = uchar(size);
+ m_data.shortString.control.setShortStringSize(size);
else
m_data.allocated.data.size = size;
}
diff --git a/src/libs/utils/smallstringiterator.h b/src/libs/utils/smallstringiterator.h
index 1217e4bd2b..82836d78c4 100644
--- a/src/libs/utils/smallstringiterator.h
+++ b/src/libs/utils/smallstringiterator.h
@@ -51,6 +51,7 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
{
return ++pointer_;
}
+
SmallStringIterator operator++(int) noexcept
{
return pointer_++;
@@ -121,16 +122,19 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
return pointer_;
}
+ constexpr
bool operator==(SmallStringIterator other) const noexcept
{
return pointer_ == other.pointer_;
}
+ constexpr
bool operator!=(SmallStringIterator other) const noexcept
{
return pointer_ != other.pointer_;
}
+ constexpr
bool operator<(SmallStringIterator other) const noexcept
{
return pointer_ < other.pointer_;
@@ -141,6 +145,11 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
return pointer_;
}
+ const Pointer data() const noexcept
+ {
+ return pointer_;
+ }
+
private:
Pointer pointer_ = nullptr;
};
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index 3a93fe8805..5f1406951e 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -28,113 +28,162 @@
#include <QtGlobal>
#include <cstdint>
+#include <memory>
#include <type_traits>
-#if defined(Q_CC_MSVC) && !defined(_WIN64)
-# define ALIGNAS_16
-#else
-# define ALIGNAS_16 alignas(16)
-#endif
-
namespace Utils {
namespace Internal {
using size_type = std::size_t;
-template<bool Bool>
-struct block_type
+template <uint MaximumShortStringDataAreaSize,
+ typename ControlType = typename std::conditional_t<(MaximumShortStringDataAreaSize < 64), uint8_t, uint16_t>>
+struct ControlBlock
{
- using type = uint8_t;
-};
+ using SizeType = ControlType;
+ constexpr ControlBlock() noexcept = default;
+ constexpr ControlBlock(ControlType shortStringSize, bool isReadOnlyReference, bool isReference) noexcept
+ : m_shortStringSize(shortStringSize),
+ m_isReadOnlyReference(isReadOnlyReference),
+ m_isReference(isReference)
+ {}
+
+ void setShortStringSize(size_type size)
+ {
+ m_shortStringSize = static_cast<SizeType>(size);
+ }
+
+ size_type shortStringSize() const
+ {
+ return m_shortStringSize;
+ }
+
+ void setIsReadOnlyReference(bool isReadOnlyReference)
+ {
+ m_isReadOnlyReference = isReadOnlyReference;
+ }
+
+ void setIsReference(bool isReference)
+ {
+ m_isReference = isReference;
+ }
-template<>
-struct block_type<false> {
- using type = uint16_t;
+ void setIsShortString(bool isShortString)
+ {
+ m_isReference = !isShortString;
+ }
+
+ constexpr
+ SizeType stringSize() const
+ {
+ return m_shortStringSize;
+ }
+
+ constexpr
+ bool isReadOnlyReference() const
+ {
+ return m_isReadOnlyReference;
+ }
+
+ constexpr
+ bool isReference() const
+ {
+ return m_isReference;
+ }
+
+ constexpr
+ bool isShortString() const
+ {
+ return !m_isReference;
+ }
+
+private:
+ ControlType m_shortStringSize : (sizeof(ControlType) * 8) - 2;
+ ControlType m_isReadOnlyReference : 1;
+ ControlType m_isReference : 1;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct AllocatedLayout {
- struct Data {
+template <uint MaximumShortStringDataAreaSize>
+struct AllocatedLayout
+{
+ struct Data
+ {
char *pointer;
size_type size;
size_type capacity;
- } data;
- char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
+ };
+
+ ControlBlock<MaximumShortStringDataAreaSize> control;
+ Data data;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct ReferenceLayout {
- struct Data {
+template <uint MaximumShortStringDataAreaSize>
+struct ReferenceLayout
+{
+ constexpr ReferenceLayout() noexcept = default;
+ constexpr ReferenceLayout(const char *stringPointer,
+ size_type size,
+ size_type capacity) noexcept
+ : control(0, true, true),
+ data{stringPointer, size, capacity}
+ {}
+
+ struct Data
+ {
const char *pointer;
size_type size;
size_type capacity;
- } data;
- char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
+ };
+
+ ControlBlock<MaximumShortStringDataAreaSize> control;
+ Data data;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct ShortStringLayout {
+template <uint MaximumShortStringDataAreaSize>
+struct ShortStringLayout
+{
+ ControlBlock<MaximumShortStringDataAreaSize> control;
char string[MaximumShortStringDataAreaSize];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
};
template <uint MaximumShortStringDataAreaSize>
-struct ALIGNAS_16 StringDataLayout {
+struct StringDataLayout {
static_assert(MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
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!");
- constexpr StringDataLayout() noexcept = default;
+ constexpr
+ StringDataLayout() noexcept
+ {
+ reset();
+ }
constexpr StringDataLayout(const char *string,
size_type size) noexcept
- : reference({{string, size, 0}, {}, 0, true, true})
+ : reference(string, size, 0)
{
}
template<size_type Size,
typename std::enable_if_t<Size <= MaximumShortStringDataAreaSize, int> = 0>
- constexpr StringDataLayout(const char(&string)[Size]) noexcept
-#if __cpp_constexpr < 201304
- : reference({{string, Size - 1, 0}, {}, 0, true, true})
-#else
+ StringDataLayout(const char(&string)[Size]) noexcept
: shortString(ShortStringLayout<MaximumShortStringDataAreaSize>{})
-#endif
{
-#if __cpp_constexpr >= 201304
for (size_type i = 0; i < Size; ++i)
shortString.string[i] = string[i];
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Woverflow"
- shortString.shortStringSize = std::uint8_t(Size) - 1;
-#pragma GCC diagnostic pop
-#endif
- shortString.isReference = false;
- shortString.isReadOnlyReference = false;
-
-#endif
+ shortString.control.setShortStringSize(Size - 1);
+ shortString.control.setIsShortString(true);
+ shortString.control.setIsReadOnlyReference(false);
}
template<size_type Size,
typename std::enable_if_t<!(Size <= MaximumShortStringDataAreaSize), int> = 1>
constexpr StringDataLayout(const char(&string)[Size]) noexcept
- : reference({{string, Size - 1, 0}, {}, 0, true, true})
+ : reference(string, Size - 1, 0)
{
}
@@ -144,6 +193,19 @@ struct ALIGNAS_16 StringDataLayout {
return MaximumShortStringDataAreaSize - 1;
}
+ void reset()
+ {
+ shortString.control = ControlBlock<MaximumShortStringDataAreaSize>();
+ shortString.string[0] = '\0';
+ }
+
+ StringDataLayout &operator=(const StringDataLayout &other)
+ {
+ this->shortString = other.shortString;
+
+ return *this;
+ }
+
union {
AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
ReferenceLayout<MaximumShortStringDataAreaSize> reference;
diff --git a/src/libs/utils/smallstringliteral.h b/src/libs/utils/smallstringliteral.h
index eedcf45d13..cf0c4953fb 100644
--- a/src/libs/utils/smallstringliteral.h
+++ b/src/libs/utils/smallstringliteral.h
@@ -63,7 +63,7 @@ public:
size_type size() const noexcept
{
- return Q_LIKELY(isShortString()) ? m_data.shortString.shortStringSize : m_data.allocated.data.size;
+ return Q_LIKELY(isShortString()) ? m_data.shortString.control.shortStringSize() : m_data.allocated.data.size;
}
constexpr
@@ -94,14 +94,16 @@ public:
return Internal::StringDataLayout<Size>::shortStringCapacity();
}
+ constexpr
bool isShortString() const noexcept
{
- return !m_data.shortString.isReference;
+ return m_data.shortString.control.isShortString();
}
+ constexpr
bool isReadOnlyReference() const noexcept
{
- return m_data.shortString.isReadOnlyReference;
+ return m_data.shortString.control.isReadOnlyReference();
}
constexpr
diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h
index 4932a85cb4..0d8600e5de 100644
--- a/src/libs/utils/smallstringview.h
+++ b/src/libs/utils/smallstringview.h
@@ -79,6 +79,12 @@ public:
{
}
+ SmallStringView(const const_iterator begin, const const_iterator end) noexcept
+ : m_pointer(begin.data()),
+ m_size(std::size_t(end - begin))
+ {
+ }
+
template<typename String,
typename Utils::enable_if_has_char_data_pointer<String> = 0>
SmallStringView(const String &string) noexcept
diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp
index f64c608696..ee55d875a7 100644
--- a/tests/unit/unittest/smallstring-test.cpp
+++ b/tests/unit/unittest/smallstring-test.cpp
@@ -55,24 +55,17 @@ TEST(SmallString, NullSmallStringIsEqualToEmptySmallString)
TEST(SmallString, ShortSmallStringLiteralIsShortSmallString)
{
- constexpr SmallStringLiteral shortText("short string");
+ // constexpr
+ SmallStringLiteral shortText("short string");
-#if __cpp_constexpr >= 201304
ASSERT_TRUE(shortText.isShortString());
-#else
- ASSERT_TRUE(shortText.isReadOnlyReference());
-#endif
}
TEST(SmallString, ShortSmallStringIsShortSmallString)
{
SmallString shortText("short string");
-#if __cpp_constexpr >= 201304
ASSERT_TRUE(shortText.isShortString());
-#else
- ASSERT_TRUE(shortText.isReadOnlyReference());
-#endif
}
TEST(SmallString, CreateFromCStringIterators)
@@ -189,11 +182,7 @@ TEST(SmallString, CopyShortConstExpressionSmallStringIsShortSmallString)
auto shortTextCopy = shortText;
-#if __cpp_constexpr >= 201304
ASSERT_TRUE(shortTextCopy.isShortString());
-#else
- ASSERT_TRUE(shortTextCopy.isReadOnlyReference());
-#endif
}
TEST(SmallString, CopyLongConstExpressionSmallStringIsLongSmallString)