// ---- ---- const std = @import("std"); const utils = @import("structures/utils.zig"); pub const getFileExtension = utils.getFileExtension; pub const getBasePath = utils.getBasePath; pub const getFolder = utils.getFolder; pub const getDir = utils.getFolder; pub const BumpArena = @import("structures/bump-arena.zig").BumpArena; pub const dupeString = utils.dupeString; pub const xxd = @import("utils/xxd.zig"); pub const stringStrip = utils.stringStrip; pub const xxdWrite = xxd.xxdWrite; pub const loadFileAlloc = utils.loadFileAlloc; const ArrayList = std.ArrayList; const ArrayListUnmanaged = std.ArrayListUnmanaged; pub usingnamespace @import("structures/interface.zig"); pub const assertf = utils.assertf; pub const asserts = utils.asserts; pub const assert = utils.assert; pub const createFileWithPath = utils.createFileWithPath; pub const static_structures = @import("structures/static-structures.zig"); pub const StaticVector = static_structures.StaticVector; pub const ring_queue = @import("structures/ring-queue.zig"); pub const RingQueueU = ring_queue.RingQueueU; pub const RingQueue = ring_queue.RingQueue; pub const sparse_set = @import("structures/sparse-set.zig"); pub const SparseSet = sparse_set.SparseSet; pub const SparseMap = sparse_set.SparseMap; pub const SparseMultiSet = sparse_set.SparseMultiSet; pub const SparseSetAdvanced = sparse_set.SparseSetAdvanced; pub const SparseMultiSetAdvanced = sparse_set.SparseMultiSetAdvanced; pub const SetHandle = sparse_set.SetHandle; pub const EcsContainerInterface = sparse_set.EcsContainerInterface; pub const stack_structures = @import("structures/stack-structures.zig"); pub const index_pool = @import("structures/index-pool.zig"); pub const IndexPoolHandle = index_pool.Handle; pub const IndexPool = index_pool.IndexPool; pub const concurrent_queue = @import("structures/concurrent-queue.zig"); pub const ConcurrentQueueU = concurrent_queue.ConcurrentQueueU; pub const ConcurrentQueueUnmanagedAdvanced = concurrent_queue.ConcurrentQueueUnmanagedAdvanced; pub const string_pool = @import("structures/string-pool.zig"); pub const paged_vector = @import("structures/paged-vector.zig"); pub const PagedVector = paged_vector.PagedVector; pub const names = @import("structures/names.zig"); pub const NameInvalid = names.NameInvalid; pub const Name = names.Name; pub const StaticName = names.StaticName; pub const MakeName = names.MakeName; pub const DefineName = names.DefineName; pub const createNameRegistry = names.createNameRegistry; pub const destroyNameRegistry = names.destroyNameRegistry; pub const setNameRegistry = names.setNameRegistry; pub const NameRegistry = names.NameRegistry; pub const spans = @import("structures/spans.zig"); pub const MergedSpans = spans.MergedSpans; pub const Span = spans.Span; pub const shell = @import("utils/shell.zig"); pub fn sharedLibNameAlloc(allocator: std.mem.Allocator, s: []const u8) ![]u8 { const os_tag = @import("builtin").os.tag; var suffix: []const u8 = "dll"; var prefix: []const u8 = ""; if (os_tag == .linux) { prefix = "lib"; suffix = "so"; } else if (os_tag == .macos) { suffix = "dylib"; prefix = "lib"; } const path = try std.fmt.allocPrint(allocator, "{s}{s}.{s}", .{ prefix, s, suffix }); return path; } comptime { std.testing.refAllDecls(utils); std.testing.refAllDecls(static_structures); std.testing.refAllDecls(ring_queue); std.testing.refAllDecls(sparse_set); std.testing.refAllDecls(stack_structures); std.testing.refAllDecls(index_pool); std.testing.refAllDecls(concurrent_queue); std.testing.refAllDecls(string_pool); std.testing.refAllDecls(spans); } // ---- aliases ---- pub const ObjectHandle = SetHandle; pub inline fn u32_to_slice(array: *u32) []u8 { var slice: []u8 = undefined; slice.ptr = @ptrCast(array); slice.len = 4; return slice; } pub inline fn u64_to_slice(array: *u64) []u8 { var slice: []u8 = undefined; slice.ptr = @ptrCast(array); slice.len = 8; return slice; } pub inline fn arrayTo_u32(array: anytype) u32 { return @as(*const u32, @ptrCast(@alignCast(&array))).*; } pub inline fn arrayTo_u64(array: anytype) u64 { return @as(*const u64, @ptrCast(@alignCast(&array))).*; } // ---- tests ---- test "multi-sparse-basic" { const allocator = std.testing.allocator; const TestStructField = struct { x: u32, }; const TestStruct = struct { field1: usize, structField: TestStructField, }; var testSet = SparseMultiSet(TestStruct).init(allocator); defer testSet.deinit(); const sparseHandle = try testSet.createObject(.{ .field1 = 1, .structField = .{ .x = 12 } }); const sparseHandle1 = try testSet.createObject(.{ .field1 = 2, .structField = .{ .x = 34 } }); const sparseHandle2 = try testSet.createObject(.{ .field1 = 3, .structField = .{ .x = 56 } }); std.debug.print("handle: {any}\n", .{testSet.get(sparseHandle, .field1).?.*}); std.debug.print("handle1: {any}\n", .{testSet.get(sparseHandle1, .field1).?.*}); std.debug.print("handle2: {any}\n", .{testSet.get(sparseHandle2, .field1).?.*}); _ = testSet.destroyObject(sparseHandle); std.debug.print("handle1: {any}\n", .{testSet.get(sparseHandle1, .field1).?.*}); std.debug.print("handle2: {any}\n", .{testSet.get(sparseHandle2, .field1).?.*}); } // As backlog is primarily a playground for me to learn and practice programming, // There will be some implementations of basic data structures. For fun ofc pub fn AppendToArrayListUnique(list: anytype, value: anytype) !void { for (list.items) |v| { if (v == value) return; } try list.append(value); } fn printSetHandle(s: SetHandle) void { std.debug.print("{any}\n", .{s}); } test "sparse-set" { std.debug.print("\n", .{}); const Payload = struct { name: []const u8, v: u32, }; const PayloadSet = SparseSet(Payload); const expect = std.testing.expect; var set = PayloadSet.init(std.testing.allocator); defer set.deinit(); var set2 = PayloadSet.init(std.testing.allocator); defer set2.deinit(); const setHandle = (try set.createAndGet(.{ .name = "object1", .v = 0 })).handle; printSetHandle(setHandle); const setHandle1 = (try set.createObject(.{ .name = "object2", .v = 1 })); printSetHandle(setHandle1); const setHandle2 = (try set.createObject(.{ .name = "object3", .v = 2 })); printSetHandle(setHandle2); const setHandle3 = (try set.createObject(.{ .name = "object4", .v = 3 })); printSetHandle(setHandle3); const set2Handle1 = (try set2.createWithHandle(setHandle3, set.get(setHandle2).?.*)).handle; std.debug.print("set2 handle: \n", .{}); printSetHandle(set2Handle1); for (set.dense.items) |entry| { std.debug.print("{any}: {s}\n", .{ entry.value, entry.value.name }); } std.debug.print("\ndestroying handle\n", .{}); set.destroyObject(setHandle); for (set.dense.items) |entry| { std.debug.print("{any}: {s}\n", .{ entry.value, entry.value.name }); } try expect(set.get(setHandle) == null); try expect(set.get(setHandle1).?.v == 1); try expect(set.get(setHandle2).?.v == 2); try expect(set.get(setHandle3).?.v == 3); std.debug.print("\ndestroying handle\n", .{}); set.destroyObject(setHandle1); for (set.dense.items) |entry| { std.debug.print("{any}: {s}\n", .{ entry.value, entry.value.name }); } try expect(set.get(setHandle) == null); try expect(set.get(setHandle1) == null); try expect(set.get(setHandle2).?.v == 2); try expect(set.get(setHandle3).?.v == 3); std.debug.print("\ndestroying handle\n", .{}); set.destroyObject(setHandle2); for (set.dense.items) |entry| { std.debug.print("{any}: {s}\n", .{ entry.value, entry.value.name }); } try expect(set.get(setHandle) == null); try expect(set.get(setHandle1) == null); try expect(set.get(setHandle3).?.v == 3); try expect(set.get(setHandle2) == null); std.debug.print("\ndestroying handle\n", .{}); set.destroyObject(setHandle3); for (set.dense.items) |entry| { std.debug.print("{any}: {s}\n", .{ entry.value, entry.value.name }); } try expect(set.get(setHandle) == null); try expect(set.get(setHandle1) == null); try expect(set.get(setHandle2) == null); try expect(set.get(setHandle3) == null); try expect(set.dense.items.len == 0); } test "ringBuffer" { std.debug.print("\nbuffer test: filling a ring buffer\n", .{}); const allocator = std.testing.allocator; var b = try RingQueueU(u32).init(allocator, 4); defer b.deinit(allocator); const expect = std.testing.expect; try b.push(1); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); try b.push(2); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); try b.push(3); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); try expect(b.count() == 3); std.debug.print("popping: {d}\n", .{b.pop().?}); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); try expect(b.count() == 2); std.debug.print("popping: {d}\n", .{b.pop().?}); try expect(b.count() == 1); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); std.debug.print("popping: {d}\n", .{b.pop().?}); try expect(b.count() == 0); try expect(b.pop() == null); std.debug.print("head={d} tail={d}\n", .{ b.head, b.tail }); try std.testing.expect(b.head == b.tail); try std.testing.expect(b.isEmpty()); try b.push(11); std.debug.print("head={d} tail={d} count={d} len={d}\n", .{ b.head, b.tail, b.count(), b.buffer.len }); try expect(b.count() == 1); try b.push(12); std.debug.print("head={d} tail={d} count={d} len={d}\n", .{ b.head, b.tail, b.count(), b.buffer.len }); try expect(b.count() == 2); try b.push(13); std.debug.print("head={d} tail={d} count={d} len={d}\n", .{ b.head, b.tail, b.count(), b.buffer.len }); try expect(b.count() == 3); try b.push(14); std.debug.print("head={d} tail={d} count={d} len={d}\n", .{ b.head, b.tail, b.count(), b.buffer.len }); try expect(b.head == 3); try expect(b.count() == 4); try expect(b.tail == ((b.head + 4) % b.buffer.len)); try expect(b.at(0).? == b.peek().?); const newSize = b.buffer.len * 4; try b.resize(allocator, newSize); // grow that shit, expect the new size to be size + 1 try expect(b.capacity() == newSize); try expect(b.buffer.len == newSize + 1); var errorHit: bool = false; b.resize(allocator, 2) catch |e| { errorHit = true; try expect(e == error.AllocSizeTooSmall); std.debug.print("{any}\n", .{e}); }; try expect(errorHit); try expect(b.peekBack().?.* == 14); try expect(b.atBack(1).?.* == 14); try expect(b.atBack(2).?.* == 13); try expect(b.atBack(3).?.* == 12); try expect(b.atBack(4).?.* == 11); try b.pushFront(44); try expect(b.count() == 5); try expect(b.peek().?.* == 44); } test "spin child process echo" { { std.debug.print("spin child process\n", .{}); const process = try shell.ShellProcess.init(std.testing.allocator, &.{ "echo", "lmao 2 nova" }); defer process.deinit(); std.debug.print("child process created: {s}\n", .{process.argv}); } { std.debug.print("spin child process 2\n", .{}); const process = try shell.ShellProcess.initCmd(std.testing.allocator, "echo lmao2nova -target='lmao 3 nova'"); defer process.deinit(); std.debug.print("{s}\n", .{process.argv}); } }