103 lines
3.6 KiB
Zig
103 lines
3.6 KiB
Zig
|
const std = @import("std");
|
||
|
|
||
|
pub const Placeholder = struct {
|
||
|
loc: Loc,
|
||
|
|
||
|
pub const Loc = std.zig.Token.Loc;
|
||
|
|
||
|
pub fn placeholderSlice(self: Placeholder, source: []const u8) []const u8 {
|
||
|
return source[self.loc.start..self.loc.end];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// returns an array of all placeholder locations
|
||
|
pub fn collectPlaceholder(allocator: std.mem.Allocator, source: []const u8) ![]Placeholder {
|
||
|
var placeholders = std.ArrayListUnmanaged(Placeholder){};
|
||
|
errdefer placeholders.deinit(allocator);
|
||
|
|
||
|
var source_index: usize = 0;
|
||
|
while (std.mem.indexOfScalarPos(u8, source, source_index, '<')) |start_index| {
|
||
|
const end_index = std.mem.indexOfScalarPos(u8, source, start_index + 1, '>') orelse return error.Invalid;
|
||
|
|
||
|
try placeholders.append(allocator, .{ .loc = .{
|
||
|
.start = start_index,
|
||
|
.end = end_index,
|
||
|
} });
|
||
|
|
||
|
source_index = end_index + 1;
|
||
|
}
|
||
|
|
||
|
return placeholders.toOwnedSlice(allocator);
|
||
|
}
|
||
|
|
||
|
/// returns `source` without any placeholders
|
||
|
pub fn clearPlaceholders(allocator: std.mem.Allocator, source: []const u8) ![]const u8 {
|
||
|
var output = std.ArrayListUnmanaged(u8){};
|
||
|
errdefer output.deinit(allocator);
|
||
|
|
||
|
var source_index: usize = 0;
|
||
|
while (std.mem.indexOfScalarPos(u8, source, source_index, '<')) |start_index| {
|
||
|
try output.appendSlice(allocator, source[source_index..start_index]);
|
||
|
|
||
|
source_index = std.mem.indexOfScalarPos(u8, source, start_index + 1, '>') orelse return error.Invalid;
|
||
|
source_index += 1;
|
||
|
}
|
||
|
try output.appendSlice(allocator, source[source_index..source.len]);
|
||
|
|
||
|
return output.toOwnedSlice(allocator);
|
||
|
}
|
||
|
|
||
|
const CollectClearPlaceholdersResult = struct {
|
||
|
/// placeholders relative to the `source` parameter in `collectClearPlaceholders`
|
||
|
placeholders: []Placeholder,
|
||
|
/// placeholders locations to `source`
|
||
|
placeholder_locations: []usize,
|
||
|
/// source without any placeholders
|
||
|
source: []const u8,
|
||
|
|
||
|
pub fn deinit(self: @This(), allocator: std.mem.Allocator) void {
|
||
|
allocator.free(self.placeholders);
|
||
|
allocator.free(self.placeholder_locations);
|
||
|
allocator.free(self.source);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// see `CollectClearPlaceholdersResult`
|
||
|
pub fn collectClearPlaceholders(allocator: std.mem.Allocator, source: []const u8) !CollectClearPlaceholdersResult {
|
||
|
var placeholders = std.ArrayListUnmanaged(Placeholder){};
|
||
|
errdefer placeholders.deinit(allocator);
|
||
|
|
||
|
var locations = std.ArrayListUnmanaged(usize){};
|
||
|
errdefer locations.deinit(allocator);
|
||
|
|
||
|
var new_source = std.ArrayListUnmanaged(u8){};
|
||
|
errdefer new_source.deinit(allocator);
|
||
|
|
||
|
var source_index: usize = 0;
|
||
|
var new_source_index: usize = 0;
|
||
|
while (std.mem.indexOfScalarPos(u8, source, source_index, '<')) |start_index| {
|
||
|
const end_index = std.mem.indexOfScalarPos(u8, source, start_index + 1, '>') orelse return error.Invalid;
|
||
|
|
||
|
const placeholder = Placeholder{ .loc = .{
|
||
|
.start = start_index + 1,
|
||
|
.end = end_index,
|
||
|
} };
|
||
|
|
||
|
try placeholders.append(allocator, placeholder);
|
||
|
|
||
|
new_source_index = new_source_index + (start_index - source_index);
|
||
|
try locations.append(allocator, new_source_index);
|
||
|
try new_source.appendSlice(allocator, source[source_index..start_index]);
|
||
|
|
||
|
source_index = end_index + 1;
|
||
|
}
|
||
|
try new_source.appendSlice(allocator, source[source_index..source.len]);
|
||
|
|
||
|
return CollectClearPlaceholdersResult{
|
||
|
.placeholders = placeholders.toOwnedSlice(allocator),
|
||
|
.placeholder_locations = locations.toOwnedSlice(allocator),
|
||
|
.source = new_source.toOwnedSlice(allocator),
|
||
|
};
|
||
|
}
|
||
|
|