Utils: Optimize smallstring a little more

For string with a larger area we use spend a little bit memory on less
execution time.

Change-Id: I261ada4120de974ce40daaa7f0922af4dd115996
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2024-05-12 22:13:03 +02:00
committed by Tim Jenssen
parent c463807dda
commit a7309597fa
15 changed files with 192 additions and 202 deletions

View File

@@ -19,11 +19,11 @@ public:
: m_sqlStatementBuilder(templateText()) : m_sqlStatementBuilder(templateText())
{} {}
void setTableName(Utils::SmallString &&tableName) void setTableName(Utils::SmallStringView tableName)
{ {
m_sqlStatementBuilder.clear(); m_sqlStatementBuilder.clear();
this->m_tableName = std::move(tableName); this->m_tableName = tableName;
} }
void addColumn(Utils::SmallStringView columnName, void addColumn(Utils::SmallStringView columnName,
@@ -291,7 +291,7 @@ private:
void bindAll() const void bindAll() const
{ {
m_sqlStatementBuilder.bind("$table", m_tableName.clone()); m_sqlStatementBuilder.bind("$table", m_tableName);
bindTemporary(); bindTemporary();
bindIfNotExists(); bindIfNotExists();

View File

@@ -145,7 +145,7 @@ public:
{ {
CreateTableSqlStatementBuilder<ColumnType> builder; CreateTableSqlStatementBuilder<ColumnType> builder;
builder.setTableName(m_tableName.clone()); builder.setTableName(m_tableName);
builder.setUseWithoutRowId(m_withoutRowId); builder.setUseWithoutRowId(m_withoutRowId);
builder.setUseIfNotExists(m_useIfNotExists); builder.setUseIfNotExists(m_useIfNotExists);
builder.setUseTemporaryTable(m_useTemporaryTable); builder.setUseTemporaryTable(m_useTemporaryTable);

View File

@@ -23,7 +23,7 @@ void SqlStatementBuilder::bindEmptyText(Utils::SmallString &&name)
changeBinding(std::move(name), {}); changeBinding(std::move(name), {});
} }
void SqlStatementBuilder::bind(Utils::SmallString &&name, Utils::SmallString &&text) void SqlStatementBuilder::bind(Utils::SmallStringView name, Utils::SmallStringView text)
{ {
clearSqlStatement(); clearSqlStatement();
checkBindingTextIsNotEmpty(text); checkBindingTextIsNotEmpty(text);
@@ -31,7 +31,7 @@ void SqlStatementBuilder::bind(Utils::SmallString &&name, Utils::SmallString &&t
changeBinding(std::move(name), std::move(text)); changeBinding(std::move(name), std::move(text));
} }
void SqlStatementBuilder::bind(Utils::SmallString &&name, const Utils::SmallStringVector &textVector) void SqlStatementBuilder::bind(Utils::SmallStringView name, const Utils::SmallStringVector &textVector)
{ {
clearSqlStatement(); clearSqlStatement();
checkBindingTextVectorIsNotEmpty(textVector); checkBindingTextVectorIsNotEmpty(textVector);
@@ -39,7 +39,7 @@ void SqlStatementBuilder::bind(Utils::SmallString &&name, const Utils::SmallStri
changeBinding(std::move(name), textVector.join(", ")); changeBinding(std::move(name), textVector.join(", "));
} }
void SqlStatementBuilder::bind(Utils::SmallString &&name, int value) void SqlStatementBuilder::bind(Utils::SmallStringView name, int value)
{ {
clearSqlStatement(); clearSqlStatement();
checkIfPlaceHolderExists(name); checkIfPlaceHolderExists(name);
@@ -60,7 +60,8 @@ Utils::SmallStringVector integerVectorToStringVector(const std::vector<int> &int
return stringVector; return stringVector;
} }
} }
void SqlStatementBuilder::bind(Utils::SmallString &&name, const std::vector<int> &integerVector)
void SqlStatementBuilder::bind(Utils::SmallStringView name, const std::vector<int> &integerVector)
{ {
clearSqlStatement(); clearSqlStatement();
checkBindingIntegerVectorIsNotEmpty(integerVector); checkBindingIntegerVectorIsNotEmpty(integerVector);

View File

@@ -19,10 +19,10 @@ public:
SqlStatementBuilder(Utils::SmallStringView m_sqlTemplate); SqlStatementBuilder(Utils::SmallStringView m_sqlTemplate);
void bindEmptyText(Utils::SmallString &&name); void bindEmptyText(Utils::SmallString &&name);
void bind(Utils::SmallString &&name, Utils::SmallString &&text); void bind(Utils::SmallStringView name, Utils::SmallStringView text);
void bind(Utils::SmallString &&name, const Utils::SmallStringVector &textVector); void bind(Utils::SmallStringView name, const Utils::SmallStringVector &textVector);
void bind(Utils::SmallString &&name, int value); void bind(Utils::SmallStringView name, int value);
void bind(Utils::SmallString &&name, const std::vector<int> &integerVector); void bind(Utils::SmallStringView name, const std::vector<int> &integerVector);
void bindWithInsertTemplateParameters(Utils::SmallString &&name, void bindWithInsertTemplateParameters(Utils::SmallString &&name,
const Utils::SmallStringVector &columns); const Utils::SmallStringVector &columns);
void bindWithUpdateTemplateParameters(Utils::SmallString &&name, void bindWithUpdateTemplateParameters(Utils::SmallString &&name,
@@ -56,8 +56,8 @@ protected:
Utils::SmallString sqlTemplate); Utils::SmallString sqlTemplate);
private: private:
Utils::BasicSmallString<510> m_sqlTemplate; Utils::BasicSmallString<496> m_sqlTemplate;
mutable Utils::BasicSmallString<510> m_sqlStatement; mutable Utils::BasicSmallString<496> m_sqlStatement;
mutable std::vector<BindingPair> m_bindings; mutable std::vector<BindingPair> m_bindings;
}; };

View File

@@ -47,7 +47,7 @@ public:
using size_type = std::size_t; using size_type = std::size_t;
static_assert(Size < 64 ? sizeof(Internal::StringDataLayout<Size>) == Size + 1 static_assert(Size < 64 ? sizeof(Internal::StringDataLayout<Size>) == Size + 1
: sizeof(Internal::StringDataLayout<Size>) == Size + 2, : sizeof(Internal::StringDataLayout<Size>) == Size + 16,
"Size is wrong"); "Size is wrong");
BasicSmallString() noexcept = default; BasicSmallString() noexcept = default;
@@ -63,16 +63,8 @@ public:
{} {}
BasicSmallString(const char *string, size_type size, size_type capacity) noexcept BasicSmallString(const char *string, size_type size, size_type capacity) noexcept
{ : m_data{string, size, capacity}
if (Q_LIKELY(capacity <= shortStringCapacity())) { {}
m_data.control = Internal::ControlBlock<Size>(size, false, false);
std::char_traits<char>::copy(m_data.shortString, string, size);
} else {
auto pointer = Memory::allocate(capacity);
std::char_traits<char>::copy(pointer, string, size);
initializeLongString(pointer, size, capacity);
}
}
explicit BasicSmallString(SmallStringView stringView) noexcept explicit BasicSmallString(SmallStringView stringView) noexcept
: BasicSmallString(stringView.data(), stringView.size(), stringView.size()) : BasicSmallString(stringView.data(), stringView.size(), stringView.size())
@@ -126,7 +118,7 @@ public:
~BasicSmallString() noexcept ~BasicSmallString() noexcept
{ {
if (Q_UNLIKELY(hasAllocatedMemory())) if (Q_UNLIKELY(hasAllocatedMemory()))
Memory::deallocate(m_data.reference.pointer); Memory::deallocate(m_data.data());
} }
BasicSmallString(const BasicSmallString &other) noexcept BasicSmallString(const BasicSmallString &other) noexcept
@@ -170,17 +162,6 @@ public:
} }
BasicSmallString take() noexcept { return std::move(*this); } BasicSmallString take() noexcept { return std::move(*this); }
BasicSmallString clone() const noexcept
{
BasicSmallString clonedString(m_data);
if (Q_UNLIKELY(hasAllocatedMemory()))
new (&clonedString) BasicSmallString{m_data.reference.pointer,
m_data.reference.size,
m_data.reference.capacity};
return clonedString;
}
friend void swap(BasicSmallString &first, BasicSmallString &second) noexcept friend void swap(BasicSmallString &first, BasicSmallString &second) noexcept
{ {
@@ -229,8 +210,8 @@ public:
{ {
if (fitsNotInCapacity(newCapacity)) { if (fitsNotInCapacity(newCapacity)) {
if (Q_UNLIKELY(hasAllocatedMemory())) { if (Q_UNLIKELY(hasAllocatedMemory())) {
m_data.reference.pointer = Memory::reallocate(m_data.reference.pointer, newCapacity); m_data.setPointer(Memory::reallocate(m_data.data(), newCapacity));
m_data.reference.capacity = newCapacity; m_data.setAllocatedCapacity(newCapacity);
} else { } else {
auto oldSize = size(); auto oldSize = size();
new (this) BasicSmallString{data(), oldSize, std::max(newCapacity, oldSize)}; new (this) BasicSmallString{data(), oldSize, std::max(newCapacity, oldSize)};
@@ -252,15 +233,9 @@ public:
m_data = Internal::StringDataLayout<Size>(); m_data = Internal::StringDataLayout<Size>();
} }
char *data() noexcept char *data() noexcept { return m_data.data(); }
{
return Q_LIKELY(isShortString()) ? m_data.shortString : m_data.reference.pointer;
}
const char *data() const noexcept const char *data() const noexcept { return m_data.data(); }
{
return Q_LIKELY(isShortString()) ? m_data.shortString : m_data.reference.pointer;
}
iterator begin() noexcept iterator begin() noexcept
{ {
@@ -387,21 +362,9 @@ public:
return at(size() - 1) == character; return at(size() - 1) == character;
} }
size_type size() const noexcept size_type size() const noexcept { return m_data.size(); }
{
if (!isShortString())
return m_data.reference.size;
return m_data.control.shortStringSize(); size_type capacity() const noexcept { return m_data.capacity(); }
}
size_type capacity() const noexcept
{
if (!isShortString())
return m_data.reference.capacity;
return shortStringCapacity();
}
bool isEmpty() const noexcept bool isEmpty() const noexcept
{ {
@@ -608,11 +571,6 @@ public:
return size; return size;
} }
constexpr size_type shortStringSize() const noexcept
{
return m_data.control.shortStringSize();
}
static BasicSmallString join(std::initializer_list<SmallStringView> list, static BasicSmallString join(std::initializer_list<SmallStringView> list,
Utils::SmallStringView separator) noexcept Utils::SmallStringView separator) noexcept
{ {
@@ -708,17 +666,12 @@ public:
} }
unittest_public: unittest_public:
constexpr constexpr bool isShortString() const noexcept
bool isShortString() const noexcept
{ {
return m_data.control.isShortString(); return m_data.isShortString();
} }
constexpr constexpr bool isReadOnlyReference() const noexcept { return m_data.isReadOnlyReference(); }
bool isReadOnlyReference() const noexcept
{
return m_data.control.isReadOnlyReference();
}
constexpr constexpr
bool hasAllocatedMemory() const noexcept bool hasAllocatedMemory() const noexcept
@@ -728,10 +681,7 @@ unittest_public:
bool fitsNotInCapacity(size_type capacity) const noexcept bool fitsNotInCapacity(size_type capacity) const noexcept
{ {
if (isShortString()) return capacity > m_data.capacity();
return capacity > shortStringCapacity();
return capacity > m_data.reference.capacity;
} }
static size_type optimalHeapCapacity(const size_type size) noexcept static size_type optimalHeapCapacity(const size_type size) noexcept
@@ -790,13 +740,6 @@ private:
} }
} }
constexpr void initializeLongString(char *pointer, size_type size, size_type capacity) noexcept
{
m_data.control = Internal::ControlBlock<Size>(0, false, true);
m_data.reference.pointer = pointer;
m_data.reference.size = size;
m_data.reference.capacity = capacity;
}
char &at(size_type index) noexcept { return *(data() + index); } char &at(size_type index) noexcept { return *(data() + index); }
@@ -922,13 +865,7 @@ private:
} }
} }
void setSize(size_type size) noexcept void setSize(size_type size) noexcept { m_data.setSize(size); }
{
if (isShortString())
m_data.control.setShortStringSize(size);
else
m_data.reference.size = size;
}
private: private:
Internal::StringDataLayout<Size> m_data; Internal::StringDataLayout<Size> m_data;
@@ -962,7 +899,7 @@ Type clone(const Type &vector)
} }
using SmallString = BasicSmallString<31>; using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<190>; using PathString = BasicSmallString<176>;
inline SmallString operator+(SmallStringView first, SmallStringView second) noexcept inline SmallString operator+(SmallStringView first, SmallStringView second) noexcept
{ {

View File

@@ -17,6 +17,6 @@ class SmallStringView;
template <uint Size> template <uint Size>
class BasicSmallString; class BasicSmallString;
using SmallString = BasicSmallString<31>; using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<190>; using PathString = BasicSmallString<176>;
} // namespace Utils } // namespace Utils

View File

@@ -3,6 +3,8 @@
#pragma once #pragma once
#include "smallstringmemory.h"
#include <QtGlobal> #include <QtGlobal>
#include <algorithm> #include <algorithm>
@@ -110,7 +112,27 @@ struct alignas(16) StringDataLayout
} }
} }
constexpr static size_type shortStringCapacity() noexcept StringDataLayout(const char *string, size_type size, size_type capacity) noexcept
{
if (Q_LIKELY(capacity <= shortStringCapacity())) {
control = Internal::ControlBlock<MaximumShortStringDataAreaSize>(size, false, false);
std::char_traits<char>::copy(shortString, string, size);
} else {
auto pointer = Memory::allocate(capacity);
std::char_traits<char>::copy(pointer, string, size);
initializeLongString(pointer, size, capacity);
}
}
constexpr void initializeLongString(char *pointer, size_type size, size_type capacity) noexcept
{
control = Internal::ControlBlock<MaximumShortStringDataAreaSize>(0, false, true);
reference.pointer = pointer;
reference.size = size;
reference.capacity = capacity;
}
static constexpr size_type shortStringCapacity() noexcept
{ {
return MaximumShortStringDataAreaSize; return MaximumShortStringDataAreaSize;
} }
@@ -126,6 +148,45 @@ struct alignas(16) StringDataLayout
#endif #endif
} }
void setSize(size_type size) noexcept
{
if (isShortString())
control.setShortStringSize(size);
else
reference.size = size;
}
size_type size() const noexcept
{
if (!control.isShortString())
return reference.size;
return control.shortStringSize();
}
bool isShortString() const noexcept { return control.isShortString(); }
size_type capacity() const noexcept
{
if (!isShortString())
return reference.capacity;
return shortStringCapacity();
}
constexpr bool isReadOnlyReference() const noexcept { return control.isReadOnlyReference(); }
char *data() noexcept { return Q_LIKELY(isShortString()) ? shortString : reference.pointer; }
const char *data() const noexcept
{
return Q_LIKELY(isShortString()) ? shortString : reference.pointer;
}
void setPointer(char *p) noexcept { reference.pointer = p; }
void setAllocatedCapacity(size_type capacity) noexcept { reference.capacity = capacity; }
union { union {
struct struct
{ {
@@ -145,45 +206,46 @@ struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
std::enable_if_t<MaximumShortStringDataAreaSize >= 32>> std::enable_if_t<MaximumShortStringDataAreaSize >= 32>>
{ {
static_assert(MaximumShortStringDataAreaSize > 31, "Size must be greater than 31 bytes!"); static_assert(MaximumShortStringDataAreaSize > 31, "Size must be greater than 31 bytes!");
static_assert(MaximumShortStringDataAreaSize < 64 static_assert(((MaximumShortStringDataAreaSize + 16) % 16) == 0,
? ((MaximumShortStringDataAreaSize + 1) % 16) == 0 "Size + 16 must be dividable by 16!");
: ((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 { reset(); } constexpr StringDataLayout() noexcept { reset(); }
constexpr StringDataLayout(const char *string, size_type size) noexcept constexpr StringDataLayout(const char *string, size_type size) noexcept
: controlReference{0, true, true} : constPointer{string}
, reference{{string}, size, 0} , size_{static_cast<int>(size)}
, capacity_{0}
{} {}
template<size_type Size> template<size_type Size>
constexpr StringDataLayout(const char (&string)[Size]) noexcept constexpr StringDataLayout(const char (&string)[Size]) noexcept
{ {
constexpr auto size = Size - 1; constexpr size_type size = Size - 1;
size_ = size;
if constexpr (size <= MaximumShortStringDataAreaSize) { if constexpr (size <= MaximumShortStringDataAreaSize) {
control = {size, false, false}; pointer = buffer;
capacity_ = MaximumShortStringDataAreaSize;
for (size_type i = 0; i < size; ++i) for (size_type i = 0; i < size; ++i)
shortString[i] = string[i]; buffer[i] = string[i];
#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L #if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
if (std::is_constant_evaluated()) { if (std::is_constant_evaluated()) {
for (size_type i = size; i < MaximumShortStringDataAreaSize; ++i) for (size_type i = size; i < MaximumShortStringDataAreaSize; ++i)
shortString[i] = 0; buffer[i] = 0;
} }
#endif #endif
} else { } else {
control = {0, true, true}; constPointer = string;
reference = {{string}, size, 0}; capacity_ = 0;
} }
} }
void copyHere(const StringDataLayout &other) noexcept void copyHere(const StringDataLayout &other) noexcept
{ {
constexpr auto controlBlockSize = sizeof(ControlBlock<MaximumShortStringDataAreaSize>); auto isShortString = other.isShortString();
auto shortStringLayoutSize = other.control.stringSize() + controlBlockSize; auto shortStringSize = isShortString ? other.size() : 0;
constexpr auto referenceLayoutSize = sizeof(ReferenceLayout); auto areaSize = 8 + shortStringSize;
std::memcpy(this, &other, std::max(shortStringLayoutSize, referenceLayoutSize)); pointer = isShortString ? buffer : other.pointer;
std::memcpy(&size_, &other.size_, areaSize);
} }
StringDataLayout(const StringDataLayout &other) noexcept { copyHere(other); } StringDataLayout(const StringDataLayout &other) noexcept { copyHere(other); }
@@ -195,6 +257,18 @@ struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
return *this; return *this;
} }
StringDataLayout(const char *string, size_type size, size_type capacity) noexcept
: size_{static_cast<int>(size)}
, capacity_{static_cast<int>(capacity)}
{
if (Q_LIKELY(capacity <= shortStringCapacity())) {
std::char_traits<char>::copy(buffer, string, size);
pointer = buffer;
} else {
pointer = Memory::allocate(capacity);
std::char_traits<char>::copy(pointer, string, size);
}
}
constexpr static size_type shortStringCapacity() noexcept constexpr static size_type shortStringCapacity() noexcept
{ {
return MaximumShortStringDataAreaSize; return MaximumShortStringDataAreaSize;
@@ -202,27 +276,39 @@ struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
constexpr void reset() noexcept constexpr void reset() noexcept
{ {
control = ControlBlock<MaximumShortStringDataAreaSize>(); pointer = nullptr;
#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L size_ = 0;
if (std::is_constant_evaluated()) { capacity_ = MaximumShortStringDataAreaSize;
for (size_type i = 0; i < MaximumShortStringDataAreaSize; ++i)
shortString[i] = 0;
}
#endif
} }
void setSize(size_type size) noexcept { size_ = size; }
size_type size() const noexcept { return size_; }
bool isShortString() const noexcept { return pointer == buffer; }
size_type capacity() const noexcept { return capacity_; }
constexpr bool isReadOnlyReference() const noexcept { return capacity_ == 0; }
char *data() noexcept { return pointer; }
const char *data() const noexcept { return constPointer; }
void setPointer(char *p) noexcept { pointer = p; }
void setAllocatedCapacity(size_type capacity) noexcept { capacity_ = capacity; }
constexpr size_type shortStringSize() const noexcept { return size_; }
union { union {
struct char *pointer;
{ const char *constPointer;
ControlBlock<MaximumShortStringDataAreaSize> control;
char shortString[MaximumShortStringDataAreaSize];
};
struct
{
ControlBlock<MaximumShortStringDataAreaSize> controlReference;
ReferenceLayout reference;
};
}; };
int size_;
int capacity_;
char buffer[MaximumShortStringDataAreaSize];
}; };
} // namespace Internal } // namespace Internal

View File

@@ -128,6 +128,6 @@ private:
using SmallStringVector = BasicSmallStringVector<BasicSmallString<31>>; using SmallStringVector = BasicSmallStringVector<BasicSmallString<31>>;
using PathStringVector = BasicSmallStringVector<BasicSmallString<190>>; using PathStringVector = BasicSmallStringVector<BasicSmallString<176>>;
using StringViewVector = BasicSmallStringVector<SmallStringView>; using StringViewVector = BasicSmallStringVector<SmallStringView>;
} // namespace Utils; } // namespace Utils;

View File

@@ -242,7 +242,7 @@ struct TypeTraits
static_assert(sizeof(TypeTraits) == sizeof(unsigned int) * 2, static_assert(sizeof(TypeTraits) == sizeof(unsigned int) * 2,
"TypeTraits must be of size unsigned long long!"); "TypeTraits must be of size unsigned long long!");
using TypeNameString = ::Utils::BasicSmallString<63>; using TypeNameString = ::Utils::BasicSmallString<64>;
class VersionNumber class VersionNumber
{ {
@@ -374,7 +374,7 @@ struct ItemLibraryProperty
using ItemLibraryProperties = QVarLengthArray<ItemLibraryProperty, 5>; using ItemLibraryProperties = QVarLengthArray<ItemLibraryProperty, 5>;
using ToolTipString = Utils::BasicSmallString<94>; using ToolTipString = Utils::BasicSmallString<96>;
struct ItemLibraryEntry struct ItemLibraryEntry
{ {

View File

@@ -47,7 +47,7 @@ public:
} }
explicit SourcePath(const Utils::PathString &sourcePath) explicit SourcePath(const Utils::PathString &sourcePath)
: SourcePath(sourcePath.clone()) : SourcePath(Utils::PathString{sourcePath})
{ {
} }

View File

@@ -157,7 +157,7 @@ void PrintTo(const Utils::SmallString &text, ::std::ostream *os)
*os << "\"" << text << "\""; *os << "\"" << text << "\"";
} }
void PrintTo(const Utils::BasicSmallString<94> &text, ::std::ostream *os) void PrintTo(const Utils::BasicSmallString<96> &text, ::std::ostream *os)
{ {
*os << "\"" << text << "\""; *os << "\"" << text << "\"";
} }

View File

@@ -93,7 +93,7 @@ void PrintTo(const std::optional<Type> &optional, ::std::ostream *os)
void PrintTo(Utils::SmallStringView text, ::std::ostream *os); void PrintTo(Utils::SmallStringView text, ::std::ostream *os);
void PrintTo(const Utils::SmallString &text, ::std::ostream *os); void PrintTo(const Utils::SmallString &text, ::std::ostream *os);
void PrintTo(const Utils::BasicSmallString<94> &text, ::std::ostream *os); void PrintTo(const Utils::BasicSmallString<96> &text, ::std::ostream *os);
void PrintTo(const Utils::PathString &text, ::std::ostream *os); void PrintTo(const Utils::PathString &text, ::std::ostream *os);
} // namespace Utils } // namespace Utils

View File

@@ -214,10 +214,10 @@ TYPED_TEST(StorageCache, populate_with_empty_vector)
TYPED_TEST(StorageCache, is_not_empty_after_populate_with_some_entries) TYPED_TEST(StorageCache, is_not_empty_after_populate_with_some_entries)
{ {
typename TypeParam::CacheEntries entries{{this->filePath1.clone(), this->id1}, typename TypeParam::CacheEntries entries{{this->filePath1, this->id1},
{this->filePath2.clone(), this->id4}, {this->filePath2, this->id4},
{this->filePath3.clone(), this->id3}, {this->filePath3, this->id3},
{this->filePath4.clone(), SourceContextId::create(5)}}; {this->filePath4, SourceContextId::create(5)}};
ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries)); ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries));
this->cache.uncheckedPopulate(); this->cache.uncheckedPopulate();
@@ -227,10 +227,10 @@ TYPED_TEST(StorageCache, is_not_empty_after_populate_with_some_entries)
TYPED_TEST(StorageCache, get_entry_after_populate_with_some_entries) TYPED_TEST(StorageCache, get_entry_after_populate_with_some_entries)
{ {
typename TypeParam::CacheEntries entries{{this->filePath1.clone(), this->id1}, typename TypeParam::CacheEntries entries{{this->filePath1, this->id1},
{this->filePath2.clone(), this->id2}, {this->filePath2, this->id2},
{this->filePath3.clone(), SourceContextId::create(7)}, {this->filePath3, SourceContextId::create(7)},
{this->filePath4.clone(), this->id4}}; {this->filePath4, this->id4}};
ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries)); ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries));
this->cache.uncheckedPopulate(); this->cache.uncheckedPopulate();
@@ -241,10 +241,10 @@ TYPED_TEST(StorageCache, get_entry_after_populate_with_some_entries)
TYPED_TEST(StorageCache, entries_have_unique_ids) TYPED_TEST(StorageCache, entries_have_unique_ids)
{ {
typename TypeParam::CacheEntries entries{{this->filePath1.clone(), this->id1}, typename TypeParam::CacheEntries entries{{this->filePath1, this->id1},
{this->filePath2.clone(), this->id2}, {this->filePath2, this->id2},
{this->filePath3.clone(), this->id3}, {this->filePath3, this->id3},
{this->filePath4.clone(), this->id3}}; {this->filePath4, this->id3}};
ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries)); ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries));
ASSERT_THROW(this->cache.populate(), StorageCacheException); ASSERT_THROW(this->cache.populate(), StorageCacheException);
@@ -252,10 +252,10 @@ TYPED_TEST(StorageCache, entries_have_unique_ids)
TYPED_TEST(StorageCache, multiple_entries) TYPED_TEST(StorageCache, multiple_entries)
{ {
typename TypeParam::CacheEntries entries{{this->filePath1.clone(), this->id1}, typename TypeParam::CacheEntries entries{{this->filePath1, this->id1},
{this->filePath1.clone(), this->id2}, {this->filePath1, this->id2},
{this->filePath3.clone(), this->id3}, {this->filePath3, this->id3},
{this->filePath4.clone(), this->id4}}; {this->filePath4, this->id4}};
ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries)); ON_CALL(this->mockStorage, fetchAllSourceContexts()).WillByDefault(Return(entries));
ASSERT_THROW(this->cache.populate(), StorageCacheException); ASSERT_THROW(this->cache.populate(), StorageCacheException);

View File

@@ -40,7 +40,7 @@ TEST_F(SqliteTable, column_is_added_to_table)
TEST_F(SqliteTable, set_table_name) TEST_F(SqliteTable, set_table_name)
{ {
table.setName(tableName.clone()); table.setName(tableName);
ASSERT_THAT(table.name(), tableName); ASSERT_THAT(table.name(), tableName);
} }
@@ -54,7 +54,7 @@ TEST_F(SqliteTable, set_use_without_rowid)
TEST_F(SqliteTable, add_index) TEST_F(SqliteTable, add_index)
{ {
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
@@ -67,7 +67,7 @@ TEST_F(SqliteTable, add_index)
TEST_F(SqliteTable, initialize_table) TEST_F(SqliteTable, initialize_table)
{ {
table.setName(tableName.clone()); table.setName(tableName);
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setUseTemporaryTable(true); table.setUseTemporaryTable(true);
table.setUseWithoutRowId(true); table.setUseWithoutRowId(true);
@@ -84,7 +84,7 @@ TEST_F(SqliteTable, initialize_table)
TEST_F(SqliteTable, initialize_table_with_index) TEST_F(SqliteTable, initialize_table_with_index)
{ {
InSequence sequence; InSequence sequence;
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
table.addIndex({column}); table.addIndex({column});
@@ -104,7 +104,7 @@ TEST_F(SqliteTable, initialize_table_with_index)
TEST_F(SqliteTable, initialize_table_with_unique_index) TEST_F(SqliteTable, initialize_table_with_unique_index)
{ {
InSequence sequence; InSequence sequence;
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
table.addUniqueIndex({column}); table.addUniqueIndex({column});
@@ -302,7 +302,7 @@ TEST_F(SqliteTable, add_foreign_key_column_with_column_and_not_null)
TEST_F(SqliteTable, add_primary_table_contraint) TEST_F(SqliteTable, add_primary_table_contraint)
{ {
table.setName(tableName.clone()); table.setName(tableName);
const auto &idColumn = table.addColumn("id"); const auto &idColumn = table.addColumn("id");
const auto &nameColumn = table.addColumn("name"); const auto &nameColumn = table.addColumn("name");
table.addPrimaryKeyContraint({idColumn, nameColumn}); table.addPrimaryKeyContraint({idColumn, nameColumn});
@@ -331,7 +331,7 @@ TEST_F(StrictSqliteTable, column_is_added_to_table)
TEST_F(StrictSqliteTable, set_table_name) TEST_F(StrictSqliteTable, set_table_name)
{ {
table.setName(tableName.clone()); table.setName(tableName);
ASSERT_THAT(table.name(), tableName); ASSERT_THAT(table.name(), tableName);
} }
@@ -345,7 +345,7 @@ TEST_F(StrictSqliteTable, set_use_without_rowid)
TEST_F(StrictSqliteTable, add_index) TEST_F(StrictSqliteTable, add_index)
{ {
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
@@ -358,7 +358,7 @@ TEST_F(StrictSqliteTable, add_index)
TEST_F(StrictSqliteTable, initialize_table) TEST_F(StrictSqliteTable, initialize_table)
{ {
table.setName(tableName.clone()); table.setName(tableName);
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setUseTemporaryTable(true); table.setUseTemporaryTable(true);
table.setUseWithoutRowId(true); table.setUseWithoutRowId(true);
@@ -375,7 +375,7 @@ TEST_F(StrictSqliteTable, initialize_table)
TEST_F(StrictSqliteTable, initialize_table_with_index) TEST_F(StrictSqliteTable, initialize_table_with_index)
{ {
InSequence sequence; InSequence sequence;
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
table.addIndex({column}); table.addIndex({column});
@@ -395,7 +395,7 @@ TEST_F(StrictSqliteTable, initialize_table_with_index)
TEST_F(StrictSqliteTable, initialize_table_with_unique_index) TEST_F(StrictSqliteTable, initialize_table_with_unique_index)
{ {
InSequence sequence; InSequence sequence;
table.setName(tableName.clone()); table.setName(tableName);
auto &column = table.addColumn("name"); auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value"); auto &column2 = table.addColumn("value");
table.addUniqueIndex({column}); table.addUniqueIndex({column});
@@ -599,7 +599,7 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_column_and_not_null)
TEST_F(StrictSqliteTable, add_primary_table_contraint) TEST_F(StrictSqliteTable, add_primary_table_contraint)
{ {
table.setName(tableName.clone()); table.setName(tableName);
const auto &idColumn = table.addColumn("id"); const auto &idColumn = table.addColumn("id");
const auto &nameColumn = table.addColumn("name"); const auto &nameColumn = table.addColumn("name");
table.addPrimaryKeyContraint({idColumn, nameColumn}); table.addPrimaryKeyContraint({idColumn, nameColumn});

View File

@@ -17,12 +17,12 @@ using Utils::SmallStringLiteral;
using Utils::SmallStringView; using Utils::SmallStringView;
static_assert(32 == sizeof(Utils::BasicSmallString<31>)); static_assert(32 == sizeof(Utils::BasicSmallString<31>));
static_assert(64 == sizeof(Utils::BasicSmallString<63>)); static_assert(80 == sizeof(Utils::BasicSmallString<64>));
static_assert(192 == sizeof(Utils::BasicSmallString<190>)); static_assert(192 == sizeof(Utils::BasicSmallString<176>));
static_assert(16 == alignof(Utils::BasicSmallString<31>)); static_assert(16 == alignof(Utils::BasicSmallString<31>));
static_assert(16 == alignof(Utils::BasicSmallString<63>)); static_assert(16 == alignof(Utils::BasicSmallString<64>));
static_assert(16 == alignof(Utils::BasicSmallString<190>)); static_assert(16 == alignof(Utils::BasicSmallString<192>));
TEST(SmallString, basic_string_equal) TEST(SmallString, basic_string_equal)
{ {
@@ -135,33 +135,6 @@ TEST(SmallString, long_const_expression_small_string_is_reference)
ASSERT_TRUE(longText.isReadOnlyReference()); ASSERT_TRUE(longText.isReadOnlyReference());
} }
TEST(SmallString, clone_short_small_string)
{
SmallString shortText("short string");
auto clonedText = shortText.clone();
ASSERT_THAT(clonedText, Eq("short string"));
}
TEST(SmallString, clone_long_small_string)
{
SmallString longText = SmallString::fromUtf8("very very very very very very very very very very very long string");
auto clonedText = longText.clone();
ASSERT_THAT(clonedText, Eq("very very very very very very very very very very very long string"));
}
TEST(SmallString, cloned_long_small_string_data_pointer_is_different)
{
SmallString longText = SmallString::fromUtf8("very very very very very very very very very very very long string");
auto clonedText = longText.clone();
ASSERT_THAT(clonedText.data(), Ne(longText.data()));
}
TEST(SmallString, copy_short_const_expression_small_string_is_short_small_string) TEST(SmallString, copy_short_const_expression_small_string_is_short_small_string)
{ {
SmallString shortText("short string"); SmallString shortText("short string");
@@ -254,13 +227,6 @@ TEST(SmallString, long_data_access)
ASSERT_THAT(longText, StrEq(longCString)); ASSERT_THAT(longText, StrEq(longCString));
} }
TEST(SmallString, long_small_string_has_short_small_string_size_zero)
{
auto longText = SmallString::fromUtf8("very very very very very very very very very very very long string");
ASSERT_THAT(longText.shortStringSize(), 0);
}
TEST(SmallString, small_string_begin_is_equal_end_for_empty_small_string) TEST(SmallString, small_string_begin_is_equal_end_for_empty_small_string)
{ {
SmallString text; SmallString text;
@@ -1922,7 +1888,7 @@ TEST(SmallString, string_plus_operator_reverse_order)
TEST(SmallString, short_string_capacity) TEST(SmallString, short_string_capacity)
{ {
ASSERT_THAT(SmallString().shortStringCapacity(), 31); ASSERT_THAT(SmallString().shortStringCapacity(), 31);
ASSERT_THAT(PathString().shortStringCapacity(), 190); ASSERT_THAT(PathString().shortStringCapacity(), 176);
} }
TEST(SmallString, to_view) TEST(SmallString, to_view)