forked from qt-creator/qt-creator
Utils: Modernize SmallString
Use more C++ api and constexpr. With C++ 17 we can use even more. Change-Id: I33934cd7e087c311bf98501442df848bdb108279 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -90,39 +90,35 @@ public:
|
||||
constexpr
|
||||
BasicSmallString(const char(&string)[ArraySize])
|
||||
: m_data(string)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
BasicSmallString(const char *string, size_type size, size_type capacity)
|
||||
{
|
||||
if (Q_LIKELY(capacity <= shortStringCapacity())) {
|
||||
std::memcpy(m_data.shortString.string, string, size);
|
||||
std::char_traits<char>::copy(m_data.shortString.string, string, size);
|
||||
m_data.shortString.string[size] = 0;
|
||||
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);
|
||||
std::char_traits<char>::copy(m_data.allocated.data.pointer, string, size);
|
||||
initializeLongString(size, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
explicit BasicSmallString(SmallStringView stringView)
|
||||
: BasicSmallString(stringView.data(), stringView.size(), stringView.size())
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
BasicSmallString(const char *string, size_type size)
|
||||
: BasicSmallString(string, size, size)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Type,
|
||||
typename = std::enable_if_t<std::is_pointer<Type>::value>
|
||||
>
|
||||
template<typename Type, typename = std::enable_if_t<std::is_pointer<Type>::value>>
|
||||
BasicSmallString(Type characterPointer)
|
||||
: BasicSmallString(characterPointer, std::strlen(characterPointer))
|
||||
: BasicSmallString(characterPointer, std::char_traits<char>::length(characterPointer))
|
||||
{
|
||||
static_assert(!std::is_array<Type>::value, "Input type is array and not char pointer!");
|
||||
}
|
||||
@@ -253,7 +249,7 @@ public:
|
||||
static
|
||||
BasicSmallString fromUtf8(const char *characterPointer)
|
||||
{
|
||||
return BasicSmallString(characterPointer, std::strlen(characterPointer));
|
||||
return BasicSmallString(characterPointer, std::char_traits<char>::length(characterPointer));
|
||||
}
|
||||
|
||||
void reserve(size_type newCapacity)
|
||||
@@ -271,7 +267,7 @@ public:
|
||||
const char *oldData = data();
|
||||
|
||||
char *newData = Memory::allocate(newCapacity + 1);
|
||||
std::memcpy(newData, oldData, oldSize);
|
||||
std::char_traits<char>::copy(newData, oldData, oldSize);
|
||||
m_data.allocated.data.pointer = newData;
|
||||
initializeLongString(oldSize, newCapacity);
|
||||
}
|
||||
@@ -380,7 +376,7 @@ public:
|
||||
|
||||
bool contains(char characterToSearch) const
|
||||
{
|
||||
auto found = std::memchr(data(), characterToSearch, size());
|
||||
auto found = std::char_traits<char>::find(data(), size(), characterToSearch);
|
||||
|
||||
return found != nullptr;
|
||||
}
|
||||
@@ -388,7 +384,9 @@ public:
|
||||
bool startsWith(SmallStringView subStringToSearch) const noexcept
|
||||
{
|
||||
if (size() >= subStringToSearch.size())
|
||||
return !std::memcmp(data(), subStringToSearch.data(), subStringToSearch.size());
|
||||
return !std::char_traits<char>::compare(data(),
|
||||
subStringToSearch.data(),
|
||||
subStringToSearch.size());
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -401,9 +399,10 @@ public:
|
||||
bool endsWith(SmallStringView subStringToSearch) const noexcept
|
||||
{
|
||||
if (size() >= subStringToSearch.size()) {
|
||||
const int comparison = std::memcmp(end().data() - subStringToSearch.size(),
|
||||
subStringToSearch.data(),
|
||||
subStringToSearch.size());
|
||||
const int comparison = std::char_traits<char>::compare(end().data()
|
||||
- subStringToSearch.size(),
|
||||
subStringToSearch.data(),
|
||||
subStringToSearch.size());
|
||||
return comparison == 0;
|
||||
}
|
||||
|
||||
@@ -462,7 +461,7 @@ public:
|
||||
size_type newSize = oldSize + string.size();
|
||||
|
||||
reserve(optimalCapacity(newSize));
|
||||
std::memcpy(data() + oldSize, string.data(), string.size());
|
||||
std::char_traits<char>::copy(data() + oldSize, string.data(), string.size());
|
||||
at(newSize) = 0;
|
||||
setSize(newSize);
|
||||
}
|
||||
@@ -724,7 +723,7 @@ private:
|
||||
at(size) = 0;
|
||||
}
|
||||
|
||||
void initializeLongString(size_type size, size_type capacity)
|
||||
constexpr void initializeLongString(size_type size, size_type capacity)
|
||||
{
|
||||
m_data.allocated.data.pointer[size] = 0;
|
||||
m_data.allocated.data.size = size;
|
||||
@@ -757,7 +756,7 @@ private:
|
||||
while (found != end()) {
|
||||
start = found + toText.size();
|
||||
|
||||
std::memcpy(found.data(), toText.data(), toText.size());
|
||||
std::char_traits<char>::copy(found.data(), toText.data(), toText.size());
|
||||
|
||||
found = std::search(start,
|
||||
end(),
|
||||
|
@@ -25,6 +25,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define constexpr17 constexpr
|
||||
#else
|
||||
#define constexpr17 inline
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#define constexpr20 constexpr
|
||||
#else
|
||||
#define constexpr20 inline
|
||||
#endif
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
namespace Utils {
|
||||
@@ -35,9 +47,4 @@ class BasicSmallString;
|
||||
using SmallString = BasicSmallString<31>;
|
||||
using PathString = BasicSmallString<190>;
|
||||
|
||||
inline
|
||||
int compare(SmallStringView first, SmallStringView second) noexcept;
|
||||
inline
|
||||
int reverseCompare(SmallStringView first, SmallStringView second) noexcept;
|
||||
|
||||
} // namespace Utils
|
||||
|
@@ -32,123 +32,94 @@ namespace Utils {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
template <class Category,
|
||||
class Type,
|
||||
typename DistanceType = ptrdiff_t,
|
||||
typename Pointer = Type*,
|
||||
typename Reference = Type&>
|
||||
struct SmallStringIterator : public std::iterator<Category, Type, DistanceType, Pointer, Reference>
|
||||
template<class Category,
|
||||
class Type,
|
||||
typename DistanceType = ptrdiff_t,
|
||||
typename Pointer = Type *,
|
||||
typename Reference = Type &>
|
||||
struct SmallStringIterator
|
||||
{
|
||||
constexpr
|
||||
SmallStringIterator() noexcept = default;
|
||||
using iterator_category = Category;
|
||||
using value_type = Type;
|
||||
using difference_type = DistanceType;
|
||||
using pointer = Pointer;
|
||||
using reference = Reference;
|
||||
|
||||
constexpr
|
||||
SmallStringIterator(Pointer ptr) noexcept : pointer_(ptr)
|
||||
{
|
||||
}
|
||||
constexpr SmallStringIterator() noexcept = default;
|
||||
|
||||
SmallStringIterator operator++() noexcept
|
||||
{
|
||||
return ++pointer_;
|
||||
}
|
||||
constexpr SmallStringIterator(Pointer ptr) noexcept
|
||||
: pointer_(ptr)
|
||||
{}
|
||||
|
||||
SmallStringIterator operator++(int) noexcept
|
||||
{
|
||||
return pointer_++;
|
||||
}
|
||||
constexpr SmallStringIterator operator++() noexcept { return ++pointer_; }
|
||||
|
||||
SmallStringIterator operator--() noexcept
|
||||
{
|
||||
return --pointer_;
|
||||
}
|
||||
constexpr SmallStringIterator operator++(int) noexcept { return pointer_++; }
|
||||
|
||||
SmallStringIterator operator--(int) noexcept
|
||||
{
|
||||
return pointer_--;
|
||||
}
|
||||
constexpr SmallStringIterator operator--() noexcept { return --pointer_; }
|
||||
|
||||
SmallStringIterator operator+(DistanceType difference) const noexcept
|
||||
constexpr SmallStringIterator operator--(int) noexcept { return pointer_--; }
|
||||
|
||||
constexpr SmallStringIterator operator+(DistanceType difference) const noexcept
|
||||
{
|
||||
return pointer_ + difference;
|
||||
}
|
||||
|
||||
SmallStringIterator operator-(DistanceType difference) const noexcept
|
||||
constexpr SmallStringIterator operator-(DistanceType difference) const noexcept
|
||||
{
|
||||
return pointer_ - difference;
|
||||
}
|
||||
|
||||
SmallStringIterator operator+(std::size_t difference) const noexcept
|
||||
constexpr SmallStringIterator operator+(std::size_t difference) const noexcept
|
||||
{
|
||||
return pointer_ + difference;
|
||||
}
|
||||
|
||||
SmallStringIterator operator-(std::size_t difference) const noexcept
|
||||
constexpr SmallStringIterator operator-(std::size_t difference) const noexcept
|
||||
{
|
||||
return pointer_ - difference;
|
||||
}
|
||||
|
||||
DistanceType operator-(SmallStringIterator other) const noexcept
|
||||
constexpr DistanceType operator-(SmallStringIterator other) const noexcept
|
||||
{
|
||||
return pointer_ - other.data();
|
||||
}
|
||||
|
||||
SmallStringIterator operator+=(DistanceType difference) noexcept
|
||||
constexpr SmallStringIterator operator+=(DistanceType difference) noexcept
|
||||
{
|
||||
return pointer_ += difference;
|
||||
}
|
||||
|
||||
SmallStringIterator operator-=(DistanceType difference) noexcept
|
||||
constexpr SmallStringIterator operator-=(DistanceType difference) noexcept
|
||||
{
|
||||
return pointer_ -= difference;
|
||||
}
|
||||
|
||||
Reference operator*() noexcept
|
||||
{
|
||||
return *pointer_;
|
||||
}
|
||||
constexpr Reference operator*() noexcept { return *pointer_; }
|
||||
|
||||
const Reference operator*() const noexcept
|
||||
{
|
||||
return *pointer_;
|
||||
}
|
||||
const Reference operator*() const noexcept { return *pointer_; }
|
||||
|
||||
Pointer operator->() noexcept
|
||||
{
|
||||
return pointer_;
|
||||
}
|
||||
constexpr Pointer operator->() noexcept { return pointer_; }
|
||||
|
||||
const Pointer operator->() const noexcept
|
||||
{
|
||||
return pointer_;
|
||||
}
|
||||
constexpr const Pointer operator->() const noexcept { return pointer_; }
|
||||
|
||||
constexpr
|
||||
bool operator==(SmallStringIterator other) const noexcept
|
||||
constexpr bool operator==(SmallStringIterator other) const noexcept
|
||||
{
|
||||
return pointer_ == other.pointer_;
|
||||
}
|
||||
|
||||
constexpr
|
||||
bool operator!=(SmallStringIterator other) const noexcept
|
||||
constexpr bool operator!=(SmallStringIterator other) const noexcept
|
||||
{
|
||||
return pointer_ != other.pointer_;
|
||||
}
|
||||
|
||||
constexpr
|
||||
bool operator<(SmallStringIterator other) const noexcept
|
||||
constexpr bool operator<(SmallStringIterator other) const noexcept
|
||||
{
|
||||
return pointer_ < other.pointer_;
|
||||
}
|
||||
|
||||
Pointer data() noexcept
|
||||
{
|
||||
return pointer_;
|
||||
}
|
||||
constexpr Pointer data() noexcept { return pointer_; }
|
||||
|
||||
const Pointer data() const noexcept
|
||||
{
|
||||
return pointer_;
|
||||
}
|
||||
constexpr const Pointer data() const noexcept { return pointer_; }
|
||||
|
||||
private:
|
||||
Pointer pointer_ = nullptr;
|
||||
|
@@ -49,30 +49,21 @@ struct ControlBlock
|
||||
m_isReference(isReference)
|
||||
{}
|
||||
|
||||
void setShortStringSize(size_type size)
|
||||
constexpr void setShortStringSize(size_type size)
|
||||
{
|
||||
m_shortStringSize = static_cast<SizeType>(size);
|
||||
}
|
||||
|
||||
size_type shortStringSize() const
|
||||
{
|
||||
return m_shortStringSize;
|
||||
}
|
||||
constexpr size_type shortStringSize() const { return m_shortStringSize; }
|
||||
|
||||
void setIsReadOnlyReference(bool isReadOnlyReference)
|
||||
constexpr void setIsReadOnlyReference(bool isReadOnlyReference)
|
||||
{
|
||||
m_isReadOnlyReference = isReadOnlyReference;
|
||||
}
|
||||
|
||||
void setIsReference(bool isReference)
|
||||
{
|
||||
m_isReference = isReference;
|
||||
}
|
||||
constexpr void setIsReference(bool isReference) { m_isReference = isReference; }
|
||||
|
||||
void setIsShortString(bool isShortString)
|
||||
{
|
||||
m_isReference = !isShortString;
|
||||
}
|
||||
constexpr void setIsShortString(bool isShortString) { m_isReference = !isShortString; }
|
||||
|
||||
constexpr
|
||||
SizeType stringSize() const
|
||||
@@ -168,7 +159,7 @@ struct StringDataLayout {
|
||||
|
||||
template<size_type Size,
|
||||
typename std::enable_if_t<Size <= MaximumShortStringDataAreaSize, int> = 0>
|
||||
StringDataLayout(const char(&string)[Size]) noexcept
|
||||
constexpr StringDataLayout(const char (&string)[Size]) noexcept
|
||||
: shortString(ShortStringLayout<MaximumShortStringDataAreaSize>{})
|
||||
{
|
||||
for (size_type i = 0; i < Size; ++i)
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "smallstringfwd.h"
|
||||
#include "smallstringiterator.h"
|
||||
|
||||
#include <QString>
|
||||
@@ -53,36 +54,32 @@ public:
|
||||
|
||||
constexpr SmallStringView() = default;
|
||||
|
||||
SmallStringView(const char *characterPointer) noexcept
|
||||
constexpr17 SmallStringView(const char *characterPointer) noexcept
|
||||
: m_pointer(characterPointer)
|
||||
, m_size(std::strlen(characterPointer))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr
|
||||
SmallStringView(const char *const string, const size_type size) noexcept
|
||||
: m_pointer(string),
|
||||
m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
: m_pointer(string.data()),
|
||||
m_size(string.size())
|
||||
, m_size(std::char_traits<char>::length(characterPointer))
|
||||
{}
|
||||
|
||||
static
|
||||
SmallStringView fromUtf8(const char *const characterPointer)
|
||||
constexpr SmallStringView(const char *const string, const size_type size) noexcept
|
||||
: m_pointer(string)
|
||||
, m_size(size)
|
||||
{
|
||||
return SmallStringView(characterPointer, std::strlen(characterPointer));
|
||||
}
|
||||
|
||||
constexpr 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>
|
||||
constexpr SmallStringView(const String &string) noexcept
|
||||
: m_pointer(string.data())
|
||||
, m_size(string.size())
|
||||
{}
|
||||
|
||||
static constexpr17 SmallStringView fromUtf8(const char *const characterPointer)
|
||||
{
|
||||
return SmallStringView(characterPointer);
|
||||
}
|
||||
|
||||
constexpr
|
||||
@@ -133,93 +130,85 @@ public:
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
constexpr17 const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept
|
||||
constexpr17 const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
return std::string(data(), size());
|
||||
}
|
||||
constexpr20 operator std::string() const { return std::string(data(), size()); }
|
||||
|
||||
explicit operator QString() const
|
||||
{
|
||||
return QString::fromUtf8(data(), int(size()));
|
||||
}
|
||||
|
||||
bool startsWith(SmallStringView subStringToSearch) const noexcept
|
||||
constexpr17 bool startsWith(SmallStringView subStringToSearch) const noexcept
|
||||
{
|
||||
if (size() >= subStringToSearch.size())
|
||||
return !std::memcmp(m_pointer, subStringToSearch.data(), subStringToSearch.size());
|
||||
return !std::char_traits<char>::compare(m_pointer,
|
||||
subStringToSearch.data(),
|
||||
subStringToSearch.size());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool startsWith(char characterToSearch) const noexcept
|
||||
constexpr bool startsWith(char characterToSearch) const noexcept
|
||||
{
|
||||
return m_pointer[0] == characterToSearch;
|
||||
}
|
||||
|
||||
char back() const { return m_pointer[m_size - 1]; }
|
||||
constexpr char back() const { return m_pointer[m_size - 1]; }
|
||||
|
||||
char operator[](std::size_t index) { return m_pointer[index]; }
|
||||
constexpr char operator[](std::size_t index) { return m_pointer[index]; }
|
||||
|
||||
private:
|
||||
const char *m_pointer = "";
|
||||
size_type m_size = 0;
|
||||
};
|
||||
|
||||
inline
|
||||
bool operator==(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr17 bool operator==(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
return first.size() == second.size() && std::memcmp(first.data(), second.data(), first.size()) == 0;
|
||||
return first.size() == second.size()
|
||||
&& std::char_traits<char>::compare(first.data(), second.data(), first.size()) == 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator!=(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr17 bool operator!=(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
inline
|
||||
int compare(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr17 int compare(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
int sizeDifference = int(first.size() - second.size());
|
||||
|
||||
if (sizeDifference == 0)
|
||||
return std::memcmp(first.data(), second.data(), first.size());
|
||||
return std::char_traits<char>::compare(first.data(), second.data(), first.size());
|
||||
|
||||
return sizeDifference;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator<(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr17 bool operator<(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
return compare(first, second) < 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator>(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr17 bool operator>(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
return second < first;
|
||||
}
|
||||
|
||||
namespace Internal {
|
||||
inline
|
||||
int reverse_memcmp(const char *first, const char *second, size_t n)
|
||||
constexpr int reverse_memcmp(const char *first, const char *second, size_t n)
|
||||
{
|
||||
|
||||
const char *currentFirst = first + n - 1;
|
||||
const char *currentSecond = second + n - 1;
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
while (n > 0) {
|
||||
// If the current characters differ, return an appropriately signed
|
||||
// value; otherwise, keep searching backwards
|
||||
int difference = *currentFirst - *currentSecond;
|
||||
@@ -233,10 +222,9 @@ int reverse_memcmp(const char *first, const char *second, size_t n)
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace Internal
|
||||
|
||||
inline
|
||||
int reverseCompare(SmallStringView first, SmallStringView second) noexcept
|
||||
constexpr int reverseCompare(SmallStringView first, SmallStringView second) noexcept
|
||||
{
|
||||
int sizeDifference = int(first.size() - second.size());
|
||||
|
||||
@@ -248,10 +236,7 @@ int reverseCompare(SmallStringView first, SmallStringView second) noexcept
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
#ifdef __cpp_user_defined_literals
|
||||
inline
|
||||
constexpr Utils::SmallStringView operator""_sv(const char *const string, size_t size)
|
||||
{
|
||||
return Utils::SmallStringView(string, size);
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user