340 lines
12 KiB
Zig
340 lines
12 KiB
Zig
// ---- ----
|
|
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});
|
|
}
|
|
}
|