diff options
author | 2022-03-06 07:35:16 -0800 | |
---|---|---|
committer | 2022-03-06 07:35:16 -0800 | |
commit | 7c5c6cd5192acde43006070e740bbe51cfd49255 (patch) | |
tree | 53f1e3cb999a477791dd76f4f2bedd3c56084756 /src/string_joiner.zig | |
parent | 093807391a9563ad36c2b04a286da23d09fad835 (diff) | |
download | bun-7c5c6cd5192acde43006070e740bbe51cfd49255.tar.gz bun-7c5c6cd5192acde43006070e740bbe51cfd49255.tar.zst bun-7c5c6cd5192acde43006070e740bbe51cfd49255.zip |
source maps work for app code in `bun dev`!
Diffstat (limited to 'src/string_joiner.zig')
-rw-r--r-- | src/string_joiner.zig | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/string_joiner.zig b/src/string_joiner.zig new file mode 100644 index 000000000..d49c32867 --- /dev/null +++ b/src/string_joiner.zig @@ -0,0 +1,80 @@ +/// Rope-like data structure for joining many small strings into one big string. +const Joiner = @This(); + +const string = @import("string_types.zig").string; +const Allocator = @import("std").mem.Allocator; +const assert = @import("std").debug.assert; +const copy = @import("std").mem.copy; +const Env = @import("./env.zig"); +const ObjectPool = @import("./pool.zig").ObjectPool; + +const default_allocator = @import("./global.zig").default_allocator; + +const Joinable = struct { + offset: u31 = 0, + needs_deinit: bool = false, + allocator: std.mem.Allocator = undefined, + slice: []const u8 = "", + + pub const Pool = ObjectPool(Joinable, null, true, 4); +}; + +last_byte: u8 = 0, +len: usize = 0, + +head: ?*Joinable.Pool.Node = null, +tail: ?*Joinable.Pool.Node = null, + +pub fn done(this: *Joiner, allocator: std.mem.Allocator) ![]u8 { + var slice = try allocator.alloc(u8, this.cap); + var remaining = slice; + var el_ = this.head; + while (el_) |join| { + const to_join = join.data.slice[join.offset..]; + @memcpy(remaining.ptr, to_join.ptr, to_join.len); + + remaining = remaining[to_join.len..]; + + var prev = join; + el_ = join.next; + if (prev.data.needs_deinit) { + prev.data.allocator.free(join.data.slice); + prev.data = Joinable{}; + } + prev.release(); + } + + return slice[0 .. slice.len - remaining.len]; +} + +pub fn lastByte(this: *const Joiner) u8 { + if (this.tail) |tail| { + const slice = tail.data.slice[tail.data.offset..]; + return if (slice.len > 0) slice[slice.len - 1] else 0; + } + + return 0; +} + +pub fn append(this: *Joiner, slice: string, offset: u32, allocator: ?std.mem.Allocator) void { + const data = slice[offset..]; + this.len += @truncate(u32, data.len); + + var new_tail = Joinable.Pool.get(default_allocator); + new_tail.data = Joinable{ + .offset = offset, + .allocator = allocator orelse undefined, + .needs_deinit = allocator != null, + .slice = slice, + }; + + var tail = this.tail orelse { + this.tail = new_tail; + this.head = new_tail; + return; + }; + tail.next = new_tail; + this.tail = new_tail; +} + +const std = @import("std"); |