mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add HashSet implementation (#2322)
* Add HashSet implementation Add a generic HashSet with full allocator support and standard set operations. - Basic operations: add/remove/contains/clear - Set operations:union_set/intersection/symmetric_difference/difference/is_subset - Memory management with allocator support - Iteration support - Automatic resizing with load factor control * Add "add_all" "add_all_from" "remove_all" "remove_all_from" --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
231
test/unit/stdlib/collections/set.c3
Normal file
231
test/unit/stdlib/collections/set.c3
Normal file
@@ -0,0 +1,231 @@
|
||||
module set_test @test;
|
||||
import std::collections::set;
|
||||
|
||||
alias IntSet = HashSet{int};
|
||||
|
||||
fn void basic_operations()
|
||||
{
|
||||
IntSet set;
|
||||
defer set.free();
|
||||
|
||||
assert(set.is_empty());
|
||||
assert(!set.contains(1));
|
||||
|
||||
assert(set.add(1));
|
||||
assert(set.contains(1));
|
||||
assert(!set.is_empty());
|
||||
assert(set.len() == 1);
|
||||
|
||||
assert(!set.add(1));
|
||||
assert(set.len() == 1);
|
||||
|
||||
assert(set.add(2));
|
||||
assert(set.add(3));
|
||||
assert(set.len() == 3);
|
||||
assert(set.contains(2));
|
||||
assert(set.contains(3));
|
||||
|
||||
set.remove(2);
|
||||
assert(!set.contains(2));
|
||||
assert(set.len() == 2);
|
||||
|
||||
set.clear();
|
||||
assert(set.is_empty());
|
||||
assert(!set.contains(1));
|
||||
}
|
||||
|
||||
fn void initialization_methods()
|
||||
{
|
||||
IntSet set1;
|
||||
set1.tinit();
|
||||
defer set1.free();
|
||||
assert(set1.is_initialized());
|
||||
|
||||
IntSet set2;
|
||||
set2.tinit_with_values(1, 2, 3);
|
||||
defer set2.free();
|
||||
assert(set2.contains(1));
|
||||
assert(set2.contains(2));
|
||||
assert(set2.contains(3));
|
||||
assert(set2.len() == 3);
|
||||
|
||||
int[] values = {4, 5, 6};
|
||||
IntSet set3;
|
||||
set3.tinit_from_values(values);
|
||||
defer set3.free();
|
||||
assert(set3.contains(4));
|
||||
assert(set3.contains(5));
|
||||
assert(set3.contains(6));
|
||||
assert(set3.len() == 3);
|
||||
|
||||
IntSet set4;
|
||||
set4.tinit_from_set(&set3);
|
||||
defer set4.free();
|
||||
assert(set4.contains(4));
|
||||
assert(set4.contains(5));
|
||||
assert(set4.contains(6));
|
||||
assert(set4.len() == 3);
|
||||
}
|
||||
|
||||
fn void set_operations()
|
||||
{
|
||||
IntSet set1;
|
||||
set1.tinit_with_values(1, 2, 3);
|
||||
defer set1.free();
|
||||
|
||||
IntSet set2;
|
||||
set2.tinit_with_values(2, 3, 4);
|
||||
defer set2.free();
|
||||
|
||||
IntSet union_set = set1.tset_union(&set2);
|
||||
defer union_set.free();
|
||||
assert(union_set.contains(1));
|
||||
assert(union_set.contains(2));
|
||||
assert(union_set.contains(3));
|
||||
assert(union_set.contains(4));
|
||||
assert(union_set.len() == 4);
|
||||
|
||||
IntSet intersect_set = set1.tintersection(&set2);
|
||||
defer intersect_set.free();
|
||||
assert(intersect_set.contains(2));
|
||||
assert(intersect_set.contains(3));
|
||||
assert(!intersect_set.contains(1));
|
||||
assert(!intersect_set.contains(4));
|
||||
assert(intersect_set.len() == 2);
|
||||
|
||||
IntSet diff_set = set1.tdifference(&set2);
|
||||
assert(diff_set.contains(1));
|
||||
assert(!diff_set.contains(2));
|
||||
assert(!diff_set.contains(3));
|
||||
assert(!diff_set.contains(4));
|
||||
assert(diff_set.len() == 1);
|
||||
|
||||
IntSet sdiff_set = set1.tsymmetric_difference(&set2);
|
||||
assert(sdiff_set.contains(1));
|
||||
assert(!sdiff_set.contains(2));
|
||||
assert(!sdiff_set.contains(3));
|
||||
assert(sdiff_set.contains(4));
|
||||
assert(sdiff_set.len() == 2);
|
||||
|
||||
IntSet subset;
|
||||
subset.tinit_with_values(2, 3);
|
||||
defer subset.free();
|
||||
assert(subset.is_subset(&set1));
|
||||
assert(!set1.is_subset(&subset));
|
||||
}
|
||||
|
||||
fn void iterator_test()
|
||||
{
|
||||
IntSet set;
|
||||
set.tinit_with_values(1, 2, 3);
|
||||
defer set.free();
|
||||
|
||||
int count = 0;
|
||||
bool found1 = false; bool found2 = false; bool found3 = false;
|
||||
|
||||
set.@each(; int value)
|
||||
{
|
||||
count++;
|
||||
switch (value)
|
||||
{
|
||||
case 1: found1 = true;
|
||||
case 2: found2 = true;
|
||||
case 3: found3 = true;
|
||||
}
|
||||
};
|
||||
|
||||
assert(count == 3);
|
||||
assert(found1 && found2 && found3);
|
||||
|
||||
HashSetIterator {int} iter = set.iter();
|
||||
count = 0;
|
||||
while (@ok(iter.next()))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
assert(count == 3);
|
||||
}
|
||||
|
||||
fn void edge_cases()
|
||||
{
|
||||
IntSet empty;
|
||||
empty.tinit();
|
||||
defer empty.free();
|
||||
|
||||
assert(empty.is_empty());
|
||||
assert(!empty.contains(0));
|
||||
empty.remove(0); // Shouldn't crash
|
||||
|
||||
IntSet large;
|
||||
large.tinit();
|
||||
defer large.free();
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
large.add(i);
|
||||
}
|
||||
assert(large.len() == 1000);
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
assert(large.contains(i));
|
||||
}
|
||||
|
||||
assert(@catch(large.remove(1001)));
|
||||
assert(large.len() == 1000);
|
||||
|
||||
large.clear();
|
||||
assert(large.is_empty());
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
assert(!large.contains(i));
|
||||
}
|
||||
}
|
||||
|
||||
alias StringSet = HashSet{String};
|
||||
|
||||
fn void string_set_test()
|
||||
{
|
||||
StringSet set;
|
||||
set.tinit();
|
||||
defer set.free();
|
||||
|
||||
assert(set.add("hello"));
|
||||
assert(set.add("world"));
|
||||
assert(!set.add("hello"));
|
||||
|
||||
assert(set.contains("hello"));
|
||||
assert(set.contains("world"));
|
||||
assert(!set.contains("foo"));
|
||||
|
||||
set.remove("hello");
|
||||
assert(!set.contains("hello"));
|
||||
assert(set.len() == 1);
|
||||
}
|
||||
|
||||
fn void add_all_test()
|
||||
{
|
||||
StringSet set;
|
||||
set.init(mem);
|
||||
defer set.free();
|
||||
|
||||
String[] list = { "hello", "world", "hello" };
|
||||
usz total = set.add_all(list);
|
||||
assert(total == 2);
|
||||
|
||||
assert(set.contains("hello"));
|
||||
assert(set.contains("world"));
|
||||
assert(!set.contains("foo"));
|
||||
|
||||
set.remove("hello");
|
||||
assert(!set.contains("hello"));
|
||||
assert(set.len() == 1);
|
||||
}
|
||||
|
||||
fn void is_initialized_test()
|
||||
{
|
||||
IntSet test;
|
||||
assert(!test.is_initialized());
|
||||
test.tinit();
|
||||
assert(test.is_initialized());
|
||||
test.free();
|
||||
}
|
||||
Reference in New Issue
Block a user