Fix missing free on GrowableBitSet. init_new/init_temp for GrowableBitSet, LinkedList, List, HashMap, DString, ByteBuffer. Interface to_string renamed to_new_string. Change in allocator usage, malloc is now heap. Added new_array, new_zero_array, new, new_clear, clone. Concat => concat_new. string::printf => string::new_format, string::tprintf => string::tformat. "to_*" are now "to_new_*" and "to_temp_*". "from_*" is "new_from*"

This commit is contained in:
Christoffer Lerno
2023-11-06 23:20:41 +01:00
committed by Christoffer Lerno
parent 69470b8738
commit 1e38ccdd2b
77 changed files with 1049 additions and 1412 deletions

View File

@@ -82,14 +82,24 @@ struct GrowableBitSet
GrowableBitSetList data;
}
fn void GrowableBitSet.init(&self, usz initial_capacity = 1, Allocator* using = mem::heap())
/**
* @param initial_capacity
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
**/
fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap())
{
self.data.init(initial_capacity, using);
self.data.init_new(initial_capacity, allocator);
return self;
}
fn void GrowableBitSet.tinit(&self)
fn GrowableBitSet* GrowableBitSet.init_temp(&self, usz initial_capacity = 1)
{
self.init(.using = mem::temp());
return self.init_new(initial_capacity, mem::temp()) @inline;
}
fn void GrowableBitSet.free(&self)
{
self.data.free();
}
fn usz GrowableBitSet.cardinality(&self)

View File

@@ -25,9 +25,14 @@ fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic
return n;
}
fn String EnumMap.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String EnumMap.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
{
return string::printf("%s", *self);
return string::new_format("%s", *self, .allocator = allocator);
}
fn String EnumMap.to_tstring(&self) @dynamic
{
return string::tformat("%s", *self);
}
/**

View File

@@ -140,9 +140,14 @@ fn usz! EnumSet.to_format(&set, Formatter* formatter) @dynamic
return n;
}
fn String EnumSet.to_string(&set, Allocator* using = mem::heap()) @dynamic
fn String EnumSet.to_new_string(&set, Allocator* allocator = mem::heap()) @dynamic
{
return string::printf("%s", *set);
return string::new_format("%s", *set, .allocator = allocator);
}
fn String EnumSet.to_tstring(&set) @dynamic
{
return string::tformat("%s", *set);
}
module std::collections::enumset::private;

View File

@@ -28,12 +28,20 @@ fn void LinkedList.push_last(&self, Type value)
self.link_last(value);
}
fn void LinkedList.init(&self, Allocator* using = mem::heap())
/**
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
* @return "the initialized list"
**/
fn LinkedList* LinkedList.init_new(&self, Allocator* allocator = mem::heap())
{
*self = { .allocator = using };
*self = { .allocator = allocator };
return self;
}
fn void LinkedList.tinit(&self) => self.init(mem::temp()) @inline;
fn LinkedList* LinkedList.init_temp(&self)
{
return self.init_new(mem::temp()) @inline;
}
/**
* @require self.allocator
@@ -45,7 +53,7 @@ macro void LinkedList.free_node(&self, Node* node) @private
macro Node* LinkedList.alloc_node(&self) @private
{
if (!self.allocator) self.allocator = mem::heap();
return malloc(Node, .using = self.allocator);
return self.allocator.new(Node);
}
fn void LinkedList.link_first(&self, Type value) @private
@@ -175,7 +183,7 @@ fn void LinkedList.insert(&self, usz index, Type element)
fn void LinkedList.link_before(&self, Node *succ, Type value) @private
{
Node* pred = succ.prev;
Node* new_node = malloc(Node);
Node* new_node = self.alloc_node();
*new_node = { .prev = pred, .next = succ, .value = value };
succ.prev = new_node;
if (!pred)

View File

@@ -19,36 +19,42 @@ struct List (Printable)
}
/**
* @require using "A valid allocator must be provided"
* @param initial_capacity "The initial capacity to reserve"
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
**/
fn void List.init(&self, usz initial_capacity = 16, Allocator* using = mem::heap())
fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap())
{
self.allocator = using;
self.allocator = allocator;
self.size = 0;
if (initial_capacity > 0)
{
initial_capacity = math::next_power_of_2(initial_capacity);
self.entries = malloc_aligned(Type, initial_capacity, .alignment = Type[1].alignof, .using = using)!!;
self.entries = allocator.alloc_aligned(Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!;
}
else
{
self.entries = null;
}
self.capacity = initial_capacity;
}
fn void List.tinit(&self, usz initial_capacity = 16)
{
self.init(initial_capacity, mem::temp()) @inline;
return self;
}
/**
* Initialize the list using the temp allocator.
*
* @param initial_capacity "The initial capacity to reserve"
**/
fn List* List.init_temp(&self, usz initial_capacity = 16)
{
return self.init_new(initial_capacity, mem::temp()) @inline;
}
/**
* Initialize the List by referencing the provided types.
* @require self.size == 0 "The List must be empty"
**/
fn void List.init_wrapping_array(&self, Type[] types, Allocator* using = mem::heap())
fn void List.init_wrapping_array(&self, Type[] types, Allocator* allocator = mem::heap())
{
self.allocator = using;
self.allocator = allocator;
self.size = types.len;
self.capacity = types.len;
self.entries = types.ptr;
@@ -74,9 +80,14 @@ fn usz! List.to_format(&self, Formatter* formatter) @dynamic
}
}
fn String List.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String List.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
{
return string::printf("%s", *self);
return string::new_format("%s", *self, .allocator = allocator);
}
fn String List.to_tstring(&self)
{
return string::tformat("%s", *self);
}
fn void List.push(&self, Type element) @inline
@@ -136,14 +147,19 @@ fn void List.add_all(&self, List* other_list)
}
fn Type[] List.to_array(&self, Allocator* using = mem::heap())
fn Type[] List.to_new_array(&self, Allocator* allocator = mem::heap())
{
if (!self.size) return Type[] {};
Type[] result = malloc(Type, self.size, .using = using);
Type[] result = allocator.new_array(Type, self.size);
result[..] = self.entries[:self.size];
return result;
}
fn Type[] List.to_tarray(&self)
{
return self.to_new_array(mem::temp());
}
/**
* Reverse the elements in a list.
**/
@@ -244,7 +260,7 @@ fn Type List.get(&self, usz index) @inline
fn void List.free(&self)
{
if (!self.allocator) return;
free_aligned(self.entries, .using = self.allocator);
self.allocator.free_aligned(self.entries);
self.capacity = 0;
self.size = 0;
self.entries = null;
@@ -342,7 +358,7 @@ fn void List.reserve(&self, usz min_capacity)
if (self.capacity >= min_capacity) return;
if (!self.allocator) self.allocator = mem::heap();
min_capacity = math::next_power_of_2(min_capacity);
self.entries = realloc_aligned(self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof, .using = self.allocator) ?? null;
self.entries = self.allocator.realloc_aligned(self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof) ?? null;
self.capacity = min_capacity;
}

View File

@@ -20,19 +20,20 @@ struct HashMap
}
/**
* @param [&inout] allocator "The allocator to use"
* @require capacity > 0 "The capacity must be 1 or higher"
* @require load_factor > 0.0 "The load factor must be higher than 0"
* @require !map.allocator "Map was already initialized"
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
* @require (bool)using "The allocator must be non-null"
**/
fn void HashMap.init(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* using = mem::heap())
fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap())
{
capacity = math::next_power_of_2(capacity);
map.allocator = using;
map.allocator = allocator;
map.load_factor = load_factor;
map.threshold = (uint)(capacity * load_factor);
map.table = calloc(Entry*, capacity, .using = using);
map.table = allocator.new_zero_array(Entry*, capacity);
return map;
}
/**
@@ -41,9 +42,9 @@ fn void HashMap.init(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_
* @require !map.allocator "Map was already initialized"
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
**/
fn void HashMap.tinit(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
fn HashMap* HashMap.init_temp(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
{
map.init(capacity, load_factor, mem::temp());
return map.init_new(capacity, load_factor, mem::temp());
}
/**
@@ -57,15 +58,23 @@ fn bool HashMap.is_initialized(&map)
return (bool)map.allocator;
}
fn void HashMap.init_from_map(&map, HashMap* other_map, Allocator* using = mem::heap())
/**
* @param [&inout] allocator "The allocator to use"
* @param [&in] other_map "The map to copy from."
**/
fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap())
{
map.init(other_map.table.len, other_map.load_factor, using);
map.put_all_for_create(other_map);
self.init_new(other_map.table.len, other_map.load_factor, allocator);
self.put_all_for_create(other_map);
return self;
}
fn void HashMap.tinit_from_map(&map, HashMap* other_map)
/**
* @param [&in] other_map "The map to copy from."
**/
fn HashMap* HashMap.init_temp_from_map(&map, HashMap* other_map)
{
map.init_from_map(other_map, mem::temp()) @inline;
return map.init_new_from_map(other_map, mem::temp()) @inline;
}
fn bool HashMap.is_empty(&map) @inline
@@ -137,7 +146,7 @@ fn bool HashMap.set(&map, Key key, Value value) @operator([]=)
// If the map isn't initialized, use the defaults to initialize it.
if (!map.allocator)
{
map.init();
map.init_new();
}
uint hash = rehash(key.hash());
uint index = index_for(hash, map.table.len);
@@ -188,14 +197,14 @@ fn void HashMap.free(&map)
fn Key[] HashMap.key_tlist(&map)
{
return map.key_list(mem::temp()) @inline;
return map.key_new_list(mem::temp()) @inline;
}
fn Key[] HashMap.key_list(&map, Allocator* using = mem::heap())
fn Key[] HashMap.key_new_list(&map, Allocator* allocator = mem::heap())
{
if (!map.count) return {};
Key[] list = calloc(Key, map.count, .using = using);
Key[] list = allocator.new_array(Key, map.count);
usz index = 0;
foreach (Entry* entry : map.table)
{
@@ -232,13 +241,13 @@ macro HashMap.@each_entry(map; @body(entry))
fn Value[] HashMap.value_tlist(&map)
{
return map.value_list(mem::temp()) @inline;
return map.value_new_list(mem::temp()) @inline;
}
fn Value[] HashMap.value_list(&map, Allocator* using = mem::heap())
fn Value[] HashMap.value_new_list(&map, Allocator* allocator = mem::heap())
{
if (!map.count) return {};
Value[] list = calloc(Value, map.count, .using = using);
Value[] list = allocator.new_array(Value, map.count);
usz index = 0;
foreach (Entry* entry : map.table)
{
@@ -269,7 +278,7 @@ fn bool HashMap.has_value(&map, Value v) @if(VALUE_IS_EQUATABLE)
fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private
{
Entry* entry = malloc(Entry, .using = map.allocator);
Entry* entry = map.allocator.new(Entry);
$if COPY_KEYS:
key = key.copy(map.allocator);
$endif
@@ -290,7 +299,7 @@ fn void HashMap.resize(&map, uint new_capacity) @private
map.threshold = uint.max;
return;
}
Entry*[] new_table = calloc(Entry*, new_capacity, .using = map.allocator);
Entry*[] new_table = map.allocator.new_zero_array(Entry*, new_capacity);
map.transfer(new_table);
map.table = new_table;
map.free_internal(old_table.ptr);
@@ -389,7 +398,7 @@ fn bool HashMap.remove_entry_for_key(&map, Key key) @private
fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private
{
Entry *e = map.table[bucket_index];
Entry* entry = malloc(Entry, .using = map.allocator);
Entry* entry = map.allocator.new(Entry);
$if COPY_KEYS:
key = key.copy(map.allocator);
$endif
@@ -401,7 +410,7 @@ fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_i
fn void HashMap.free_entry(&self, Entry *entry) @local
{
$if COPY_KEYS:
entry.key.free(self.allocator);
self.allocator.free(entry.key);
$endif
self.free_internal(entry);
}

View File

@@ -78,10 +78,10 @@ fn usz! Object.to_format(&self, Formatter* formatter) @dynamic
}
}
fn Object* new_obj(Allocator* using = mem::heap())
fn Object* new_obj(Allocator* allocator)
{
Object* o = malloc(Object, .using = using);
*o = { .allocator = using, .type = void.typeid };
Object* o = allocator.new(Object);
*o = { .allocator = allocator, .type = void.typeid };
return o;
}
@@ -90,31 +90,31 @@ fn Object* new_null()
return &NULL_OBJECT;
}
fn Object* new_int(int128 i, Allocator* using = mem::heap())
fn Object* new_int(int128 i, Allocator* allocator)
{
Object* o = malloc(Object, .using = using);
*o = { .i = i, .allocator = using, .type = int128.typeid };
Object* o = allocator.new(Object);
*o = { .i = i, .allocator = allocator, .type = int128.typeid };
return o;
}
macro Object* new_enum(e, Allocator* using = mem::heap())
macro Object* new_enum(e, Allocator* allocator)
{
Object* o = malloc(Object, .using = using);
*o = { .i = (int128)e, .allocator = using, .type = $typeof(e).typeid };
Object* o = allocator.new(Object);
*o = { .i = (int128)e, .allocator = allocator, .type = $typeof(e).typeid };
return o;
}
fn Object* new_float(double f, Allocator* using = mem::heap())
fn Object* new_float(double f, Allocator* allocator)
{
Object* o = malloc(Object, .using = using);
*o = { .f = f, .allocator = using, .type = double.typeid };
Object* o = allocator.new(Object);
*o = { .f = f, .allocator = allocator, .type = double.typeid };
return o;
}
fn Object* new_string(String s, Allocator* using = mem::heap())
fn Object* new_string(String s, Allocator* allocator)
{
Object* o = malloc(Object, .using = using);
*o = { .s = s.copy(using), .allocator = using, .type = String.typeid };
Object* o = allocator.new(Object);
*o = { .s = s.copy(allocator), .allocator = allocator, .type = String.typeid };
return o;
}
@@ -131,7 +131,7 @@ fn void Object.free(&self)
case void:
break;
case String:
free(self.s, .using = self.allocator);
self.allocator.free(self.s);
case ObjectInternalList:
foreach (ol : self.array)
{
@@ -140,13 +140,13 @@ fn void Object.free(&self)
self.array.free();
case ObjectInternalMap:
self.map.@each_entry(; ObjectInternalMapEntry* entry) {
free(entry.key, .using = self.allocator);
self.allocator.free(entry.key);
entry.value.free();
};
default:
break;
}
if (self.allocator) free(self, .using = self.allocator);
if (self.allocator) self.allocator.free(self);
}
fn bool Object.is_null(&self) @inline => self == &NULL_OBJECT;
@@ -168,7 +168,7 @@ fn void Object.init_map_if_needed(&self) @private
if (self.is_empty())
{
self.type = ObjectInternalMap.typeid;
self.map.init(.using = self.allocator);
self.map.init_new(.allocator = self.allocator);
}
}
@@ -180,7 +180,7 @@ fn void Object.init_array_if_needed(&self) @private
if (self.is_empty())
{
self.type = ObjectInternalList.typeid;
self.array.init(.using = self.allocator);
self.array.init_new(.allocator = self.allocator);
}
}
@@ -193,7 +193,7 @@ fn void Object.set_object(&self, String key, Object* new_object) @private
ObjectInternalMapEntry*! entry = self.map.get_entry(key);
defer
{
(void)free(entry.key, .using = self.allocator);
(void)self.allocator.free(entry.key);
(void)entry.value.free();
}
self.map.set(key.copy(self.map.allocator), new_object);

View File

@@ -31,19 +31,19 @@ import std::collections::list;
def Heap = List(<Type>);
struct PrivatePriorityQueue
struct PrivatePriorityQueue (Printable)
{
Heap heap;
}
fn void PrivatePriorityQueue.init(&self, usz initial_capacity = 16, Allocator* using = mem::heap()) @inline
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline
{
self.heap.init(initial_capacity, using);
self.heap.init_new(initial_capacity, allocator);
}
fn void PrivatePriorityQueue.tinit(&self, usz initial_capacity = 16) @inline
fn void PrivatePriorityQueue.init_temp(&self, usz initial_capacity = 16) @inline
{
self.init(initial_capacity, mem::temp());
self.heap.init_new(initial_capacity, mem::temp()) @inline;
}
fn void PrivatePriorityQueue.push(&self, Type element)
@@ -133,13 +133,13 @@ fn Type PrivatePriorityQueue.peek_at(&self, usz index) @operator([])
return self.heap[index];
}
fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter)
fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter) @dynamic
{
return self.heap.to_format(formatter);
}
fn String PrivatePriorityQueue.to_string(&self, Allocator* using = mem::heap())
fn String PrivatePriorityQueue.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
{
return self.heap.to_string(using);
return self.heap.to_new_string(allocator);
}

View File

@@ -28,9 +28,14 @@ fn Type Range.get(&self, usz index) @operator([])
return (Type)(self.start + (usz)index);
}
fn String Range.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String Range.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
{
return string::printf("[%s..%s]", self.start, self.end);
return string::new_format("[%s..%s]", self.start, self.end, .allocator = allocator);
}
fn String Range.to_tstring(&self)
{
return self.to_new_string(mem::temp());
}
fn usz! Range.to_format(&self, Formatter* formatter) @dynamic
@@ -60,9 +65,14 @@ fn usz! ExclusiveRange.to_format(&self, Formatter* formatter) @dynamic
return formatter.printf("[%s..<%s]", self.start, self.end)!;
}
fn String ExclusiveRange.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String ExclusiveRange.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
{
return string::printf("[%s..<%s]", self.start, self.end);
return string::new_format("[%s..<%s]", self.start, self.end, .allocator = allocator);
}
fn String ExclusiveRange.to_tstring(&self)
{
return self.to_new_string(mem::temp());
}
/**