delete_if, retain_if, rindex_of, compact, compact_count added to List.

This commit is contained in:
Christoffer Lerno
2023-04-21 12:15:35 +02:00
parent 809321e20c
commit 8059dc1539
24 changed files with 278 additions and 70 deletions

View File

@@ -4,6 +4,8 @@
module std::collections::list<Type>;
import std::math;
typedef ElementPredicate = fn bool(Type *type);
struct List
{
usz size;
@@ -196,6 +198,47 @@ fn void List.swap(List* list, usz i, usz j)
@swap(list.entries[i], list.entries[j]);
}
/**
* @param [&inout] list "The list to remove elements from"
* @param filter "The function to determine if it should be removed or not"
* @return "the number of deleted elements"
**/
fn usz List.delete_if(List* list, ElementPredicate filter)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
{
if (filter(&list.entries[i - 1])) continue;
for (usz j = i; j < size; j++)
{
list.entries[j - 1] = list.entries[j];
}
list.size--;
}
return size - list.size;
}
/**
* @param [&inout] list "The list to remove elements from"
* @param selection "The function to determine if it should be kept or not"
* @return "the number of deleted elements"
**/
fn usz List.retain_if(List* list, ElementPredicate selection)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
{
if (!selection(&list.entries[i - 1])) continue;
for (usz j = i; j < size; j++)
{
list.entries[j - 1] = list.entries[j];
}
list.size--;
}
return size - list.size;
}
/**
* Reserve at least min_capacity
**/
@@ -219,6 +262,19 @@ fn Type* List.get_ref(List* list, usz index) @operator(&[]) @inline
return &list.entries[index];
}
fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
{
usz new_size = list.size + added;
if (list.capacity > new_size) return;
assert(new_size < usz.max / 2U);
usz new_capacity = list.capacity ? 2U * list.capacity : 16U;
while (new_size >= new_capacity) new_capacity *= 2U;
list.reserve(new_capacity);
}
// Functions for equatable types
$if (types::is_equatable_type(Type))
fn usz! List.index_of(List* list, Type type)
@@ -230,6 +286,15 @@ fn usz! List.index_of(List* list, Type type)
return SearchResult.MISSING?;
}
fn usz! List.rindex_of(List* list, Type type)
{
foreach_r (i, v : list)
{
if (v == type) return i;
}
return SearchResult.MISSING?;
}
fn bool List.equals(List* list, List other_list)
{
if (list.size != other_list.size) return false;
@@ -240,24 +305,70 @@ fn bool List.equals(List* list, List other_list)
return true;
}
fn bool List.contains(List* list, Type type)
/**
* Check for presence of a value in a list.
*
* @param [&in] list "the list to find elements in"
* @param value "The value to search for"
* @return "True if the value is found, false otherwise"
**/
fn bool List.contains(List* list, Type value)
{
foreach (i, v : list)
{
if (v == type) return true;
if (v == value) return true;
}
return false;
}
/**
* @param [&inout] list "The list to remove elements from"
* @param value "The value to remove"
* @return "the number of deleted elements."
**/
fn usz List.delete(List* list, Type value)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
{
if (list.entries[i - 1] != value) continue;
for (usz j = i; j < size; j++)
{
list.entries[j - 1] = list.entries[j];
}
list.size--;
}
return size - list.size;
}
$endif
fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
{
usz new_size = list.size + added;
if (list.capacity > new_size) return;
$if (Type.kindof == POINTER)
assert(new_size < usz.max / 2U);
usz new_capacity = list.capacity ? 2U * list.capacity : 16U;
while (new_size >= new_capacity) new_capacity *= 2U;
list.reserve(new_capacity);
/**
* @param [&in] list
* @return "The number non-null values in the list"
**/
fn usz List.compact_count(List* list)
{
usz vals = 0;
foreach (v : list) if (v) vals++;
return vals;
}
fn usz List.compact(List* list)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
{
if (list.entries[i - 1]) continue;
for (usz j = i; j < size; j++)
{
list.entries[j - 1] = list.entries[j];
}
list.size--;
}
return size - list.size;
}
$endif