Static_Array :: struct(capacity: int, T: Type) { items: [capacity]T; count: int; Default :: #run mem.default_of(T); } append :: inline (a: *Static_Array, item: a.T) -> *a.T #no_abc { ensure_array_has_room(a, 1); ptr := *a.items[a.count]; ptr.* = item; a.count += 1; return ptr; } append :: inline (a: *Static_Array) -> *a.T #no_abc { ensure_array_has_room(a, 1); ptr := *a.items[a.count]; a.count += 1; return ptr; } append :: inline (a: *Static_Array, items: ..a.T) -> *a.T #no_abc { ensure_array_has_room(a, items.count); first := *a.items[a.count]; memcpy(a.items.data + a.count, items.data, items.count * size_of(a.T)); a.count += items.count; return first; } remove_ordered :: inline (a: *Static_Array, index: int, loc := #caller_location) #no_abc { meta.check_bounds(index, a.count, loc = loc); memcpy(a.items.data + index, a.items.data + index + 1, (a.count - index - 1) * size_of(a.T)); a.count -= 1; } remove_unordered :: inline (a: *Static_Array, index: int, loc := #caller_location) #no_abc { meta.check_bounds(index, a.count, loc = loc); a.items[index] = a.items[a.count - 1]; a.count -= 1; } reset :: inline (a: *Static_Array) #no_abc { for 0..a.count - 1 a.items[it] = a.Default; a.count = 0; } find :: (a: Static_Array, $predicate: (a.T) -> bool) -> a.T, bool, int { for a if inline predicate(it) return it, true, it_index; return mem.undefined_of(a.T), false, -1; } find_pointer :: (a: *Static_Array, $predicate: (a.T) -> bool) -> *a.T, bool, int { for * a if inline predicate(it.*) return it, true, it_index; return null, false, -1; } operator [] :: inline (a: Static_Array, $$index: int, loc := #caller_location) -> a.T #no_abc { meta.check_bounds(index, a.count, loc = loc); return a.items[index]; } operator *[] :: inline (a: *Static_Array, $$index: int, loc := #caller_location) -> *a.T #no_abc { meta.check_bounds(index, a.count, loc = loc); return *a.items[index]; } operator []= :: inline (a: *Static_Array, $$index: int, value: a.T, loc := #caller_location) #no_abc { meta.check_bounds(index, a.count, loc = loc); a.items[index] = value; } for_expansion :: (a: *Static_Array, body: Code, flags: For_Flags) #expand { view := make_view(a); for *=(flags & .POINTER == .POINTER) <=(flags & .REVERSE == .REVERSE) `it, `it_index: view { #insert,scope(body)(break = break it) body; } } make_view :: (a: Static_Array) -> []a.T { view := a.items.([]a.T); view.count = a.count; return view; } make_dynamic :: (a: *Static_Array) -> [..]a.T { res: [..]a.T; res.count = a.count; res.allocated = a.count; res.data = basic.alloc(a.count * size_of(a.T)); memcpy(res.data, a.items.data, a.count * size_of(a.T)); } #scope_file; ensure_array_has_room :: (array: *Static_Array, count: int, loc := #caller_location) #expand { basic.assert(array.count + count <= array.capacity, "attempt to add too many elements! want: %, max: %", array.count + count, array.capacity, loc = loc); } mem :: #import "jc/memory"; meta :: #import "jc/meta"; basic :: #import "Basic"; // @future // ---------------------------------------------------------- // TESTS // ---------------------------------------------------------- #if #exists(RUN_TESTS) #run { test :: #import "jc/meta/test"; test.run("basic operations", (t) => { a: Static_Array(10, int); test.expect(t, a.count == 0); test.expect(t, a.capacity == 10); append(*a, 10, 20, 30); test.expect(t, a.count == 3, "count: %", a.count); _, ok := find(a, v => v == 10); test.expect(t, ok); _, ok = find_pointer(*a, v => v == 20); test.expect(t, ok); }); test.run("remove_ordered", (t) => { a: Static_Array(10, int); append(*a, 10, 20, 30); remove_ordered(*a, 1); test.expect(t, a.count == 2); test.expect(t, a.items[0] == 10); remove_ordered(*a, 0); test.expect(t, a.count == 1); test.expect(t, a.items[0] == 30); remove_ordered(*a, 0); test.expect(t, a.count == 0); append(*a, 10); test.expect(t, a.count == 1); test.expect(t, a.items[0] == 10); }); test.run("remove_unordered", (t) => { a: Static_Array(10, int); append(*a, 10, 20, 30); remove_unordered(*a, 1); test.expect(t, a.count == 2); test.expect(t, a.items[1] == 30); remove_unordered(*a, 0); test.expect(t, a.count == 1); test.expect(t, a.items[0] == 30); remove_unordered(*a, 0); test.expect(t, a.count == 0); append(*a, 10); test.expect(t, a.count == 1); test.expect(t, a.items[0] == 10); }); }