value: store strings/scalars as null-terminated

Since these were already always copied from the source data, this was a
very easy change to implement. This makes our output schema string
detection a bit stricter, and saves performing a copy in the case that
the output string needs to be 0 terminated.

Unfortunately, we can't skip copies in the general slice case since
each child element needs to get converted to the appropriate type.
This commit is contained in:
torque 2023-11-23 17:52:16 -08:00
parent 21a9753d46
commit 33ab092a06
Signed by: torque
SSH Key Fingerprint: SHA256:nCrXefBNo6EbjNSQhv0nXmEg/VuNq3sMF5b8zETw3Tk
2 changed files with 9 additions and 10 deletions

View File

@ -70,7 +70,7 @@ pub const State = struct {
}, },
.value => switch (state.value_stack.getLast().*) { .value => switch (state.value_stack.getLast().*) {
// we have an in-progress string, finish it. // we have an in-progress string, finish it.
.string => |*string| string.* = try state.string_builder.toOwnedSlice(arena_alloc), .string => |*string| string.* = try state.string_builder.toOwnedSliceSentinel(arena_alloc, 0),
// if we have a dangling -, attach an empty scalar to it // if we have a dangling -, attach an empty scalar to it
.list => |*list| if (state.expect_shift == .indent) try list.append(Value.emptyScalar()), .list => |*list| if (state.expect_shift == .indent) try list.append(Value.emptyScalar()),
// if we have a dangling "key:", attach an empty scalar to it // if we have a dangling "key:", attach an empty scalar to it
@ -185,7 +185,7 @@ pub const State = struct {
if (firstpass and line.shift == .dedent) { if (firstpass and line.shift == .dedent) {
// copy the string into the document proper // copy the string into the document proper
string.* = try state.string_builder.toOwnedSlice(arena_alloc); string.* = try state.string_builder.toOwnedSliceSentinel(arena_alloc, 0);
var dedent_depth = line.shift.dedent; var dedent_depth = line.shift.dedent;
while (dedent_depth > 0) : (dedent_depth -= 1) while (dedent_depth > 0) : (dedent_depth -= 1)

View File

@ -51,7 +51,7 @@ pub fn Parsed(comptime T: type) type {
} }
pub const Value = union(enum) { pub const Value = union(enum) {
pub const String = []const u8; pub const String = [:0]const u8;
pub const Map = std.StringArrayHashMap(Value); pub const Map = std.StringArrayHashMap(Value);
pub const List = std.ArrayList(Value); pub const List = std.ArrayList(Value);
pub const TagType = @typeInfo(Value).Union.tag_type.?; pub const TagType = @typeInfo(Value).Union.tag_type.?;
@ -120,12 +120,11 @@ pub const Value = union(enum) {
// probably be solved in the zig stdlib or similar. // probably be solved in the zig stdlib or similar.
switch (self) { switch (self) {
.scalar, .string => |str| { .scalar, .string => |str| {
if (ptr.child == u8) { if (comptime ptr.child == u8) {
if (ptr.sentinel) |sent| { if (comptime ptr.sentinel) |sentinel|
var copy = try allocator.allocSentinel(u8, str.len, @as(*const u8, @ptrCast(sent)).*); if (comptime @as(*align(1) const ptr.child, @ptrCast(sentinel)).* != 0)
@memcpy(copy, str); return error.BadValue;
return copy;
}
return str; return str;
} else { } else {
return error.BadValue; return error.BadValue;
@ -348,7 +347,7 @@ pub const Value = union(enum) {
} }
inline fn _fromScalarOrString(alloc: std.mem.Allocator, comptime classification: TagType, input: []const u8) !Value { inline fn _fromScalarOrString(alloc: std.mem.Allocator, comptime classification: TagType, input: []const u8) !Value {
return @unionInit(Value, @tagName(classification), try alloc.dupe(u8, input)); return @unionInit(Value, @tagName(classification), try alloc.dupeZ(u8, input));
} }
pub inline fn emptyScalar() Value { pub inline fn emptyScalar() Value {