BAN: Basic containers have shrink_to_fit() method
I also chaged the default memory allocation increase from 1.5 to 2
This commit is contained in:
parent
5d31e89574
commit
4afc4660a4
|
@ -185,6 +185,19 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> String::shrink_to_fit()
|
||||||
|
{
|
||||||
|
size_type temp = m_capacity;
|
||||||
|
m_capacity = 0;
|
||||||
|
auto error_or = ensure_capacity(m_size);
|
||||||
|
if (error_or.is_error())
|
||||||
|
{
|
||||||
|
m_capacity = temp;
|
||||||
|
return error_or;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
StringView String::sv() const
|
StringView String::sv() const
|
||||||
{
|
{
|
||||||
return StringView(*this);
|
return StringView(*this);
|
||||||
|
@ -214,7 +227,7 @@ namespace BAN
|
||||||
{
|
{
|
||||||
if (m_capacity >= size)
|
if (m_capacity >= size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||||
void* new_data = BAN::allocator(new_cap);
|
void* new_data = BAN::allocator(new_cap);
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::from_string("String: Could not allocate memory");
|
return Error::from_string("String: Could not allocate memory");
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Hash.h>
|
#include <BAN/Hash.h>
|
||||||
#include <BAN/LinkedList.h>
|
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
|
|
||||||
namespace BAN
|
namespace BAN
|
||||||
|
@ -29,6 +28,8 @@ namespace BAN
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> emplace(const Key&, Args&&...);
|
ErrorOr<void> emplace(const Key&, Args&&...);
|
||||||
|
|
||||||
|
ErrorOr<void> reserve(size_type);
|
||||||
|
|
||||||
void remove(const Key&);
|
void remove(const Key&);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -55,11 +56,11 @@ namespace BAN
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ErrorOr<void> rebucket(size_type);
|
ErrorOr<void> rebucket(size_type);
|
||||||
LinkedList<Entry>& get_bucket(const Key&);
|
Vector<Entry>& get_bucket(const Key&);
|
||||||
const LinkedList<Entry>& get_bucket(const Key&) const;
|
const Vector<Entry>& get_bucket(const Key&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<LinkedList<Entry>> m_buckets;
|
Vector<Vector<Entry>> m_buckets;
|
||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,6 +127,13 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Key, typename T, typename HASH>
|
||||||
|
ErrorOr<void> HashMap<Key, T, HASH>::reserve(size_type size)
|
||||||
|
{
|
||||||
|
TRY(rebucket(size));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Key, typename T, typename HASH>
|
template<typename Key, typename T, typename HASH>
|
||||||
void HashMap<Key, T, HASH>::remove(const Key& key)
|
void HashMap<Key, T, HASH>::remove(const Key& key)
|
||||||
{
|
{
|
||||||
|
@ -200,8 +208,8 @@ namespace BAN
|
||||||
if (m_buckets.size() >= bucket_count)
|
if (m_buckets.size() >= bucket_count)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
size_type new_bucket_count = BAN::Math::max<size_type>(bucket_count, m_buckets.size() * 3 / 2);
|
size_type new_bucket_count = BAN::Math::max<size_type>(bucket_count, m_buckets.size() * 2);
|
||||||
Vector<LinkedList<Entry>> new_buckets;
|
Vector<Vector<Entry>> new_buckets;
|
||||||
if (new_buckets.resize(new_bucket_count).is_error())
|
if (new_buckets.resize(new_bucket_count).is_error())
|
||||||
return Error::from_string("HashMap: Could not allocate memory");
|
return Error::from_string("HashMap: Could not allocate memory");
|
||||||
|
|
||||||
|
@ -222,7 +230,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename T, typename HASH>
|
template<typename Key, typename T, typename HASH>
|
||||||
LinkedList<typename HashMap<Key, T, HASH>::Entry>& HashMap<Key, T, HASH>::get_bucket(const Key& key)
|
Vector<typename HashMap<Key, T, HASH>::Entry>& HashMap<Key, T, HASH>::get_bucket(const Key& key)
|
||||||
{
|
{
|
||||||
ASSERT(!m_buckets.empty());
|
ASSERT(!m_buckets.empty());
|
||||||
auto index = HASH()(key) % m_buckets.size();
|
auto index = HASH()(key) % m_buckets.size();
|
||||||
|
@ -230,7 +238,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename T, typename HASH>
|
template<typename Key, typename T, typename HASH>
|
||||||
const LinkedList<typename HashMap<Key, T, HASH>::Entry>& HashMap<Key, T, HASH>::get_bucket(const Key& key) const
|
const Vector<typename HashMap<Key, T, HASH>::Entry>& HashMap<Key, T, HASH>::get_bucket(const Key& key) const
|
||||||
{
|
{
|
||||||
ASSERT(!m_buckets.empty());
|
ASSERT(!m_buckets.empty());
|
||||||
auto index = HASH()(key) % m_buckets.size();
|
auto index = HASH()(key) % m_buckets.size();
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace BAN
|
||||||
void remove(const T&);
|
void remove(const T&);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
ErrorOr<void> reserve(size_type);
|
||||||
|
|
||||||
const_iterator begin() const { return const_iterator(this, m_buckets.begin()); }
|
const_iterator begin() const { return const_iterator(this, m_buckets.begin()); }
|
||||||
const_iterator end() const { return const_iterator(this, m_buckets.end()); }
|
const_iterator end() const { return const_iterator(this, m_buckets.end()); }
|
||||||
|
|
||||||
|
@ -160,6 +162,13 @@ namespace BAN
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename HASH>
|
||||||
|
ErrorOr<void> HashSet<T, HASH>::reserve(size_type size)
|
||||||
|
{
|
||||||
|
TRY(rebucket(size));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename HASH>
|
template<typename T, typename HASH>
|
||||||
bool HashSet<T, HASH>::contains(const T& key) const
|
bool HashSet<T, HASH>::contains(const T& key) const
|
||||||
{
|
{
|
||||||
|
@ -185,7 +194,7 @@ namespace BAN
|
||||||
if (m_buckets.size() >= bucket_count)
|
if (m_buckets.size() >= bucket_count)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
size_type new_bucket_count = BAN::Math::max<size_type>(bucket_count, m_buckets.size() * 3 / 2);
|
size_type new_bucket_count = BAN::Math::max<size_type>(bucket_count, m_buckets.size() * 2);
|
||||||
Vector<Vector<T>> new_buckets;
|
Vector<Vector<T>> new_buckets;
|
||||||
if (new_buckets.resize(new_bucket_count).is_error())
|
if (new_buckets.resize(new_bucket_count).is_error())
|
||||||
return Error::from_string("HashSet: Could not allocate memory");
|
return Error::from_string("HashSet: Could not allocate memory");
|
||||||
|
|
|
@ -29,6 +29,9 @@ namespace BAN
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> emplace(Args&&...);
|
ErrorOr<void> emplace(Args&&...);
|
||||||
|
|
||||||
|
ErrorOr<void> reserve(size_type);
|
||||||
|
ErrorOr<void> shrink_to_fit();
|
||||||
|
|
||||||
void pop();
|
void pop();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -126,6 +129,27 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ErrorOr<void> Queue<T>::reserve(size_type size)
|
||||||
|
{
|
||||||
|
TRY(ensure_capacity(size));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ErrorOr<void> Queue<T>::shrink_to_fit()
|
||||||
|
{
|
||||||
|
size_type temp = m_capacity;
|
||||||
|
m_capacity = 0;
|
||||||
|
auto error_or = ensure_capacity(m_size);
|
||||||
|
if (error_or.is_error())
|
||||||
|
{
|
||||||
|
m_capacity = temp;
|
||||||
|
return error_or;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Queue<T>::pop()
|
void Queue<T>::pop()
|
||||||
{
|
{
|
||||||
|
@ -178,7 +202,7 @@ namespace BAN
|
||||||
{
|
{
|
||||||
if (m_capacity > size)
|
if (m_capacity > size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||||
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::from_string("Queue: Could not allocate memory");
|
return Error::from_string("Queue: Could not allocate memory");
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace BAN
|
||||||
ErrorOr<void> insert(StringView, size_type);
|
ErrorOr<void> insert(StringView, size_type);
|
||||||
ErrorOr<void> append(StringView);
|
ErrorOr<void> append(StringView);
|
||||||
ErrorOr<void> append(const String&);
|
ErrorOr<void> append(const String&);
|
||||||
|
|
||||||
void pop_back();
|
void pop_back();
|
||||||
void remove(size_type);
|
void remove(size_type);
|
||||||
void erase(size_type, size_type);
|
void erase(size_type, size_type);
|
||||||
|
@ -46,6 +46,7 @@ namespace BAN
|
||||||
|
|
||||||
ErrorOr<void> resize(size_type, char = '\0');
|
ErrorOr<void> resize(size_type, char = '\0');
|
||||||
ErrorOr<void> reserve(size_type);
|
ErrorOr<void> reserve(size_type);
|
||||||
|
ErrorOr<void> shrink_to_fit();
|
||||||
|
|
||||||
StringView sv() const;
|
StringView sv() const;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace BAN
|
||||||
|
|
||||||
ErrorOr<void> resize(size_type);
|
ErrorOr<void> resize(size_type);
|
||||||
ErrorOr<void> reserve(size_type);
|
ErrorOr<void> reserve(size_type);
|
||||||
|
ErrorOr<void> shrink_to_fit();
|
||||||
|
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
size_type size() const;
|
size_type size() const;
|
||||||
|
@ -330,6 +331,7 @@ namespace BAN
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& Vector<T>::front()
|
T& Vector<T>::front()
|
||||||
{
|
{
|
||||||
|
@ -358,6 +360,20 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ErrorOr<void> Vector<T>::shrink_to_fit()
|
||||||
|
{
|
||||||
|
size_type temp = m_capacity;
|
||||||
|
m_capacity = 0;
|
||||||
|
auto error_or = ensure_capacity(m_size);
|
||||||
|
if (error_or.is_error())
|
||||||
|
{
|
||||||
|
m_capacity = temp;
|
||||||
|
return error_or;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool Vector<T>::empty() const
|
bool Vector<T>::empty() const
|
||||||
{
|
{
|
||||||
|
@ -381,7 +397,7 @@ namespace BAN
|
||||||
{
|
{
|
||||||
if (m_capacity >= size)
|
if (m_capacity >= size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||||
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::from_string("Vector: Could not allocate memory");
|
return Error::from_string("Vector: Could not allocate memory");
|
||||||
|
|
Loading…
Reference in New Issue