use tagged union
This commit is contained in:
parent
c3ab5c0d41
commit
22e1bcccea
1 changed files with 57 additions and 30 deletions
87
src/bdf.zig
87
src/bdf.zig
|
@ -27,6 +27,7 @@ const Font = struct {
|
||||||
while (iterator.next()) |char| {
|
while (iterator.next()) |char| {
|
||||||
char.deinit(allocator);
|
char.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
allocator.free(self.name);
|
||||||
self.characters.deinit();
|
self.characters.deinit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -40,9 +41,13 @@ const Command = enum {
|
||||||
_IGNORED,
|
_IGNORED,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Line = struct {
|
const ParsedCommand = union(Command) {
|
||||||
command: Command,
|
FONT: []const u8,
|
||||||
params: []const u8,
|
FONTBOUNDINGBOX: struct { width: u8, height: u8 },
|
||||||
|
ENCODING: u16,
|
||||||
|
BITMAP: void,
|
||||||
|
STARTCHAR: []const u8,
|
||||||
|
_IGNORED: void,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse(allocator: std.mem.Allocator, bdf: anytype) !Font {
|
pub fn parse(allocator: std.mem.Allocator, bdf: anytype) !Font {
|
||||||
|
@ -56,55 +61,77 @@ pub fn parse(allocator: std.mem.Allocator, bdf: anytype) !Font {
|
||||||
var bufferedReader = std.io.bufferedReader(bdf);
|
var bufferedReader = std.io.bufferedReader(bdf);
|
||||||
var reader = bufferedReader.reader();
|
var reader = bufferedReader.reader();
|
||||||
|
|
||||||
var currentName: []const u8 = undefined;
|
var arenaAllocator = std.heap.ArenaAllocator.init(allocator);
|
||||||
|
defer arenaAllocator.deinit();
|
||||||
|
|
||||||
|
var currentName: []u8 = undefined;
|
||||||
var currentCharacter: u16 = 0;
|
var currentCharacter: u16 = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
var lineBuffer: [1024]u8 = undefined;
|
var lineBuffer: [1024]u8 = undefined;
|
||||||
const nextLine = try reader.readUntilDelimiterOrEof(&lineBuffer, '\n') orelse break;
|
const nextLine = try reader.readUntilDelimiterOrEof(&lineBuffer, '\n') orelse break;
|
||||||
|
|
||||||
// Parse line
|
// Parse line
|
||||||
const line = try parseLine(nextLine);
|
const line = try parseLine(arenaAllocator.allocator(), nextLine);
|
||||||
switch (line.command) {
|
switch (line) {
|
||||||
.FONT => {
|
.FONT => |name| {
|
||||||
font.name = line.params;
|
font.name = try allocator.dupe(u8, name);
|
||||||
std.log.debug("Font: {s}", .{font.name});
|
std.log.debug("Font: {s}", .{name});
|
||||||
},
|
},
|
||||||
.FONTBOUNDINGBOX => {
|
.FONTBOUNDINGBOX => |box| {
|
||||||
var boundingBox = std.mem.splitScalar(u8, line.params, ' ');
|
font.width = box.width;
|
||||||
font.width = try std.fmt.parseInt(u8, boundingBox.next().?, 10);
|
font.height = box.height;
|
||||||
font.height = try std.fmt.parseInt(u8, boundingBox.next().?, 10);
|
std.log.debug("Bounding box: {d}x{d}", .{ box.width, box.height });
|
||||||
|
},
|
||||||
std.log.debug("Bounding box: {d}x{d}", .{ font.width, font.height });
|
.STARTCHAR => |name| {
|
||||||
|
currentName = try allocator.dupe(u8, name);
|
||||||
|
},
|
||||||
|
.ENCODING => |num| {
|
||||||
|
currentCharacter = num;
|
||||||
},
|
},
|
||||||
.BITMAP => {
|
.BITMAP => {
|
||||||
const bitmap = try readBitmap(allocator, font.width, font.height, reader);
|
const bitmap = try readBitmap(allocator, font.width, font.height, reader);
|
||||||
try font.characters.put(currentCharacter, .{
|
try font.characters.put(currentCharacter, .{
|
||||||
.name = try allocator.dupe(u8, currentName),
|
.name = currentName,
|
||||||
.bitmap = bitmap,
|
.bitmap = bitmap,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.STARTCHAR => {
|
._IGNORED => {},
|
||||||
currentName = line.params;
|
|
||||||
},
|
|
||||||
.ENCODING => {
|
|
||||||
// This probably breaks with custom encodings, not doing anything for now
|
|
||||||
currentCharacter = try std.fmt.parseInt(u16, line.params, 10);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseLine(line: []const u8) !Line {
|
fn parseLine(allocator: std.mem.Allocator, line: []const u8) !ParsedCommand {
|
||||||
const firstSpace = std.mem.indexOfScalar(u8, line, ' ') orelse line.len;
|
const firstSpace = std.mem.indexOfScalar(u8, line, ' ') orelse line.len;
|
||||||
const command = line[0..firstSpace];
|
const command = std.meta.stringToEnum(Command, line[0..firstSpace]) orelse Command._IGNORED;
|
||||||
|
|
||||||
return .{
|
const rest = if (firstSpace == line.len) "" else line[firstSpace + 1 ..];
|
||||||
.command = std.meta.stringToEnum(Command, command) orelse Command._IGNORED,
|
|
||||||
.params = if (firstSpace == line.len) "" else line[firstSpace + 1 ..],
|
switch (command) {
|
||||||
};
|
.ENCODING => {
|
||||||
|
return ParsedCommand{ .ENCODING = try std.fmt.parseInt(u16, rest, 10) };
|
||||||
|
},
|
||||||
|
.BITMAP => {
|
||||||
|
return ParsedCommand{ .BITMAP = {} };
|
||||||
|
},
|
||||||
|
.STARTCHAR => {
|
||||||
|
return ParsedCommand{ .STARTCHAR = try allocator.dupe(u8, rest) };
|
||||||
|
},
|
||||||
|
.FONT => {
|
||||||
|
return ParsedCommand{ .FONT = try allocator.dupe(u8, rest) };
|
||||||
|
},
|
||||||
|
.FONTBOUNDINGBOX => {
|
||||||
|
var boundingBox = std.mem.splitScalar(u8, rest, ' ');
|
||||||
|
return ParsedCommand{ .FONTBOUNDINGBOX = .{
|
||||||
|
.width = try std.fmt.parseInt(u8, boundingBox.next().?, 10),
|
||||||
|
.height = try std.fmt.parseInt(u8, boundingBox.next().?, 10),
|
||||||
|
} };
|
||||||
|
},
|
||||||
|
._IGNORED => {
|
||||||
|
return ParsedCommand{ ._IGNORED = {} };
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readBitmap(
|
fn readBitmap(
|
||||||
|
|
Loading…
Reference in a new issue