Files
bun.sh/src/string_joiner.zig
Jarred Sumner c0dd284136 Upgrade to latest Zig (#1610)
* @min and @max

* builtins and some trivial ones

* Most of them

* more

* more!

* More Progress

* wip

* Update tagged_pointer.zig

* Update http_client_async.zig

* Most of the iterable dir changes

* alright

* Remove usages of deprecated formatters

* 📷

* fmt

* Update shimmer.zig

* wip

* wip

* wip

* progress

* more

* Latest

* stuck on error

* latest

* workaround stage2

* wip

* Update string_immutable.zig

* wip

* Migrate `Dirent` and `require("fs')` to use JSC<>Zig bindings

* Fix build errors

* Fixup most of the test failures

* Fix `make headers`

* Fix "outside package path" error

* Fixup aligned alloc

* Add missing file

* linux

* More linux fixes

* use latest peechy

* Fix transpiler test failure

* Forgot about these

* Fixup test failure

* Update node-timers.test.ts

* [node:htt] Fix `undefined is not an object` error

Fixes https://github.com/oven-sh/bun/issues/1618

* Update http.exports.js

* Make this test less flaky

* fix hashes

* Fix hex formatting and zls issues

* Download zig version

* Update Dockerfile

* Update Dockerfile

* Update uws

* Update Dockerfile

* Set llvm version

* Update README.md

* Update uws

* Update Dockerfile

* Update io_linux.zig

* Update bun.zig

* Log output

* workaround strange @cInclude error

* Make ffi tests better

* Don't use cImport

* Update c.zig

* Update c-bindings.cpp

* call setOutputDir

* Update Dockerfile

* Use a longer name

* latest

* Update serve.test.ts

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Veikka Tuominen <git@vexu.eu>
2022-12-28 00:51:22 -08:00

96 lines
2.6 KiB
Zig

/// 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("bun").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,
use_pool: bool = true,
node_allocator: std.mem.Allocator = undefined,
head: ?*Joinable.Pool.Node = null,
tail: ?*Joinable.Pool.Node = null,
pub fn done(this: *Joiner, allocator: std.mem.Allocator) ![]u8 {
if (this.head == null) {
var out: []u8 = &[_]u8{};
return out;
}
var slice = try allocator.alloc(u8, this.len);
var remaining = slice;
var el_ = this.head;
while (el_) |join| {
const to_join = join.data.slice[join.data.offset..];
@memcpy(remaining.ptr, to_join.ptr, to_join.len);
remaining = remaining[@min(remaining.len, to_join.len)..];
var prev = join;
el_ = join.next;
if (prev.data.needs_deinit) {
prev.data.allocator.free(prev.data.slice);
prev.data = Joinable{};
}
if (this.use_pool) 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 = if (this.use_pool)
Joinable.Pool.get(default_allocator)
else
(this.node_allocator.create(Joinable.Pool.Node) catch unreachable);
new_tail.* = .{
.allocator = default_allocator,
.data = Joinable{
.offset = @truncate(u31, 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");