forked from qt-creator/qt-creator
Utils: Improve and fix operators in SmallString
Change-Id: I51f4e647cbd3ada0c3a86d16f40fd8044acead33 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -506,45 +506,14 @@ public:
|
||||
return joinedString;
|
||||
}
|
||||
|
||||
unitttest_public:
|
||||
bool isShortString() const noexcept
|
||||
char &operator[](std::size_t index)
|
||||
{
|
||||
return !m_data.shortString.isReference;
|
||||
return *(data() + index);
|
||||
}
|
||||
|
||||
bool isReadOnlyReference() const noexcept
|
||||
char operator[](std::size_t index) const
|
||||
{
|
||||
return m_data.shortString.isReadOnlyReference;
|
||||
}
|
||||
|
||||
bool hasAllocatedMemory() const noexcept
|
||||
{
|
||||
return !isShortString() && !isReadOnlyReference();
|
||||
}
|
||||
|
||||
bool fitsNotInCapacity(size_type capacity) const noexcept
|
||||
{
|
||||
return (isShortString() && capacity > shortStringCapacity())
|
||||
|| (!isShortString() && capacity > m_data.allocated.data.capacity);
|
||||
}
|
||||
|
||||
static
|
||||
size_type optimalHeapCapacity(const size_type size)
|
||||
{
|
||||
const size_type cacheLineSize = 64;
|
||||
|
||||
const auto divisionByCacheLineSize = std::div(int64_t(size), int64_t(cacheLineSize));
|
||||
|
||||
size_type cacheLineBlocks = size_type(divisionByCacheLineSize.quot);
|
||||
const size_type supplement = divisionByCacheLineSize.rem ? 1 : 0;
|
||||
|
||||
cacheLineBlocks += supplement;
|
||||
int exponent;
|
||||
const double significand = std::frexp(cacheLineBlocks, &exponent);
|
||||
const double factorOneDotFiveSignificant = std::ceil(significand * 4.) / 4.;
|
||||
cacheLineBlocks = size_type(std::ldexp(factorOneDotFiveSignificant, exponent));
|
||||
|
||||
return cacheLineBlocks * cacheLineSize;
|
||||
return *(data() + index);
|
||||
}
|
||||
|
||||
template<size_type ArraySize>
|
||||
@@ -575,12 +544,6 @@ unitttest_public:
|
||||
return second == first;
|
||||
}
|
||||
|
||||
friend bool operator==(const BasicSmallString& first, const BasicSmallString& second) noexcept
|
||||
{
|
||||
return first.size() == second.size()
|
||||
&& std::memcmp(first.data(), second.data(), first.size()) == 0;
|
||||
}
|
||||
|
||||
friend bool operator==(const BasicSmallString& first, const SmallStringView& second) noexcept
|
||||
{
|
||||
return first.size() == second.size()
|
||||
@@ -635,16 +598,6 @@ unitttest_public:
|
||||
return second != first;
|
||||
}
|
||||
|
||||
friend bool operator<(const BasicSmallString& first, const BasicSmallString& second) noexcept
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
return first.size() < second.size();
|
||||
|
||||
const int comparison = std::memcmp(first.data(), second.data(), first.size() + 1);
|
||||
|
||||
return comparison < 0;
|
||||
}
|
||||
|
||||
friend bool operator<(const BasicSmallString& first, SmallStringView second) noexcept
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
@@ -665,6 +618,47 @@ unitttest_public:
|
||||
return comparison < 0;
|
||||
}
|
||||
|
||||
unitttest_public:
|
||||
bool isShortString() const noexcept
|
||||
{
|
||||
return !m_data.shortString.isReference;
|
||||
}
|
||||
|
||||
bool isReadOnlyReference() const noexcept
|
||||
{
|
||||
return m_data.shortString.isReadOnlyReference;
|
||||
}
|
||||
|
||||
bool hasAllocatedMemory() const noexcept
|
||||
{
|
||||
return !isShortString() && !isReadOnlyReference();
|
||||
}
|
||||
|
||||
bool fitsNotInCapacity(size_type capacity) const noexcept
|
||||
{
|
||||
return (isShortString() && capacity > shortStringCapacity())
|
||||
|| (!isShortString() && capacity > m_data.allocated.data.capacity);
|
||||
}
|
||||
|
||||
static
|
||||
size_type optimalHeapCapacity(const size_type size)
|
||||
{
|
||||
const size_type cacheLineSize = 64;
|
||||
|
||||
const auto divisionByCacheLineSize = std::div(int64_t(size), int64_t(cacheLineSize));
|
||||
|
||||
size_type cacheLineBlocks = size_type(divisionByCacheLineSize.quot);
|
||||
const size_type supplement = divisionByCacheLineSize.rem ? 1 : 0;
|
||||
|
||||
cacheLineBlocks += supplement;
|
||||
int exponent;
|
||||
const double significand = std::frexp(cacheLineBlocks, &exponent);
|
||||
const double factorOneDotFiveSignificant = std::ceil(significand * 4.) / 4.;
|
||||
cacheLineBlocks = size_type(std::ldexp(factorOneDotFiveSignificant, exponent));
|
||||
|
||||
return cacheLineBlocks * cacheLineSize;
|
||||
}
|
||||
|
||||
private:
|
||||
BasicSmallString(Internal::StringDataLayout<Size> data) noexcept
|
||||
: m_data(data)
|
||||
@@ -818,6 +812,37 @@ private:
|
||||
Internal::StringDataLayout<Size> m_data;
|
||||
};
|
||||
|
||||
template<template<uint> class String, uint Size>
|
||||
using isSameString = std::is_same<std::remove_reference_t<std::remove_cv_t<String<Size>>>,
|
||||
BasicSmallString<Size>>;
|
||||
|
||||
template<template<uint> class String,
|
||||
uint SizeOne,
|
||||
uint SizeTwo,
|
||||
typename = std::enable_if_t<isSameString<String, SizeOne>::value
|
||||
|| isSameString<String, SizeTwo>::value>>
|
||||
bool operator==(const String<SizeOne> &first, const String<SizeTwo> &second) noexcept
|
||||
{
|
||||
return first.size() == second.size()
|
||||
&& std::memcmp(first.data(), second.data(), first.size()) == 0;
|
||||
}
|
||||
|
||||
|
||||
template<template<uint> class String,
|
||||
uint SizeOne,
|
||||
uint SizeTwo,
|
||||
typename = std::enable_if_t<isSameString<String, SizeOne>::value
|
||||
|| isSameString<String, SizeTwo>::value>>
|
||||
bool operator<(const String<SizeOne> &first, const String<SizeTwo> &second) noexcept
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
return first.size() < second.size();
|
||||
|
||||
const int comparison = std::memcmp(first.data(), second.data(), first.size() + 1);
|
||||
|
||||
return comparison < 0;
|
||||
}
|
||||
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Hash = std::hash<Key>,
|
||||
|
@@ -601,6 +601,14 @@ TEST(SmallString, EqualSmallStringOperator)
|
||||
ASSERT_FALSE(SmallString("text") == SmallString("text2"));
|
||||
}
|
||||
|
||||
TEST(SmallString, EqualSmallStringOperatorWithDifferenceClassSizes)
|
||||
{
|
||||
ASSERT_TRUE(SmallString() == PathString(""));
|
||||
ASSERT_FALSE(SmallString() == PathString("text"));
|
||||
ASSERT_TRUE(SmallString("text") == PathString("text"));
|
||||
ASSERT_FALSE(SmallString("text") == PathString("text2"));
|
||||
}
|
||||
|
||||
TEST(SmallString, EqualCStringArrayOperator)
|
||||
{
|
||||
ASSERT_TRUE(SmallString() == "");
|
||||
@@ -687,6 +695,16 @@ TEST(SmallString, SmallerOperatorWithStringViewLeft)
|
||||
ASSERT_FALSE(SmallStringView("text") < SmallString("text"));
|
||||
}
|
||||
|
||||
TEST(SmallString, SmallerOperatorForDifferenceClassSizes)
|
||||
{
|
||||
ASSERT_TRUE(SmallString() < PathString("text"));
|
||||
ASSERT_TRUE(SmallString("some") < PathString("text"));
|
||||
ASSERT_TRUE(SmallString("text") < PathString("texta"));
|
||||
ASSERT_FALSE(SmallString("texta") < PathString("text"));
|
||||
ASSERT_FALSE(SmallString("text") < PathString("some"));
|
||||
ASSERT_FALSE(SmallString("text") < PathString("text"));
|
||||
}
|
||||
|
||||
TEST(SmallString, IsEmpty)
|
||||
{
|
||||
ASSERT_FALSE(SmallString("text").isEmpty());
|
||||
@@ -1129,3 +1147,42 @@ TEST(SmallString, CompareTextWithDifferentLineEndings)
|
||||
|
||||
ASSERT_THAT(unixText, convertedText);
|
||||
}
|
||||
|
||||
TEST(SmallString, ConstSubscriptOperator)
|
||||
{
|
||||
const SmallString text = {"some text"};
|
||||
|
||||
auto &&sign = text[5];
|
||||
|
||||
ASSERT_THAT(sign, 't');
|
||||
}
|
||||
|
||||
TEST(SmallString, NonConstSubscriptOperator)
|
||||
{
|
||||
SmallString text = {"some text"};
|
||||
|
||||
auto &&sign = text[5];
|
||||
|
||||
ASSERT_THAT(sign, 't');
|
||||
}
|
||||
|
||||
TEST(SmallString, ManipulateConstSubscriptOperator)
|
||||
{
|
||||
const SmallString text = {"some text"};
|
||||
auto &&sign = text[5];
|
||||
|
||||
sign = 'q';
|
||||
|
||||
ASSERT_THAT(text, SmallString{"some text"});
|
||||
}
|
||||
|
||||
TEST(SmallString, ManipulateNonConstSubscriptOperator)
|
||||
{
|
||||
char rawText[] = "some text";
|
||||
SmallString text{rawText};
|
||||
auto &&sign = text[5];
|
||||
|
||||
sign = 'q';
|
||||
|
||||
ASSERT_THAT(text, SmallString{"some qext"});
|
||||
}
|
||||
|
Reference in New Issue
Block a user