From 0b3d03121fbdf3ac913ee32e5a41c626488c95b0 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Fri, 22 May 2020 19:05:45 +0200 Subject: [PATCH] Utils: Modernize SmallString Use more C++ api and constexpr. With C++ 17 we can use even more. Change-Id: I33934cd7e087c311bf98501442df848bdb108279 Reviewed-by: Thomas Hartmann --- src/libs/utils/smallstring.h | 39 +++++----- src/libs/utils/smallstringfwd.h | 17 +++-- src/libs/utils/smallstringiterator.h | 101 +++++++++----------------- src/libs/utils/smallstringlayout.h | 21 ++---- src/libs/utils/smallstringview.h | 105 ++++++++++++--------------- 5 files changed, 118 insertions(+), 165 deletions(-) diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h index 473d9fba925..20d4a13e811 100644 --- a/src/libs/utils/smallstring.h +++ b/src/libs/utils/smallstring.h @@ -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::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::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::value> - > + template::value>> BasicSmallString(Type characterPointer) - : BasicSmallString(characterPointer, std::strlen(characterPointer)) + : BasicSmallString(characterPointer, std::char_traits::length(characterPointer)) { static_assert(!std::is_array::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::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::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::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::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::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::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::copy(found.data(), toText.data(), toText.size()); found = std::search(start, end(), diff --git a/src/libs/utils/smallstringfwd.h b/src/libs/utils/smallstringfwd.h index 05a8a9efb4f..0740cdf462b 100644 --- a/src/libs/utils/smallstringfwd.h +++ b/src/libs/utils/smallstringfwd.h @@ -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 diff --git a/src/libs/utils/smallstringiterator.h b/src/libs/utils/smallstringiterator.h index 82836d78c40..71c6a72a4a3 100644 --- a/src/libs/utils/smallstringiterator.h +++ b/src/libs/utils/smallstringiterator.h @@ -32,123 +32,94 @@ namespace Utils { namespace Internal { -template -struct SmallStringIterator : public std::iterator +template +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; diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h index c381fbd44bf..4ec5a07898e 100644 --- a/src/libs/utils/smallstringlayout.h +++ b/src/libs/utils/smallstringlayout.h @@ -49,30 +49,21 @@ struct ControlBlock m_isReference(isReference) {} - void setShortStringSize(size_type size) + constexpr void setShortStringSize(size_type size) { m_shortStringSize = static_cast(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 = 0> - StringDataLayout(const char(&string)[Size]) noexcept + constexpr StringDataLayout(const char (&string)[Size]) noexcept : shortString(ShortStringLayout{}) { for (size_type i = 0; i < Size; ++i) diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 6bdb1c6395a..039dc245a50 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -25,6 +25,7 @@ #pragma once +#include "smallstringfwd.h" #include "smallstringiterator.h" #include @@ -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 = 0> - SmallStringView(const String &string) noexcept - : m_pointer(string.data()), - m_size(string.size()) + , m_size(std::char_traits::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 = 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::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::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::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