[ox/std] Enable small string optimization by default

This commit is contained in:
Gary Talent 2021-12-01 01:10:58 -06:00
parent 457b97afba
commit 2c8f4cec2c
3 changed files with 21 additions and 20 deletions

View File

@ -10,6 +10,6 @@
namespace ox { namespace ox {
template class BasicString<0>; template class BasicString<8>;
} }

View File

@ -20,7 +20,7 @@
namespace ox { namespace ox {
template<std::size_t SmallStringSize = 8> template<std::size_t SmallStringSize>
class BasicString { class BasicString {
private: private:
Vector<char, SmallStringSize> m_buff; Vector<char, SmallStringSize> m_buff;
@ -208,9 +208,11 @@ constexpr BasicString<SmallStringSize>::BasicString() noexcept {
} }
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(std::size_t cap) noexcept { constexpr BasicString<SmallStringSize>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
m_buff.resize(cap + 1); // GCC complains if you don't do this pretty unnecessary size check
m_buff[0] = 0; if (m_buff.size()) {
m_buff[0] = 0;
}
} }
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
@ -247,7 +249,7 @@ constexpr BasicString<SmallStringSize>::BasicString(const BasicString &other) no
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(BasicString &&other) noexcept { constexpr BasicString<SmallStringSize>::BasicString(BasicString &&other) noexcept {
m_buff = move(other.m_buff); m_buff = std::move(other.m_buff);
} }
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
@ -499,8 +501,8 @@ constexpr std::size_t BasicString<SmallStringSize>::len() const noexcept {
return length; return length;
} }
extern template class BasicString<0>; extern template class BasicString<8>;
using String = BasicString<0>; using String = BasicString<8>;
} }

View File

@ -21,7 +21,7 @@ namespace ox {
namespace detail { namespace detail {
template<typename T, std::size_t Size = 100> template<typename T, std::size_t Size>
struct SmallVector { struct SmallVector {
private: private:
std::allocator<T> m_allocator; std::allocator<T> m_allocator;
@ -45,18 +45,20 @@ struct SmallVector {
const auto dstItems = reinterpret_cast<T*>(m_data); const auto dstItems = reinterpret_cast<T*>(m_data);
const auto srcItems = reinterpret_cast<T*>(src.m_data); const auto srcItems = reinterpret_cast<T*>(src.m_data);
for (auto i = 0u; i < count; ++i) { for (auto i = 0u; i < count; ++i) {
new (&dstItems[i]) T(move(srcItems[i])); new (&dstItems[i]) T(std::move(srcItems[i]));
} }
*items = reinterpret_cast<T*>(m_data); *items = reinterpret_cast<T*>(m_data);
} }
} }
constexpr void moveItemsFrom(T **items, SmallVector &src, const std::size_t count, const std::size_t cap) noexcept { constexpr void moveItemsFrom(T **items, SmallVector &src, const std::size_t count, const std::size_t cap) noexcept {
if (cap <= Size) { // this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
// try removing it later
if (cap <= Size && count <= Size) {
const auto dstItems = reinterpret_cast<T*>(m_data); const auto dstItems = reinterpret_cast<T*>(m_data);
const auto srcItems = reinterpret_cast<T*>(src.m_data); const auto srcItems = reinterpret_cast<T*>(src.m_data);
for (auto i = 0u; i < count; ++i) { for (std::size_t i = 0; i < count; ++i) {
dstItems[i] = move(srcItems[i]); dstItems[i] = std::move(srcItems[i]);
} }
*items = reinterpret_cast<T*>(m_data); *items = reinterpret_cast<T*>(m_data);
} }
@ -101,7 +103,7 @@ struct SmallVector<T, 0> {
} }
template<typename T, std::size_t SmallVectorSize = 0> template<typename T, std::size_t SmallVectorSize = 1>
class Vector: detail::SmallVector<T, SmallVectorSize> { class Vector: detail::SmallVector<T, SmallVectorSize> {
public: public:
@ -603,12 +605,9 @@ constexpr void Vector<T, SmallVectorSize>::expandCap(std::size_t cap) {
m_cap = cap; m_cap = cap;
this->allocate(&m_items, cap); this->allocate(&m_items, cap);
if (oldItems) { // move over old items if (oldItems) { // move over old items
const auto itRange = cap > m_size ? m_size : cap; const auto itRange = ox::min(cap, m_size);
for (std::size_t i = 0; i < itRange; i++) { for (std::size_t i = 0; i < itRange; ++i) {
new (&m_items[i]) T(move(oldItems[i])); new (&m_items[i]) T(std::move(oldItems[i]));
}
for (std::size_t i = itRange; i < m_cap; i++) {
new (&m_items[i]) T;
} }
this->deallocate(oldItems, m_cap); this->deallocate(oldItems, m_cap);
} }