Returns null when the code_page is set to DEFAULT
pub fn parsePragmaCodePage(full_command: []const u8) !?SupportedCodePage
pub fn parsePragmaCodePage(full_command: []const u8) !?SupportedCodePage {
var command = full_command;
// Anything besides exactly this is ignored by the Windows RC implementation
const expected_directive = "#pragma";
if (!std.mem.startsWith(u8, command, expected_directive)) return error.NotPragma;
command = command[expected_directive.len..];
if (command.len == 0 or !std.ascii.isWhitespace(command[0])) return error.NotCodePagePragma;
while (command.len > 0 and std.ascii.isWhitespace(command[0])) {
command = command[1..];
}
// Note: CoDe_PaGeZ is also treated as "code_page" by the Windows RC implementation,
// and it will error with 'Missing left parenthesis in code_page #pragma'
const expected_extension = "code_page";
if (!std.ascii.startsWithIgnoreCase(command, expected_extension)) return error.NotCodePagePragma;
command = command[expected_extension.len..];
while (command.len > 0 and std.ascii.isWhitespace(command[0])) {
command = command[1..];
}
if (command.len == 0 or command[0] != '(') {
return error.CodePagePragmaMissingLeftParen;
}
command = command[1..];
while (command.len > 0 and std.ascii.isWhitespace(command[0])) {
command = command[1..];
}
var num_str: []u8 = command[0..0];
while (command.len > 0 and (command[0] != ')' and !std.ascii.isWhitespace(command[0]))) {
command = command[1..];
num_str.len += 1;
}
if (num_str.len == 0) {
return error.CodePagePragmaNotInteger;
}
while (command.len > 0 and std.ascii.isWhitespace(command[0])) {
command = command[1..];
}
if (command.len == 0 or command[0] != ')') {
return error.CodePagePragmaMissingRightParen;
}
const code_page: ?SupportedCodePage = code_page: {
if (std.ascii.eqlIgnoreCase("DEFAULT", num_str)) {
break :code_page null;
}
// The Win32 compiler behaves fairly strangely around maxInt(u32):
// - If the overflowed u32 wraps and becomes a known code page ID, then
// it will error/warn with "Codepage not valid: ignored" (depending on /w)
// - If the overflowed u32 wraps and does not become a known code page ID,
// then it will error with 'constant too big' and 'Codepage not integer'
//
// Instead of that, we just have a separate error specifically for overflow.
const num = parseCodePageNum(num_str) catch |err| switch (err) {
error.InvalidCharacter => return error.CodePagePragmaNotInteger,
error.Overflow => return error.CodePagePragmaOverflow,
};
// Anything that starts with 0 but does not resolve to 0 is treated as invalid, e.g. 01252
if (num_str[0] == '0' and num != 0) {
return error.CodePagePragmaInvalidCodePage;
}
// Anything that resolves to 0 is treated as 'not an integer' by the Win32 implementation.
else if (num == 0) {
return error.CodePagePragmaNotInteger;
}
// Anything above u16 max is not going to be found since our CodePage enum is backed by a u16.
if (num > std.math.maxInt(u16)) {
return error.CodePagePragmaInvalidCodePage;
}
break :code_page code_pages.getByIdentifierEnsureSupported(@intCast(num)) catch |err| switch (err) {
error.InvalidCodePage => return error.CodePagePragmaInvalidCodePage,
error.UnsupportedCodePage => return error.CodePagePragmaUnsupportedCodePage,
};
};
return code_page;
}