forked from Bananymous/banan-os
update main #1
|
@ -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,7 +31,6 @@ 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();
|
||||||
|
@ -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,7 +60,6 @@ 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();
|
||||||
|
@ -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';
|
||||||
|
@ -167,15 +169,6 @@ namespace BAN
|
||||||
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';
|
||||||
return {};
|
return {};
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue