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,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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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