update: add cache
This commit is contained in:
parent
cba0c8d749
commit
3c3bd6d05f
2 changed files with 106 additions and 19 deletions
57
src/cache.zig
Normal file
57
src/cache.zig
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Allocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
|
const parser = @import("parser.zig");
|
||||||
|
|
||||||
|
pub const TemplateCache = struct {
|
||||||
|
arena: Allocator,
|
||||||
|
cache: std.StringHashMapUnmanaged([]parser.Node),
|
||||||
|
|
||||||
|
pub fn init(child_allocator: std.mem.Allocator) TemplateCache {
|
||||||
|
const arena = std.heap.ArenaAllocator.init(child_allocator);
|
||||||
|
return .{
|
||||||
|
.arena = arena,
|
||||||
|
.cache = .{},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn deinit(self: *TemplateCache) void {
|
||||||
|
self.arena.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocator(self: *TemplateCache) std.mem.Allocator {
|
||||||
|
return self.arena.allocator();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: *const TemplateCache, key: []const u8) ?[]parser.Node {
|
||||||
|
return self.cache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(self: *TemplateCache, key: []const u8, nodes: []parser.Node) !void {
|
||||||
|
// const key_copy = try self.arena.dupe(u8, key);
|
||||||
|
// errdefer self.arena.free(key_copy);
|
||||||
|
|
||||||
|
// try self.cache.put(self.arena, key, nodes);
|
||||||
|
const gop = try self.cache.getOrPut(self.allocator(), key);
|
||||||
|
if (!gop.found_existing) {
|
||||||
|
gop.key_ptr.* = try self.allocator().dupe(u8, key);
|
||||||
|
gop.value_ptr.* = nodes;
|
||||||
|
}
|
||||||
|
gop.value_ptr.* = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidate(self: *TemplateCache, key: []const u8) void {
|
||||||
|
if (self.cache.getEntry(key)) |entry| {
|
||||||
|
self.arena.free(entry.key_ptr.*);
|
||||||
|
for (entry.value_ptr.*) |node| node.deinit(self.arena);
|
||||||
|
self.arena.free(entry.value_ptr.*);
|
||||||
|
_ = self.cache.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(self: *TemplateCache) void {
|
||||||
|
self.deinit();
|
||||||
|
self.cache = .{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -9,6 +9,7 @@ const Value = @import("context.zig").Value;
|
||||||
const builtin_filters = @import("filters.zig").builtin_filters;
|
const builtin_filters = @import("filters.zig").builtin_filters;
|
||||||
const FilterError = @import("filters.zig").FilterError;
|
const FilterError = @import("filters.zig").FilterError;
|
||||||
const parser = @import("parser.zig");
|
const parser = @import("parser.zig");
|
||||||
|
const TemplateCache = @import("cache.zig").TemplateCache;
|
||||||
|
|
||||||
pub const RenderError = FilterError || error{
|
pub const RenderError = FilterError || error{
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
|
|
@ -44,11 +45,13 @@ pub const RenderError = FilterError || error{
|
||||||
pub const Renderer = struct {
|
pub const Renderer = struct {
|
||||||
context: *Context,
|
context: *Context,
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
cache: *TemplateCache,
|
||||||
|
|
||||||
pub fn init(context: *Context) Renderer {
|
pub fn init(context: *Context, cache: *TemplateCache) Renderer {
|
||||||
return .{
|
return .{
|
||||||
.context = context,
|
.context = context,
|
||||||
.allocator = context.allocator(),
|
.allocator = context.allocator(),
|
||||||
|
.cache = cache,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,24 +75,7 @@ pub const Renderer = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
fn renderNodes(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, writer: anytype) RenderError!void {
|
||||||
const base_template = try self.readTemplateFile(template);
|
|
||||||
defer self.allocator.free(base_template);
|
|
||||||
return self.renderString(base_template, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
const nodes = try p.parse(alloc);
|
|
||||||
defer {
|
|
||||||
for (nodes) |node| node.deinit(alloc);
|
|
||||||
alloc.free(nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const extends_node = self.checkForExtends(nodes);
|
const extends_node = self.checkForExtends(nodes);
|
||||||
|
|
||||||
if (extends_node) |ext| {
|
if (extends_node) |ext| {
|
||||||
|
|
@ -110,6 +96,50 @@ pub const Renderer = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn renderTemplate(self: *const Renderer, template: []const u8, writer: anytype, cache_key: ?[]const u8) RenderError!void {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
|
if (cache_key) |ck| {
|
||||||
|
if (self.cache.get(ck)) |cached_nodes| {
|
||||||
|
try self.renderNodes(alloc, cached_nodes, writer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = parser.Parser.init(template);
|
||||||
|
const nodes = try p.parse(alloc);
|
||||||
|
defer {
|
||||||
|
for (nodes) |node| node.deinit(alloc);
|
||||||
|
alloc.free(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache_key) |ck| {
|
||||||
|
var alc = self.cache.allocator();
|
||||||
|
var cached_nodes = try alc.alloc(parser.Node, nodes.len);
|
||||||
|
errdefer alc.free(cached_nodes);
|
||||||
|
for (nodes, 0..) |node, i| {
|
||||||
|
cached_nodes[i] = try node.clone(self.allocator);
|
||||||
|
std.debug.print("clonou {any}\n", .{cached_nodes[i]});
|
||||||
|
}
|
||||||
|
try self.cache.add(ck, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return try self.renderNodes(alloc, nodes, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(self: *const Renderer, template_path: []const u8, writer: anytype) RenderError!void {
|
||||||
|
const base_template = try self.readTemplateFile(template_path);
|
||||||
|
defer self.allocator.free(base_template);
|
||||||
|
|
||||||
|
return try self.renderTemplate(base_template, writer, template_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||||
|
return try self.renderTemplate(template, writer, null);
|
||||||
|
}
|
||||||
|
|
||||||
fn renderWithInheritance(self: *const Renderer, alloc: Allocator, base_nodes: []parser.Node, child_nodes: []parser.Node, writer: anytype) RenderError!void {
|
fn renderWithInheritance(self: *const Renderer, alloc: Allocator, base_nodes: []parser.Node, child_nodes: []parser.Node, writer: anytype) RenderError!void {
|
||||||
for (base_nodes) |base_node| {
|
for (base_nodes) |base_node| {
|
||||||
if (base_node.type == .block) {
|
if (base_node.type == .block) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue