.
This commit is contained in:
parent
9d8a5d067e
commit
ad766bc1e8
70
intern_pool.zig
Normal file
70
intern_pool.zig
Normal file
@ -0,0 +1,70 @@
|
||||
//! Reference counted, owned, and interned strings
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
bytes: std.ArrayListUnmanaged(u8),
|
||||
map: std.StringHashMapUnmanaged(void),
|
||||
|
||||
// Construct new empty string intern pool
|
||||
pub const empty: @This() = .{ .bytes = .empty, .map = .empty };
|
||||
|
||||
// Free all memory allocated by the intern pool. Additionally, ensure
|
||||
// all memory allocated by the pool in it's lifetime is also freed.
|
||||
pub fn deinit(self: *@This(), gpa: Allocator) void {
|
||||
self.bytes.deinit(gpa);
|
||||
self.map.deinit(gpa);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
// Add a string to the intern pool, returning a stable pointer to the string.
|
||||
// The pointer will last as far as the string is not removed with `remove()`.
|
||||
pub fn add(self: *@This(), gpa: Allocator, str: []const u8) ![]const u8 {
|
||||
if (self.map.getKey(str)) |entry| {
|
||||
// Return pre-existing
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Allocate memory for & copy the string
|
||||
const str_start_idx = self.bytes.items.len;
|
||||
try self.bytes.appendSlice(gpa, str);
|
||||
const entry_str = self.bytes.items[str_start_idx..];
|
||||
errdefer self.bytes.items.len = str_start_idx;
|
||||
|
||||
// Add the entry to our map, use the owned string
|
||||
try self.map.putNoClobber(gpa, entry_str, void{});
|
||||
|
||||
// Return the stable pointer
|
||||
return entry_str;
|
||||
}
|
||||
|
||||
test "Intern Pool" {
|
||||
const gpa = std.testing.allocator;
|
||||
try generalWorkload(gpa);
|
||||
|
||||
try std.testing.checkAllAllocationFailures(gpa, generalWorkload, .{});
|
||||
}
|
||||
|
||||
fn generalWorkload(gpa: Allocator) !void {
|
||||
var pool: @This() = .empty;
|
||||
defer pool.deinit(gpa);
|
||||
|
||||
// Inserting elements
|
||||
const a = try pool.add(gpa, "x");
|
||||
const b = try pool.add(gpa, "y");
|
||||
const c = try pool.add(gpa, "z");
|
||||
const d = try pool.add(gpa, "z");
|
||||
const e = try pool.add(gpa, "y");
|
||||
|
||||
try std.testing.expectEqualSlices(u8, "x", a);
|
||||
try std.testing.expectEqualSlices(u8, "y", b);
|
||||
try std.testing.expectEqualSlices(u8, "z", c);
|
||||
try std.testing.expectEqualSlices(u8, "z", d);
|
||||
try std.testing.expectEqualSlices(u8, "y", e);
|
||||
|
||||
try std.testing.expectEqual(b.ptr, e.ptr);
|
||||
try std.testing.expectEqual(c.ptr, d.ptr);
|
||||
|
||||
try std.testing.expectEqual(pool.map.size, 3);
|
||||
try std.testing.expectEqualSlices(u8, "xyz", pool.bytes.items);
|
||||
}
|
@ -112,7 +112,11 @@ pub const ObjectEntry = struct {
|
||||
};
|
||||
|
||||
pub const Flags = packed struct {
|
||||
allow_comments: bool = false,
|
||||
allow_trailing_comma: bool = false,
|
||||
enums_are_strings: bool = false,
|
||||
unions_are_strings: bool = false,
|
||||
packed_structs_are_ints: bool = false,
|
||||
};
|
||||
|
||||
pub const Options = struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user