Add block pattern parsing (#1237)

* Revert "Remove pattern code from PR"

This reverts commit d9296b00cff93e7f0bd0962f012aa98f3ec39915.

* Apply review requests

* Update import

* Rename pattern.zig to Pattern.zig

* Fix compilation errors

* Remove code comment
This commit is contained in:
Krzysztof Wiśniewski 2025-03-28 20:04:21 +01:00 committed by GitHub
parent 8d54e187cf
commit d9dc3f1a22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -0,0 +1,52 @@
const std = @import("std");
const main = @import("main");
const AliasTable = main.utils.AliasTable;
const Block = main.blocks.Block;
const ListUnmanaged = main.ListUnmanaged;
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
blocks: AliasTable(Entry),
const Entry = struct {
block: Block,
chance: f32,
};
pub fn initFromString(allocator: NeverFailingAllocator, source: []const u8) !@This() {
var specifiers = std.mem.splitScalar(u8, source, ',');
var totalWeight: f32 = 0;
var weightedEntries: ListUnmanaged(struct {block: Block, weight: f32}) = .{};
defer weightedEntries.deinit(main.stackAllocator);
while(specifiers.next()) |specifier| {
var iterator = std.mem.splitScalar(u8, specifier, '%');
var weight: f32 = undefined;
var block = main.blocks.parseBlock(iterator.rest());
const first = iterator.first();
weight = std.fmt.parseFloat(f32, first) catch blk: {
// To distinguish somehow between mistyped numeric values and actual block IDs we check for addon name separator.
if(!std.mem.containsAtLeastScalar(u8, first, 1, ':')) return error.PatternSyntaxError;
block = main.blocks.parseBlock(first);
break :blk 1.0;
};
totalWeight += weight;
weightedEntries.append(main.stackAllocator, .{.block = block, .weight = weight});
}
const entries = allocator.alloc(Entry, weightedEntries.items.len);
for(weightedEntries.items, 0..) |entry, i| {
entries[i] = .{.block = entry.block, .chance = entry.weight/totalWeight};
}
return .{.blocks = .init(allocator, entries)};
}
pub fn deinit(self: @This(), allocator: NeverFailingAllocator) void {
self.blocks.deinit(allocator);
allocator.free(self.blocks.items);
}