update main #1

Merged
Sinipelto merged 240 commits from Bananymous/banan-os:main into main 2023-11-20 13:20:51 +02:00
2 changed files with 43 additions and 40 deletions
Showing only changes of commit f72fdeeb59 - Show all commits

View File

@ -1,6 +1,5 @@
#include <BAN/String.h> #include <BAN/String.h>
#include <BAN/New.h> #include <BAN/New.h>
#include <BAN/Variant.h>
namespace BAN namespace BAN
{ {
@ -32,8 +31,7 @@ namespace BAN
String& String::operator=(const String& other) String& String::operator=(const String& other)
{ {
clear(); clear();
if (!other.fits_in_sso()) MUST(ensure_capacity(other.size()));
MUST(ensure_capacity(other.size()));
memcpy(data(), other.data(), other.size() + 1); memcpy(data(), other.data(), other.size() + 1);
m_size = other.size(); m_size = other.size();
return *this; return *this;
@ -43,14 +41,18 @@ namespace BAN
{ {
clear(); clear();
if (other.fits_in_sso()) if (other.has_sso())
memcpy(data(), other.data(), other.size() + 1); memcpy(data(), other.data(), other.size() + 1);
else else
m_storage = other.m_storage.get<GeneralStorage>(); {
m_storage.general_storage = other.m_storage.general_storage;
m_has_sso = false;
}
m_size = other.m_size; m_size = other.m_size;
other.m_size = 0; other.m_size = 0;
other.m_storage = SSOStorage(); other.m_storage.sso_storage = SSOStorage();
other.m_has_sso = true;
return *this; return *this;
} }
@ -58,8 +60,7 @@ namespace BAN
String& String::operator=(StringView other) String& String::operator=(StringView other)
{ {
clear(); clear();
if (!fits_in_sso(other.size())) MUST(ensure_capacity(other.size()));
MUST(ensure_capacity(other.size()));
memcpy(data(), other.data(), other.size()); memcpy(data(), other.data(), other.size());
m_size = other.size(); m_size = other.size();
data()[m_size] = '\0'; data()[m_size] = '\0';
@ -125,8 +126,9 @@ namespace BAN
{ {
if (!has_sso()) if (!has_sso())
{ {
deallocator(m_storage.get<GeneralStorage>().data); deallocator(m_storage.general_storage.data);
m_storage = SSOStorage(); m_storage.sso_storage = SSOStorage();
m_has_sso = true;
} }
m_size = 0; m_size = 0;
data()[m_size] = '\0'; data()[m_size] = '\0';
@ -166,15 +168,6 @@ namespace BAN
data()[m_size] = '\0'; data()[m_size] = '\0';
return {}; return {};
} }
// shrink general -> sso
if (!has_sso() && fits_in_sso(new_size))
{
char* data = m_storage.get<GeneralStorage>().data;
m_storage = SSOStorage();
memcpy(m_storage.get<SSOStorage>().storage, data, new_size);
deallocator(data);
}
m_size = new_size; m_size = new_size;
data()[m_size] = '\0'; data()[m_size] = '\0';
@ -194,20 +187,21 @@ namespace BAN
if (fits_in_sso()) if (fits_in_sso())
{ {
char* data = m_storage.get<GeneralStorage>().data; char* data = m_storage.general_storage.data;
m_storage = SSOStorage(); m_storage.sso_storage = SSOStorage();
memcpy(m_storage.get<SSOStorage>().storage, data, m_size + 1); m_has_sso = true;
memcpy(this->data(), data, m_size + 1);
deallocator(data); deallocator(data);
return {}; return {};
} }
GeneralStorage& storage = m_storage.get<GeneralStorage>(); GeneralStorage& storage = m_storage.general_storage;
if (storage.capacity == m_size) if (storage.capacity == m_size)
return {}; return {};
char* new_data = (char*)allocator(m_size + 1); char* new_data = (char*)allocator(m_size + 1);
if (new_data == nullptr) if (new_data == nullptr)
return BAN::Error::from_errno(ENOMEM); return Error::from_errno(ENOMEM);
memcpy(new_data, storage.data, m_size); memcpy(new_data, storage.data, m_size);
deallocator(storage.data); deallocator(storage.data);
@ -222,40 +216,45 @@ namespace BAN
{ {
if (has_sso()) if (has_sso())
return sso_capacity; return sso_capacity;
return m_storage.get<GeneralStorage>().capacity; return m_storage.general_storage.capacity;
} }
char* String::data() char* String::data()
{ {
if (has_sso()) if (has_sso())
return m_storage.get<SSOStorage>().storage; return m_storage.sso_storage.data;
return m_storage.get<GeneralStorage>().data; return m_storage.general_storage.data;
} }
const char* String::data() const const char* String::data() const
{ {
if (has_sso()) if (has_sso())
return m_storage.get<SSOStorage>().storage; return m_storage.sso_storage.data;
return m_storage.get<GeneralStorage>().data; return m_storage.general_storage.data;
} }
ErrorOr<void> String::ensure_capacity(size_type new_size) ErrorOr<void> String::ensure_capacity(size_type new_size)
{ {
if (m_size >= new_size || fits_in_sso(new_size)) if (m_size >= new_size)
return {};
if (has_sso() && fits_in_sso(new_size))
return {}; return {};
char* new_data = (char*)allocator(new_size + 1); char* new_data = (char*)allocator(new_size + 1);
if (new_data == nullptr) if (new_data == nullptr)
return BAN::Error::from_errno(ENOMEM); return Error::from_errno(ENOMEM);
memcpy(new_data, data(), m_size + 1); memcpy(new_data, data(), m_size + 1);
if (has_sso()) if (has_sso())
m_storage = GeneralStorage(); {
m_storage.general_storage = GeneralStorage();
m_has_sso = false;
}
else else
deallocator(m_storage.get<GeneralStorage>().data); deallocator(m_storage.general_storage.data);
auto& storage = m_storage.get<GeneralStorage>(); auto& storage = m_storage.general_storage;
storage.capacity = new_size; storage.capacity = new_size;
storage.data = new_data; storage.data = new_data;
@ -264,7 +263,7 @@ namespace BAN
bool String::has_sso() const bool String::has_sso() const
{ {
return m_storage.has<SSOStorage>(); return m_has_sso;
} }
} }

View File

@ -82,17 +82,21 @@ namespace BAN
private: private:
struct SSOStorage struct SSOStorage
{ {
char storage[sso_capacity + 1] {}; char data[sso_capacity + 1] {};
}; };
struct GeneralStorage struct GeneralStorage
{ {
size_type capacity { 0 }; size_type capacity { 0 };
char* data; char* data { nullptr };
}; };
private: private:
Variant<SSOStorage, GeneralStorage> m_storage { SSOStorage() }; union {
size_type m_size { 0 }; SSOStorage sso_storage;
GeneralStorage general_storage;
} m_storage { .sso_storage = SSOStorage() };
size_type m_size : sizeof(size_type) * 8 - 1 { 0 };
size_type m_has_sso : 1 { true };
}; };
template<typename... Args> template<typename... Args>