update: create a suballocator for renderer
This commit is contained in:
parent
0e74ddb278
commit
256898cb41
1 changed files with 25 additions and 11 deletions
|
|
@ -53,45 +53,59 @@ pub const Renderer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
var p = parser.Parser.init(template);
|
var p = parser.Parser.init(template);
|
||||||
const nodes = try p.parse(self.allocator);
|
const nodes = try p.parse(alloc);
|
||||||
|
defer {
|
||||||
|
for (nodes) |node| node.deinit(alloc);
|
||||||
|
alloc.free(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
for (nodes) |node| {
|
for (nodes) |node| {
|
||||||
try self.renderNode(node, writer);
|
try self.renderNode(alloc, node, writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderNode(self: *const Renderer, node: parser.Node, writer: anytype) RenderError!void {
|
fn renderNode(self: *const Renderer, alloc: Allocator, node: parser.Node, writer: anytype) RenderError!void {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
.text => try writer.writeAll(node.text.?.content),
|
.text => try writer.writeAll(node.text.?.content),
|
||||||
.variable => {
|
.variable => {
|
||||||
const var_name = node.variable.?.expr;
|
const var_name = node.variable.?.expr;
|
||||||
var value: Value = self.context.get(var_name) orelse Value.null;
|
var value: Value = self.context.get(var_name) orelse Value.null;
|
||||||
var buf = ArrayListUnmanaged(u8){};
|
|
||||||
defer buf.deinit(self.allocator);
|
|
||||||
|
|
||||||
var is_safe = false;
|
var is_safe = false;
|
||||||
|
|
||||||
for (node.variable.?.filters) |f| {
|
for (node.variable.?.filters) |f| {
|
||||||
const filter_fn = builtin_filters.get(f.name) orelse continue;
|
const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter;
|
||||||
value = try filter_fn(self.allocator, value, Value{.string = f.arg orelse ""});
|
|
||||||
|
const arg = if (f.arg) |a| Value{ .string = a } else null;
|
||||||
|
value = try filter_fn(alloc, value, arg);
|
||||||
|
|
||||||
if (std.mem.eql(u8, f.name, "safe")) is_safe = true;
|
if (std.mem.eql(u8, f.name, "safe")) is_safe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_safe) {
|
if (!is_safe) {
|
||||||
if (builtin_filters.get("escape")) |escape_fn| {
|
if (builtin_filters.get("escape")) |escape_fn| {
|
||||||
value = try escape_fn(self.allocator, value, null);
|
value = try escape_fn(alloc, value, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.valueToString(&buf, value);
|
var buf = ArrayListUnmanaged(u8){};
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try self.valueToString(alloc, &buf, value);
|
||||||
try writer.writeAll(buf.items);
|
try writer.writeAll(buf.items);
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valueToString(self: *const Renderer, buf: *ArrayListUnmanaged(u8), value: Value) !void {
|
fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) !void {
|
||||||
var w = buf.writer(self.allocator);
|
_ = self;
|
||||||
|
var w = buf.writer(alloc);
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.null => try w.writeAll("null"),
|
.null => try w.writeAll("null"),
|
||||||
.bool => |b| try w.print("{}", .{b}),
|
.bool => |b| try w.print("{}", .{b}),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue