mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add HashSet and String methods (#2386)
* Add `String.contains_char` using `String.index_of_char` and `HashSet.values` together with `HashSet.tvalues` --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
committed by
GitHub
parent
d07da2804e
commit
261184b5c1
@@ -332,10 +332,7 @@ macro HashMap.@each_entry(map; @body(entry))
|
||||
}
|
||||
}
|
||||
|
||||
fn Value[] HashMap.tvalues(&map)
|
||||
{
|
||||
return map.values(tmem) @inline;
|
||||
}
|
||||
fn Value[] HashMap.tvalues(&self) => self.values(tmem) @inline;
|
||||
|
||||
fn Value[] HashMap.values(&self, Allocator allocator)
|
||||
{
|
||||
|
||||
@@ -14,14 +14,14 @@ const Allocator SET_HEAP_ALLOCATOR = (Allocator)&dummy;
|
||||
<* Copy the ONHEAP allocator to initialize to a set that is heap allocated *>
|
||||
const HashSet ONHEAP = { .allocator = SET_HEAP_ALLOCATOR };
|
||||
|
||||
struct Entry
|
||||
struct Entry
|
||||
{
|
||||
uint hash;
|
||||
Value value;
|
||||
Entry* next;
|
||||
}
|
||||
|
||||
struct HashSet (Printable)
|
||||
struct HashSet (Printable)
|
||||
{
|
||||
Entry*[] table;
|
||||
Allocator allocator;
|
||||
@@ -39,7 +39,7 @@ fn int HashSet.len(&self) @operator(len) => (int) self.count;
|
||||
@require !self.is_initialized() : "Set was already initialized"
|
||||
@require capacity < MAXIMUM_CAPACITY : "Capacity cannot exceed maximum"
|
||||
*>
|
||||
fn HashSet* HashSet.init(&self, Allocator allocator, usz capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
fn HashSet* HashSet.init(&self, Allocator allocator, usz capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
capacity = math::next_power_of_2(capacity);
|
||||
self.allocator = allocator;
|
||||
@@ -285,7 +285,7 @@ fn usz HashSet.remove_all_from(&set, HashSet* other)
|
||||
<*
|
||||
Free all memory allocated by the hash set.
|
||||
*>
|
||||
fn void HashSet.free(&set)
|
||||
fn void HashSet.free(&set)
|
||||
{
|
||||
if (!set.is_initialized()) return;
|
||||
set.clear();
|
||||
@@ -329,7 +329,23 @@ fn void HashSet.reserve(&set, usz capacity)
|
||||
}
|
||||
}
|
||||
|
||||
fn Value[] HashSet.tvalues(&self) => self.values(tmem) @inline;
|
||||
|
||||
fn Value[] HashSet.values(&self, Allocator allocator)
|
||||
{
|
||||
if (!self.count) return {};
|
||||
Value[] list = allocator::alloc_array(allocator, Value, self.count);
|
||||
usz index = 0;
|
||||
foreach (Entry* entry : self.table)
|
||||
{
|
||||
while (entry)
|
||||
{
|
||||
list[index++] = entry.value;
|
||||
entry = entry.next;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// --- Set Operations ---
|
||||
|
||||
|
||||
@@ -427,6 +427,19 @@ fn bool String.contains(s, String substr)
|
||||
return @ok(s.index_of(substr));
|
||||
}
|
||||
|
||||
<*
|
||||
Check if a character is found in the string.
|
||||
|
||||
@param [in] s
|
||||
@param character : "The character to look for."
|
||||
@pure
|
||||
@return "true if the string contains the character, false otherwise"
|
||||
*>
|
||||
fn bool String.contains_char(s, char character)
|
||||
{
|
||||
return @ok(s.index_of_char(character));
|
||||
}
|
||||
|
||||
<*
|
||||
Check how many non-overlapping instances of a substring there is.
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
- Added array `@zip` and `@zip_into` macros. #2370
|
||||
- Updated termios bindings to use bitstructs and fixed some constants with incorrect values #2372
|
||||
- Added libloaderapi to `std::os::win32`.
|
||||
- Added `HashSet.values` and `String.contains_char` #2386
|
||||
|
||||
## 0.7.4 Change list
|
||||
|
||||
@@ -70,7 +71,7 @@
|
||||
- Formatting option "%h" now supports pointers.
|
||||
- Improve error on unsigned implicit conversion to signed.
|
||||
- Update error message for struct initialization #2286
|
||||
- Add SipHash family of keyed PRFs. #2287
|
||||
- Add SipHash family of keyed PRFs. #2287
|
||||
- `$is_const` is deprecated in favour of `@is_const` based on `$defined`.
|
||||
- Multiline contract comments #2113
|
||||
- Removed the use of temp allocator in backtrace printing.
|
||||
@@ -113,7 +114,7 @@
|
||||
- Array indices are now using int64 internally.
|
||||
- Bit shift operation fails with inline uint enum despite matching underlying type #2279.
|
||||
- Fix to codegen when using a bitstruct constant defined using a cast with an operator #2248.
|
||||
- Function pointers are now compile time constants.
|
||||
- Function pointers are now compile time constants.
|
||||
- Splat 8 arguments can sometimes cause incorrect behaviour in the compiler. #2283
|
||||
- Correctly poison the analysis after a failed $assert or $error. #2284
|
||||
- `$foo` variables could be assigned non-compile time values.
|
||||
@@ -217,7 +218,7 @@
|
||||
- Incorrect codegen if a macro ends with unreachable and is assigned to something. #2210
|
||||
- Fix error for named arguments-order with compile-time arguments #2212
|
||||
- Bug in AST copying would make operator overloading like `+=` compile incorrectly #2217.
|
||||
- `$defined(#expr)` broken with binary. #2219
|
||||
- `$defined(#expr)` broken with binary. #2219
|
||||
- Method ambiguity when importing parent module publicly in private submodule. #2208
|
||||
- Linker errors when shadowing @local with public function #2198
|
||||
- Bug when offsetting pointers of large structs using ++ and --.
|
||||
|
||||
@@ -184,7 +184,7 @@ fn void edge_cases()
|
||||
alias StringSet = HashSet{String};
|
||||
|
||||
fn void string_set_test()
|
||||
{
|
||||
{
|
||||
StringSet set;
|
||||
set.tinit();
|
||||
defer set.free();
|
||||
@@ -203,22 +203,114 @@ fn void string_set_test()
|
||||
}
|
||||
|
||||
fn void add_all_test()
|
||||
{
|
||||
StringSet set1;
|
||||
set1.init(mem);
|
||||
defer set1.free();
|
||||
|
||||
String[] list = {"hello", "world", "hello"};
|
||||
usz total = set1.add_all(list);
|
||||
assert(total == 2);
|
||||
|
||||
assert(set1.contains("hello"));
|
||||
assert(set1.contains("world"));
|
||||
assert(!set1.contains("foo"));
|
||||
|
||||
set1.remove("hello");
|
||||
assert(!set1.contains("hello"));
|
||||
assert(set1.len() == 1);
|
||||
|
||||
StringSet set2;
|
||||
set2.init(mem);
|
||||
defer set2.free();
|
||||
|
||||
total = set2.add_all({"foo", "bar"});
|
||||
assert(total == 2);
|
||||
|
||||
total = set2.add_all_from(&set1);
|
||||
assert(total == 1);
|
||||
|
||||
assert(set2.contains("foo"));
|
||||
assert(set2.contains("bar"));
|
||||
assert(set2.contains("world"));
|
||||
assert(!set2.contains("hello"));
|
||||
}
|
||||
|
||||
fn void remove_all_test()
|
||||
{
|
||||
String[] list1 = {"foo", "bar", "baz"};
|
||||
String[] list2 = {"Hello", "World", "foo"};
|
||||
String[] list3 = {"the", "C3", "compiler", "said", "Hello"};
|
||||
|
||||
StringSet set1;
|
||||
set1.init_from_values(mem, list1);
|
||||
defer set1.free();
|
||||
assert(set1.len() == 3);
|
||||
|
||||
StringSet set2;
|
||||
set2.init_from_values(mem, list1);
|
||||
defer set2.free();
|
||||
assert(set1.len() == 3);
|
||||
|
||||
usz total = set2.add_all(list2);
|
||||
assert(total == 2);
|
||||
assert(set2.len() == 5);
|
||||
|
||||
total = set2.remove_all(list1);
|
||||
assert(total == 3);
|
||||
|
||||
assert(set2.len() == 2);
|
||||
assert(set2.contains("Hello"));
|
||||
assert(set2.contains("World"));
|
||||
assert(!set2.contains("foo"));
|
||||
assert(!set2.contains("bar"));
|
||||
assert(!set2.contains("baz"));
|
||||
|
||||
total = set1.add_all(list3);
|
||||
assert(total == 5);
|
||||
assert(set1.len() == 8);
|
||||
|
||||
total = set1.remove_all_from(&set2);
|
||||
assert(total == 1);
|
||||
|
||||
assert(set1.len() == 7);
|
||||
assert(set1.contains("foo"));
|
||||
assert(set1.contains("bar"));
|
||||
assert(set1.contains("baz"));
|
||||
assert(set1.contains("the"));
|
||||
assert(set1.contains("C3"));
|
||||
assert(set1.contains("compiler"));
|
||||
assert(set1.contains("said"));
|
||||
assert(!set1.contains("Hello"));
|
||||
}
|
||||
|
||||
fn void values_test()
|
||||
{
|
||||
StringSet set;
|
||||
set.init(mem);
|
||||
defer set.free();
|
||||
|
||||
String[] list = { "hello", "world", "hello" };
|
||||
usz total = set.add_all(list);
|
||||
assert(total == 2);
|
||||
String[] values = set.values(mem);
|
||||
assert(values.len == 0);
|
||||
free(values);
|
||||
|
||||
assert(set.contains("hello"));
|
||||
assert(set.contains("world"));
|
||||
assert(!set.contains("foo"));
|
||||
String[] list1 = {"foo", "bar", "baz"};
|
||||
set.add_all(list1);
|
||||
assert(set.len() == 3);
|
||||
|
||||
set.remove("hello");
|
||||
assert(!set.contains("hello"));
|
||||
assert(set.len() == 1);
|
||||
values = set.values(mem);
|
||||
assert(values.len == 3);
|
||||
assert(array::contains(values, "foo"));
|
||||
assert(array::contains(values, "bar"));
|
||||
assert(array::contains(values, "baz"));
|
||||
free(values);
|
||||
|
||||
set.remove("bar");
|
||||
values = set.tvalues();
|
||||
assert(values.len == 2);
|
||||
assert(array::contains(values, "foo"));
|
||||
assert(array::contains(values, "baz"));
|
||||
assert(!array::contains(values, "bar"));
|
||||
}
|
||||
|
||||
fn void is_initialized_test()
|
||||
|
||||
@@ -255,6 +255,24 @@ fn void test_rindex_of_char()
|
||||
assert(@catch(test.index_of_char('x')));
|
||||
}
|
||||
|
||||
fn void test_contains()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.contains("o"));
|
||||
assert(test.contains("ll"));
|
||||
assert(test.contains(" hello"));
|
||||
assert(!test.contains("wi"));
|
||||
}
|
||||
|
||||
fn void contains_char()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.contains_char('o'));
|
||||
assert(test.contains_char('l'));
|
||||
assert(test.contains_char('h'));
|
||||
assert(!test.contains_char('x'));
|
||||
}
|
||||
|
||||
fn void test_base_13_convesion()
|
||||
{
|
||||
assert("13".to_long(13)!! == 13 + 3);
|
||||
|
||||
Reference in New Issue
Block a user