mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add .hash to integer types. Fixup of make and tmake. Updated map.c3 to become a working example. Fix bug in subarray -> pointer conversion. Search extension methods in std::core. Fix slice <-> slice copy.
This commit is contained in:
committed by
Christoffer Lerno
parent
4d5821408d
commit
ad18d9ba48
97
resources/examples/map.c3
Normal file
97
resources/examples/map.c3
Normal file
@@ -0,0 +1,97 @@
|
||||
module std::container::map <Key, Type>;
|
||||
import std::core::builtin;
|
||||
import std::io;
|
||||
fault MapResult
|
||||
{
|
||||
KEY_NOT_FOUND
|
||||
}
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Key key;
|
||||
Type value;
|
||||
usize hash;
|
||||
Entry* next;
|
||||
bool used;
|
||||
}
|
||||
|
||||
struct Map
|
||||
{
|
||||
usize size;
|
||||
Entry* map;
|
||||
uint mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require map != null
|
||||
**/
|
||||
fn void Map.init(Map *map, uint capacity = 128)
|
||||
{
|
||||
if (capacity < 16) capacity = 4;
|
||||
capacity = math::next_power_of_2(capacity);
|
||||
map.map = calloc(Entry.sizeof * capacity);
|
||||
map.mod = capacity - 1;
|
||||
}
|
||||
|
||||
fn Type! Map.valueForKey(Map *map, Key key)
|
||||
{
|
||||
if (!map.map) return MapResult.KEY_NOT_FOUND!;
|
||||
uint hash = key.hash();
|
||||
usize pos = hash & map.mod;
|
||||
Entry* entry = &map.map[pos];
|
||||
if (!entry) return MapResult.KEY_NOT_FOUND!;
|
||||
while (entry)
|
||||
{
|
||||
if (entry.hash == hash && entry.key == key) return entry.value;
|
||||
entry = entry.next;
|
||||
}
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
}
|
||||
|
||||
fn Type! Map.set(Map *map, Key key, Type value) @maydiscard
|
||||
{
|
||||
if (!map.map)
|
||||
{
|
||||
map.map = calloc(Entry.sizeof * 16);
|
||||
map.mod = 0x0F;
|
||||
}
|
||||
|
||||
uint hash = key.hash();
|
||||
uint pos = hash & map.mod;
|
||||
Entry *entry = &map.map[pos];
|
||||
while (1)
|
||||
{
|
||||
if (!entry.used)
|
||||
{
|
||||
entry.used = true;
|
||||
entry.value = value;
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
}
|
||||
if (entry.hash == hash && entry.key == key)
|
||||
{
|
||||
Type old = entry.value;
|
||||
entry.value = value;
|
||||
return old;
|
||||
}
|
||||
if (entry.next)
|
||||
{
|
||||
entry = entry.next;
|
||||
continue;
|
||||
}
|
||||
Entry* new = mem::calloc(Entry.sizeof);
|
||||
new.hash = hash;
|
||||
new.key = key;
|
||||
new.value = value;
|
||||
new.next = null;
|
||||
new.used = true;
|
||||
entry.next = new;
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
}
|
||||
}
|
||||
|
||||
fn usize Map.size(Map* map)
|
||||
{
|
||||
return map.size;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
module std::container::map <Key, Type>;
|
||||
|
||||
fault MapResult
|
||||
{
|
||||
KEY_NOT_FOUND
|
||||
}
|
||||
|
||||
public struct Entry
|
||||
{
|
||||
Key key;
|
||||
Type value;
|
||||
usize hash;
|
||||
Entry* next;
|
||||
}
|
||||
|
||||
public struct Map
|
||||
{
|
||||
usize size;
|
||||
void* map;
|
||||
uint mod;
|
||||
Allocator allocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require map != null
|
||||
**/
|
||||
public fn void Map.init(Map *map, Allocator allocator)
|
||||
{
|
||||
map.allocator = allocator;
|
||||
}
|
||||
|
||||
public fn Type! Map.valueForKey(Map *map, Key key)
|
||||
{
|
||||
if (!map.map) return null;
|
||||
usize hash = key.hash();
|
||||
usize pos = hash & map.mod;
|
||||
Entry* entry = &map.map[pop];
|
||||
if (!entry) return MapResult.KEY_NOT_FOUND!;
|
||||
while (entry)
|
||||
{
|
||||
if (entry.hash == hash && entry.key == key) return entry.value;
|
||||
entry = entry.next;
|
||||
}
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
}
|
||||
|
||||
public fn Type *Map.set(Map *map, Key key, Type value)
|
||||
{
|
||||
if (!map.map)
|
||||
{
|
||||
map.map = allocator.calloc(Entry, 16);
|
||||
map.mod = 0x0F;
|
||||
}
|
||||
|
||||
usize hash = key.hash();
|
||||
usize pos = hash & map.mod;
|
||||
Entry *entry = &map.map[pop];
|
||||
while (1)
|
||||
{
|
||||
if (!entry.value)
|
||||
{
|
||||
entry.value = value;
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
return nil;
|
||||
}
|
||||
if (entry.hash == hash && entry.key == key)
|
||||
{
|
||||
Type *old = entry.value;
|
||||
entry.value = value;
|
||||
return old;
|
||||
}
|
||||
if (entry.next)
|
||||
{
|
||||
entry = entry.next;
|
||||
}
|
||||
entry.next = allocator.alloc(Entry);
|
||||
entry = entry.next;
|
||||
}
|
||||
}
|
||||
|
||||
public fn usize Map.size(Map* map)
|
||||
{
|
||||
return map.size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user