use meta.check_bounds, improvements to stable_array
This commit is contained in:
parent
3feb2f98c9
commit
71964e8aea
2 changed files with 80 additions and 65 deletions
|
|
@ -6,20 +6,71 @@ Stable_Array :: struct(T: Type, ITEMS_PER_CHUNK := 32) {
|
||||||
Chunk :: Static_Array(ITEMS_PER_CHUNK, T);
|
Chunk :: Static_Array(ITEMS_PER_CHUNK, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init :: (a: *Stable_Array, allocator: Allocator) {
|
||||||
|
a.allocator = allocator;
|
||||||
|
a.chunks.allocator = allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
append :: (a: *Stable_Array) -> *a.T {
|
||||||
|
chunk := find_or_create_chunk(a, 1);
|
||||||
|
item := append(chunk);
|
||||||
|
a.count += 1;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
append :: (a: *Stable_Array, value: a.T) -> *a.T {
|
||||||
|
chunk := find_or_create_chunk(a, 1);
|
||||||
|
item := append(chunk, value);
|
||||||
|
a.count += 1;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
append :: (a: *Stable_Array, values: ..a.T) -> *a.T {
|
||||||
|
first: *a.T;
|
||||||
|
for values {
|
||||||
|
if first == null {
|
||||||
|
first = inline append(a, it);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inline append(a, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset :: (a: *Stable_Array) {
|
||||||
|
for a.chunks it.count = 0;
|
||||||
|
a.count = 0;
|
||||||
|
a.chunks.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
operator [] :: (a: Stable_Array, index: int, loc := #caller_location) -> a.T #no_abc {
|
operator [] :: (a: Stable_Array, index: int, loc := #caller_location) -> a.T #no_abc {
|
||||||
b_idx := index / a.ITEMS_PER_CHUNK;
|
b_idx := index / a.ITEMS_PER_CHUNK;
|
||||||
i_idx := index % a.ITEMS_PER_CHUNK;
|
i_idx := index % a.ITEMS_PER_CHUNK;
|
||||||
assert(b_idx < a.chunks.count && i_idx < a.chunks[b_idx].count);
|
meta.check_bounds(b_idx, a.chunks.count, loc = loc);
|
||||||
|
meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc);
|
||||||
return a.chunks[b_idx].items[i_idx];
|
return a.chunks[b_idx].items[i_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
operator *[] :: (a: *Stable_Array, index: int, loc := #caller_location) -> *a.T #no_abc {
|
operator *[] :: (a: *Stable_Array, index: int, loc := #caller_location) -> *a.T #no_abc {
|
||||||
b_idx := index / a.ITEMS_PER_CHUNK;
|
b_idx := index / a.ITEMS_PER_CHUNK;
|
||||||
i_idx := index % a.ITEMS_PER_CHUNK;
|
i_idx := index % a.ITEMS_PER_CHUNK;
|
||||||
assert(b_idx < a.chunks.count && i_idx < a.chunks[b_idx].count);
|
meta.check_bounds(b_idx, a.chunks.count, loc = loc);
|
||||||
|
meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc);
|
||||||
return *a.chunks[b_idx].items[i_idx];
|
return *a.chunks[b_idx].items[i_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator []= :: (a: *Stable_Array, index: int, value: a.T, loc := #caller_location) #no_abc {
|
||||||
|
c_idx := index / a.ITEMS_PER_CHUNK;
|
||||||
|
i_idx := index % a.ITEMS_PER_CHUNK;
|
||||||
|
meta.check_bounds(c_idx, a.chunks.count, loc = loc);
|
||||||
|
meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc);
|
||||||
|
|
||||||
|
chunk := a.chunks[c_idx];
|
||||||
|
chunk.items[i_idx] = value;
|
||||||
|
}
|
||||||
|
|
||||||
for_expansion :: (a: Stable_Array, body: Code, flags: For_Flags) #expand {
|
for_expansion :: (a: Stable_Array, body: Code, flags: For_Flags) #expand {
|
||||||
for i: 0..a.count - 1 {
|
for i: 0..a.count - 1 {
|
||||||
`it := a[i];
|
`it := a[i];
|
||||||
|
|
@ -28,76 +79,38 @@ for_expansion :: (a: Stable_Array, body: Code, flags: For_Flags) #expand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
append :: (a: *Stable_Array) -> *a.T {
|
|
||||||
chunk := get_chunk(a, 1);
|
|
||||||
item := append(chunk);
|
|
||||||
a.count += 1;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
append :: (a: *Stable_Array, value: a.T) -> *a.T {
|
|
||||||
chunk := get_chunk(a, 1);
|
|
||||||
item := append(chunk, value);
|
|
||||||
a.count += 1;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
append :: (a: *Stable_Array, values: ..a.T) -> *a.T {
|
|
||||||
first: *a.T;
|
|
||||||
for values {
|
|
||||||
if first == null {
|
|
||||||
first = append(a, it);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
append(a, it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset :: (a: *Stable_Array, $keep_memory := true) {
|
|
||||||
#if keep_memory {
|
|
||||||
for a.chunks it.count = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for a.chunks mem.release_memory(it,, allocator = a.allocator);
|
|
||||||
mem.release_memory(a.chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
a.count = 0;
|
|
||||||
a.chunks.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#scope_file;
|
#scope_file;
|
||||||
|
|
||||||
mem :: #import "jc/memory";
|
mem :: #import "jc/memory";
|
||||||
|
meta :: #import "jc/meta";
|
||||||
|
|
||||||
get_chunk :: (a: *Stable_Array, amount: int) -> *a.Chunk {
|
find_or_create_chunk :: (a: *Stable_Array, amount: int) -> *a.Chunk {
|
||||||
if a.chunks.count == 0 {
|
if a.chunks.count == 0 {
|
||||||
if a.allocator.proc == null {
|
return create_chunk(a);
|
||||||
a.allocator = context.allocator;
|
|
||||||
a.chunks.allocator = a.allocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return make_chunk(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last := a.chunks[a.chunks.count - 1];
|
last := a.chunks[a.chunks.count - 1];
|
||||||
if amount > a.ITEMS_PER_CHUNK - last.count {
|
if amount > a.ITEMS_PER_CHUNK - last.count {
|
||||||
last = make_chunk(a);
|
last = create_chunk(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
make_chunk :: (a: *Stable_Array) -> *a.Chunk {
|
create_chunk :: (a: *Stable_Array) -> *a.Chunk {
|
||||||
|
inline try_lazy_init(a);
|
||||||
|
|
||||||
chunk := mem.request_memory(a.Chunk,, allocator = a.allocator);
|
chunk := mem.request_memory(a.Chunk,, allocator = a.allocator);
|
||||||
append(*a.chunks, chunk);
|
append(*a.chunks, chunk);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try_lazy_init :: (a: *Stable_Array) {
|
||||||
|
if a.allocator.proc == null {
|
||||||
|
init(a, context.allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #run {
|
// #run {
|
||||||
// #import "Basic";
|
// #import "Basic";
|
||||||
|
|
||||||
|
|
@ -107,7 +120,7 @@ make_chunk :: (a: *Stable_Array) -> *a.Chunk {
|
||||||
// append(*a, it * it);
|
// append(*a, it * it);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// reset(*a, keep_memory = false);
|
// reset(*a);
|
||||||
|
|
||||||
// append(*a, 10);
|
// append(*a, 10);
|
||||||
// append(*a, 20);
|
// append(*a, 20);
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@ Static_Array :: struct(capacity: int, T: Type) {
|
||||||
Default :: #run mem.default_of(T);
|
Default :: #run mem.default_of(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator [] :: inline (a: Static_Array, index: int, loc := #caller_location) -> a.T #no_abc {
|
operator [] :: inline (a: Static_Array, $$index: int, loc := #caller_location) -> a.T #no_abc {
|
||||||
assert(index >= 0 && index < a.count, "invalid index: % (max: %)", index, a.count - 1, loc = loc);
|
meta.check_bounds(index, a.count, loc = loc);
|
||||||
return a.items[index];
|
return a.items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
operator *[] :: inline (a: *Static_Array, index: int, loc := #caller_location) -> *a.T #no_abc {
|
operator *[] :: inline (a: *Static_Array, $$index: int, loc := #caller_location) -> *a.T #no_abc {
|
||||||
assert(index >= 0 && index < a.count, "invalid index: % (max: %)", index, a.count - 1, loc = loc);
|
meta.check_bounds(index, a.count, loc = loc);
|
||||||
return *a.items[index];
|
return *a.items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
operator []= :: inline (a: *Static_Array, index: int, value: a.T, loc := #caller_location) #no_abc {
|
operator []= :: inline (a: *Static_Array, $$index: int, value: a.T, loc := #caller_location) #no_abc {
|
||||||
assert(index >= 0 && index < a.capacity, "invalid index: % (max: %)", index, a.count - 1, loc = loc);
|
meta.check_bounds(index, a.count, loc = loc);
|
||||||
a.items[index] = value;
|
a.items[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ for_expansion :: (a: *Static_Array, body: Code, flags: For_Flags) #expand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
append :: inline (a: *Static_Array, item: a.T) -> *a.T {
|
append :: inline (a: *Static_Array, item: a.T) -> *a.T #no_abc {
|
||||||
ensure_array_has_room(a, 1);
|
ensure_array_has_room(a, 1);
|
||||||
ptr := *a.items[a.count];
|
ptr := *a.items[a.count];
|
||||||
ptr.* = item;
|
ptr.* = item;
|
||||||
|
|
@ -35,14 +35,14 @@ append :: inline (a: *Static_Array, item: a.T) -> *a.T {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
append :: inline (a: *Static_Array) -> *a.T {
|
append :: inline (a: *Static_Array) -> *a.T #no_abc {
|
||||||
ensure_array_has_room(a, 1);
|
ensure_array_has_room(a, 1);
|
||||||
ptr := *a.items[a.count];
|
ptr := *a.items[a.count];
|
||||||
a.count += 1;
|
a.count += 1;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
append :: inline (a: *Static_Array, items: ..a.T) -> *a.T {
|
append :: inline (a: *Static_Array, items: ..a.T) -> *a.T #no_abc {
|
||||||
ensure_array_has_room(a, items.count);
|
ensure_array_has_room(a, items.count);
|
||||||
first := *a.items[a.count];
|
first := *a.items[a.count];
|
||||||
memcpy(a.items.data + a.count, items.data, items.count * size_of(a.T));
|
memcpy(a.items.data + a.count, items.data, items.count * size_of(a.T));
|
||||||
|
|
@ -50,8 +50,8 @@ append :: inline (a: *Static_Array, items: ..a.T) -> *a.T {
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset :: inline (a: *Static_Array, $keep_memory := true) {
|
reset :: inline (a: *Static_Array) #no_abc {
|
||||||
#if !keep_memory for 0..a.count - 1 a.items[it] = a.Default;
|
for 0..a.count - 1 a.items[it] = a.Default;
|
||||||
a.count = 0;
|
a.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,6 +77,8 @@ ensure_array_has_room :: (array: *Static_Array, count: int, loc := #caller_locat
|
||||||
}
|
}
|
||||||
|
|
||||||
mem :: #import "jc/memory";
|
mem :: #import "jc/memory";
|
||||||
|
meta :: #import "jc/meta";
|
||||||
|
|
||||||
basic :: #import "Basic"; // @future
|
basic :: #import "Basic"; // @future
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue