diff options
Diffstat (limited to 'src/string_joiner.zig')
-rw-r--r-- | src/string_joiner.zig | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/string_joiner.zig b/src/string_joiner.zig index 490989c9a..373d24633 100644 --- a/src/string_joiner.zig +++ b/src/string_joiner.zig @@ -1,7 +1,8 @@ /// Rope-like data structure for joining many small strings into one big string. const std = @import("std"); -const default_allocator = @import("bun").default_allocator; -const string = @import("string_types.zig").string; +const default_allocator = bun.default_allocator; +const bun = @import("bun"); +const string = bun.string; const Allocator = std.mem.Allocator; const ObjectPool = @import("./pool.zig").ObjectPool; const Joiner = @This(); @@ -15,7 +16,6 @@ const Joinable = struct { pub const Pool = ObjectPool(Joinable, null, true, 4); }; -last_byte: u8 = 0, len: usize = 0, use_pool: bool = true, node_allocator: Allocator = undefined, @@ -23,6 +23,15 @@ node_allocator: Allocator = undefined, head: ?*Joinable.Pool.Node = null, tail: ?*Joinable.Pool.Node = null, +/// Avoid an extra pass over the list when joining +watcher: Watcher = .{}, + +pub const Watcher = struct { + input: []const u8 = "", + estimated_count: u32 = 0, + needs_newline: bool = false, +}; + pub fn done(this: *Joiner, allocator: Allocator) ![]u8 { if (this.head == null) { var out: []u8 = &[_]u8{}; @@ -60,6 +69,17 @@ pub fn lastByte(this: *const Joiner) u8 { return 0; } +pub fn push(this: *Joiner, slice: string) void { + this.append(slice, 0, null); +} + +pub fn ensureNewlineAtEnd(this: *Joiner) void { + if (this.watcher.needs_newline) { + this.watcher.needs_newline = false; + this.push("\n"); + } +} + pub fn append(this: *Joiner, slice: string, offset: u32, allocator: ?Allocator) void { const data = slice[offset..]; this.len += @truncate(u32, data.len); @@ -69,6 +89,14 @@ pub fn append(this: *Joiner, slice: string, offset: u32, allocator: ?Allocator) else (this.node_allocator.create(Joinable.Pool.Node) catch unreachable); + this.watcher.estimated_count += @boolToInt( + this.watcher.input.len > 0 and + bun.strings.contains(data, this.watcher.input), + ); + + this.watcher.needs_newline = this.watcher.input.len > 0 and data.len > 0 and + data[data.len - 1] != '\n'; + new_tail.* = .{ .allocator = default_allocator, .data = Joinable{ |