forked from Bananymous/banan-os
				
			
			update main #1
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
#include <BAN/String.h>
 | 
			
		||||
#include <BAN/New.h>
 | 
			
		||||
#include <BAN/Variant.h>
 | 
			
		||||
 | 
			
		||||
namespace BAN
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -32,8 +31,7 @@ namespace BAN
 | 
			
		|||
	String& String::operator=(const String& other)
 | 
			
		||||
	{
 | 
			
		||||
		clear();
 | 
			
		||||
		if (!other.fits_in_sso())
 | 
			
		||||
			MUST(ensure_capacity(other.size()));
 | 
			
		||||
		MUST(ensure_capacity(other.size()));
 | 
			
		||||
		memcpy(data(), other.data(), other.size() + 1);
 | 
			
		||||
		m_size = other.size();
 | 
			
		||||
		return *this;
 | 
			
		||||
| 
						 | 
				
			
			@ -43,14 +41,18 @@ namespace BAN
 | 
			
		|||
	{
 | 
			
		||||
		clear();
 | 
			
		||||
 | 
			
		||||
		if (other.fits_in_sso())
 | 
			
		||||
		if (other.has_sso())
 | 
			
		||||
			memcpy(data(), other.data(), other.size() + 1);
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
		other.m_size = 0;
 | 
			
		||||
		other.m_storage = SSOStorage();
 | 
			
		||||
		other.m_storage.sso_storage = SSOStorage();
 | 
			
		||||
		other.m_has_sso = true;
 | 
			
		||||
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,8 +60,7 @@ namespace BAN
 | 
			
		|||
	String& String::operator=(StringView other)
 | 
			
		||||
	{
 | 
			
		||||
		clear();
 | 
			
		||||
		if (!fits_in_sso(other.size()))
 | 
			
		||||
			MUST(ensure_capacity(other.size()));
 | 
			
		||||
		MUST(ensure_capacity(other.size()));
 | 
			
		||||
		memcpy(data(), other.data(), other.size());
 | 
			
		||||
		m_size = other.size();
 | 
			
		||||
		data()[m_size] = '\0';
 | 
			
		||||
| 
						 | 
				
			
			@ -125,8 +126,9 @@ namespace BAN
 | 
			
		|||
	{
 | 
			
		||||
		if (!has_sso())
 | 
			
		||||
		{
 | 
			
		||||
			deallocator(m_storage.get<GeneralStorage>().data);
 | 
			
		||||
			m_storage = SSOStorage();
 | 
			
		||||
			deallocator(m_storage.general_storage.data);
 | 
			
		||||
			m_storage.sso_storage = SSOStorage();
 | 
			
		||||
			m_has_sso = true;
 | 
			
		||||
		}
 | 
			
		||||
		m_size = 0;
 | 
			
		||||
		data()[m_size] = '\0';
 | 
			
		||||
| 
						 | 
				
			
			@ -167,15 +169,6 @@ namespace BAN
 | 
			
		|||
			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;
 | 
			
		||||
		data()[m_size] = '\0';
 | 
			
		||||
		return {};
 | 
			
		||||
| 
						 | 
				
			
			@ -194,20 +187,21 @@ namespace BAN
 | 
			
		|||
 | 
			
		||||
		if (fits_in_sso())
 | 
			
		||||
		{
 | 
			
		||||
			char* data = m_storage.get<GeneralStorage>().data;
 | 
			
		||||
			m_storage = SSOStorage();
 | 
			
		||||
			memcpy(m_storage.get<SSOStorage>().storage, data, m_size + 1);
 | 
			
		||||
			char* data = m_storage.general_storage.data;
 | 
			
		||||
			m_storage.sso_storage = SSOStorage();
 | 
			
		||||
			m_has_sso = true;
 | 
			
		||||
			memcpy(this->data(), data, m_size + 1);
 | 
			
		||||
			deallocator(data);
 | 
			
		||||
			return {};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		GeneralStorage& storage = m_storage.get<GeneralStorage>();
 | 
			
		||||
		GeneralStorage& storage = m_storage.general_storage;
 | 
			
		||||
		if (storage.capacity == m_size)
 | 
			
		||||
			return {};
 | 
			
		||||
 | 
			
		||||
		char* new_data = (char*)allocator(m_size + 1);
 | 
			
		||||
		if (new_data == nullptr)
 | 
			
		||||
			return BAN::Error::from_errno(ENOMEM);
 | 
			
		||||
			return Error::from_errno(ENOMEM);
 | 
			
		||||
 | 
			
		||||
		memcpy(new_data, storage.data, m_size);
 | 
			
		||||
		deallocator(storage.data);
 | 
			
		||||
| 
						 | 
				
			
			@ -222,40 +216,45 @@ namespace BAN
 | 
			
		|||
	{
 | 
			
		||||
		if (has_sso())
 | 
			
		||||
			return sso_capacity;
 | 
			
		||||
		return m_storage.get<GeneralStorage>().capacity;
 | 
			
		||||
		return m_storage.general_storage.capacity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	char* String::data()
 | 
			
		||||
	{
 | 
			
		||||
		if (has_sso())
 | 
			
		||||
			return m_storage.get<SSOStorage>().storage;
 | 
			
		||||
		return m_storage.get<GeneralStorage>().data;
 | 
			
		||||
			return m_storage.sso_storage.data;
 | 
			
		||||
		return m_storage.general_storage.data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const char* String::data() const
 | 
			
		||||
	{
 | 
			
		||||
		if (has_sso())
 | 
			
		||||
			return m_storage.get<SSOStorage>().storage;
 | 
			
		||||
		return m_storage.get<GeneralStorage>().data;
 | 
			
		||||
			return m_storage.sso_storage.data;
 | 
			
		||||
		return m_storage.general_storage.data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {};
 | 
			
		||||
		
 | 
			
		||||
		char* new_data = (char*)allocator(new_size + 1);
 | 
			
		||||
		if (new_data == nullptr)
 | 
			
		||||
			return BAN::Error::from_errno(ENOMEM);
 | 
			
		||||
			return Error::from_errno(ENOMEM);
 | 
			
		||||
		
 | 
			
		||||
		memcpy(new_data, data(), m_size + 1);
 | 
			
		||||
 | 
			
		||||
		if (has_sso())
 | 
			
		||||
			m_storage = GeneralStorage();
 | 
			
		||||
		{
 | 
			
		||||
			m_storage.general_storage = GeneralStorage();
 | 
			
		||||
			m_has_sso = false;
 | 
			
		||||
		}
 | 
			
		||||
		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.data = new_data;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +263,7 @@ namespace BAN
 | 
			
		|||
 | 
			
		||||
	bool String::has_sso() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_storage.has<SSOStorage>();
 | 
			
		||||
		return m_has_sso;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,17 +82,21 @@ namespace BAN
 | 
			
		|||
	private:
 | 
			
		||||
		struct SSOStorage
 | 
			
		||||
		{
 | 
			
		||||
			char storage[sso_capacity + 1] {};
 | 
			
		||||
			char data[sso_capacity + 1] {};
 | 
			
		||||
		};
 | 
			
		||||
		struct GeneralStorage
 | 
			
		||||
		{
 | 
			
		||||
			size_type capacity { 0 };
 | 
			
		||||
			char* data;
 | 
			
		||||
			size_type capacity	{ 0 };
 | 
			
		||||
			char* data			{ nullptr };
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Variant<SSOStorage, GeneralStorage>	m_storage	{ SSOStorage() };
 | 
			
		||||
		size_type							m_size		{ 0 };
 | 
			
		||||
		union {
 | 
			
		||||
			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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue