perf: small sgr parser improvements
parent
6d5b4a3426
commit
9ab9bc8e19
|
|
@ -1772,10 +1772,6 @@ pub fn setAttribute(self: *Screen, attr: sgr.Attribute) !void {
|
|||
self.cursor.style.flags.underline = v;
|
||||
},
|
||||
|
||||
.reset_underline => {
|
||||
self.cursor.style.flags.underline = .none;
|
||||
},
|
||||
|
||||
.underline_color => |rgb| {
|
||||
self.cursor.style.underline_color = .{ .rgb = .{
|
||||
.r = rgb.r,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ pub const Attribute = union(Tag) {
|
|||
|
||||
/// Underline the text
|
||||
underline: Underline,
|
||||
reset_underline,
|
||||
underline_color: color.RGB,
|
||||
@"256_underline_color": u8,
|
||||
reset_underline_color,
|
||||
|
|
@ -92,7 +91,6 @@ pub const Attribute = union(Tag) {
|
|||
"reset_italic",
|
||||
"faint",
|
||||
"underline",
|
||||
"reset_underline",
|
||||
"underline_color",
|
||||
"256_underline_color",
|
||||
"reset_underline_color",
|
||||
|
|
@ -186,15 +184,16 @@ pub const Parser = struct {
|
|||
/// Next returns the next attribute or null if there are no more attributes.
|
||||
pub fn next(self: *Parser) ?Attribute {
|
||||
if (self.idx >= self.params.len) {
|
||||
// If we're at index zero it means we must have an empty
|
||||
// list and an empty list implicitly means unset.
|
||||
if (self.idx == 0) {
|
||||
// Add one to ensure we don't loop on unset
|
||||
self.idx += 1;
|
||||
return .unset;
|
||||
}
|
||||
// We're more likely to not be done than to be done.
|
||||
@branchHint(.unlikely);
|
||||
|
||||
return null;
|
||||
// Add one to ensure we don't loop on unset
|
||||
defer self.idx += 1;
|
||||
|
||||
// If we're at index zero it means we must have an empty list
|
||||
// and an empty list implicitly means unset, otherwise we're
|
||||
// done and return null.
|
||||
return if (self.idx == 0) .unset else null;
|
||||
}
|
||||
|
||||
const slice = self.params[self.idx..self.params.len];
|
||||
|
|
@ -206,11 +205,20 @@ pub const Parser = struct {
|
|||
|
||||
// If we have a colon separator then we need to ensure we're
|
||||
// parsing a value that allows it.
|
||||
if (colon) switch (slice[0]) {
|
||||
if (colon) {
|
||||
// Colons are fairly rare in the wild.
|
||||
@branchHint(.unlikely);
|
||||
|
||||
switch (slice[0]) {
|
||||
4, 38, 48, 58 => {},
|
||||
|
||||
else => {
|
||||
// Consume all the colon separated values.
|
||||
// In real world use it's very rare
|
||||
// that we receive an invalid sequence.
|
||||
@branchHint(.cold);
|
||||
|
||||
// Consume all the colon separated
|
||||
// values and return them as unknown.
|
||||
const start = self.idx;
|
||||
while (self.params_sep.isSet(self.idx)) self.idx += 1;
|
||||
self.idx += 1;
|
||||
|
|
@ -219,7 +227,8 @@ pub const Parser = struct {
|
|||
.partial = slice[0..@min(self.idx - start + 1, slice.len)],
|
||||
} };
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
switch (slice[0]) {
|
||||
0 => return .unset,
|
||||
|
|
@ -232,25 +241,37 @@ pub const Parser = struct {
|
|||
|
||||
4 => underline: {
|
||||
if (colon) {
|
||||
// Colons are fairly rare in the wild.
|
||||
@branchHint(.unlikely);
|
||||
|
||||
assert(slice.len >= 2);
|
||||
if (self.isColon()) {
|
||||
// Invalid/unknown SGRs are just not very likely.
|
||||
@branchHint(.cold);
|
||||
|
||||
self.consumeUnknownColon();
|
||||
break :underline;
|
||||
}
|
||||
|
||||
self.idx += 1;
|
||||
switch (slice[1]) {
|
||||
0 => return .reset_underline,
|
||||
1 => return .{ .underline = .single },
|
||||
2 => return .{ .underline = .double },
|
||||
3 => return .{ .underline = .curly },
|
||||
4 => return .{ .underline = .dotted },
|
||||
5 => return .{ .underline = .dashed },
|
||||
return .{
|
||||
.underline = switch (slice[1]) {
|
||||
0 => .none,
|
||||
1 => .single,
|
||||
2 => .double,
|
||||
3 => .curly,
|
||||
4 => .dotted,
|
||||
5 => .dashed,
|
||||
|
||||
// For unknown underline styles, just render
|
||||
// a single underline.
|
||||
else => return .{ .underline = .single },
|
||||
}
|
||||
// For unknown underline styles,
|
||||
// just render a single underline.
|
||||
else => single: {
|
||||
// This is quite a rare condition.
|
||||
@branchHint(.cold);
|
||||
break :single .single;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return .{ .underline = .single };
|
||||
|
|
@ -272,7 +293,7 @@ pub const Parser = struct {
|
|||
|
||||
23 => return .reset_italic,
|
||||
|
||||
24 => return .reset_underline,
|
||||
24 => return .{ .underline = .none },
|
||||
|
||||
25 => return .reset_blink,
|
||||
|
||||
|
|
@ -286,7 +307,11 @@ pub const Parser = struct {
|
|||
.@"8_fg" = @enumFromInt(slice[0] - 30),
|
||||
},
|
||||
|
||||
38 => if (slice.len >= 2) switch (slice[1]) {
|
||||
38 => if (slice.len >= 2) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
switch (slice[1]) {
|
||||
// `2` indicates direct-color (r, g, b).
|
||||
// We need at least 3 more params for this to make sense.
|
||||
2 => if (self.parseDirectColor(
|
||||
|
|
@ -297,12 +322,17 @@ pub const Parser = struct {
|
|||
|
||||
// `5` indicates indexed color.
|
||||
5 => if (slice.len >= 3) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
self.idx += 2;
|
||||
return .{
|
||||
.@"256_fg" = @truncate(slice[2]),
|
||||
};
|
||||
},
|
||||
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
|
||||
39 => return .reset_fg,
|
||||
|
|
@ -311,7 +341,11 @@ pub const Parser = struct {
|
|||
.@"8_bg" = @enumFromInt(slice[0] - 40),
|
||||
},
|
||||
|
||||
48 => if (slice.len >= 2) switch (slice[1]) {
|
||||
48 => if (slice.len >= 2) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
switch (slice[1]) {
|
||||
// `2` indicates direct-color (r, g, b).
|
||||
// We need at least 3 more params for this to make sense.
|
||||
2 => if (self.parseDirectColor(
|
||||
|
|
@ -322,12 +356,17 @@ pub const Parser = struct {
|
|||
|
||||
// `5` indicates indexed color.
|
||||
5 => if (slice.len >= 3) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
self.idx += 2;
|
||||
return .{
|
||||
.@"256_bg" = @truncate(slice[2]),
|
||||
};
|
||||
},
|
||||
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
|
||||
49 => return .reset_bg,
|
||||
|
|
@ -335,7 +374,11 @@ pub const Parser = struct {
|
|||
53 => return .overline,
|
||||
55 => return .reset_overline,
|
||||
|
||||
58 => if (slice.len >= 2) switch (slice[1]) {
|
||||
58 => if (slice.len >= 2) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
switch (slice[1]) {
|
||||
// `2` indicates direct-color (r, g, b).
|
||||
// We need at least 3 more params for this to make sense.
|
||||
2 => if (self.parseDirectColor(
|
||||
|
|
@ -346,12 +389,16 @@ pub const Parser = struct {
|
|||
|
||||
// `5` indicates indexed color.
|
||||
5 => if (slice.len >= 3) {
|
||||
// We are very likely to have enough parameters.
|
||||
@branchHint(.likely);
|
||||
|
||||
self.idx += 2;
|
||||
return .{
|
||||
.@"256_underline_color" = @truncate(slice[2]),
|
||||
};
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
|
||||
59 => return .reset_underline_color,
|
||||
|
|
@ -389,6 +436,9 @@ pub const Parser = struct {
|
|||
// If we don't have a colon, then we expect exactly 3 semicolon
|
||||
// separated values.
|
||||
if (!colon) {
|
||||
// Semicolons are much more common than colons.
|
||||
@branchHint(.likely);
|
||||
|
||||
self.idx += 4;
|
||||
return @unionInit(Attribute, @tagName(tag), .{
|
||||
.r = @truncate(slice[2]),
|
||||
|
|
@ -402,6 +452,9 @@ pub const Parser = struct {
|
|||
const count = self.countColon();
|
||||
switch (count) {
|
||||
3 => {
|
||||
// This is the much more common case in the wild.
|
||||
@branchHint(.likely);
|
||||
|
||||
self.idx += 4;
|
||||
return @unionInit(Attribute, @tagName(tag), .{
|
||||
.r = @truncate(slice[2]),
|
||||
|
|
@ -420,6 +473,9 @@ pub const Parser = struct {
|
|||
},
|
||||
|
||||
else => {
|
||||
// Invalid/unknown SGRs just don't happen very often at all.
|
||||
@branchHint(.cold);
|
||||
|
||||
self.consumeUnknownColon();
|
||||
return null;
|
||||
},
|
||||
|
|
@ -560,7 +616,8 @@ test "sgr: underline" {
|
|||
|
||||
{
|
||||
const v = testParse(&[_]u16{24});
|
||||
try testing.expect(v == .reset_underline);
|
||||
try testing.expect(v == .underline);
|
||||
try testing.expect(v.underline == .none);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -573,7 +630,8 @@ test "sgr: underline styles" {
|
|||
|
||||
{
|
||||
const v = testParseColon(&[_]u16{ 4, 0 });
|
||||
try testing.expect(v == .reset_underline);
|
||||
try testing.expect(v == .underline);
|
||||
try testing.expect(v.underline == .none);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue