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().*) {
// 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
.list => |*list| if (state.expect_shift == .indent) try list.append(Value.emptyScalar()),
// 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) {
// 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;
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 String = []const u8;
pub const String = [:0]const u8;
pub const Map = std.StringArrayHashMap(Value);
pub const List = std.ArrayList(Value);
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.
switch (self) {
.scalar, .string => |str| {
if (ptr.child == u8) {
if (ptr.sentinel) |sent| {
var copy = try allocator.allocSentinel(u8, str.len, @as(*const u8, @ptrCast(sent)).*);
@memcpy(copy, str);
return copy;
}
if (comptime ptr.child == u8) {
if (comptime ptr.sentinel) |sentinel|
if (comptime @as(*align(1) const ptr.child, @ptrCast(sentinel)).* != 0)
return error.BadValue;
return str;
} else {
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 {
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 {