Yes, this is precisely what I want.
Thank you, I will look into parseCharLiteral
.
Update: parseCharLiteral
does indeed work like that, but requires quite a few sanity checks before you can call it.
Otherwise you risk running into panic: reached unreachable code
. For example, if your string, after the opening '
does not start with \
, or a 0 byte, parseCharLiteral
will just throw it at utf8Decode, which, as you can plainly see, doesn’t care much for strings longer than 4 bytes.
Also the functions called by utf8Decode
, utf8Decode*
- if the string you gave them is not valid UTF8… well, unreachable
.
Anyway, here’s how I currently plan calling parseCharLiteral
:
const std = @import("std");
pub fn main() !void
{
const char_strings = [_][]const u8{ "'A'", "'\\''", "'hello'", "'\\x30'", "'⚡'", "'\\u{}'",
"'abcd'", "'abc'", "'ab'", "'\\x31'", "abcde" };
for (char_strings) |s|
{
// Must ensure the preconditions are met before calling `parseCharLiteral`,
// or get `panic: reached unreachable code`
if (s.len < 3 or s[0] != '\'' or s[s.len - 1] != '\'' or s.len > 6
or (s[1] != '\\' and s[1] != 0 and
((s.len == 6 and s[1] & 0b11111000 != 0b11110000) or
(s.len == 5 and s[1] & 0b11110000 != 0b11100000) or
(s.len == 4 and s[1] & 0b11100000 != 0b11000000))))
{
std.debug.print("!!! {s} does not represent a character\n", .{ s });
continue;
}
const p = std.zig.parseCharLiteral(s);
switch (p)
{
.success =>
{
if (p.success > 255)
std.debug.print("Character value, {}, is greater than 255 (must use u21)\n", .{ p.success })
else
std.debug.print("Parsed character: {c}\n", .{ @as(u8, @intCast(p.success & 0x0000FF)) });
},
.failure => std.debug.print("!!! Could not parse {s} as a character\n", .{ s })
}
}
}