1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
const std = @import("std");
const Allocator = std.mem.Allocator;
const bun = @import("root").bun;
const Environment = bun.Environment;
const string = @import("string_types.zig").string;
const StringBuilder = @This();
const assert = std.debug.assert;
const DebugHashTable = if (Environment.allow_assert) std.AutoHashMapUnmanaged(u64, void) else void;
len: usize = 0,
cap: usize = 0,
ptr: ?[*]u8 = null,
pub fn initCapacity(
allocator: std.mem.Allocator,
cap: usize,
) !StringBuilder {
return StringBuilder{
.cap = cap,
.len = 0,
.ptr = (try allocator.alloc(u8, cap)).ptr,
};
}
pub fn count(this: *StringBuilder, slice: string) void {
this.cap += slice.len;
}
pub fn allocate(this: *StringBuilder, allocator: Allocator) !void {
var slice = try allocator.alloc(u8, this.cap);
this.ptr = slice.ptr;
this.len = 0;
}
pub fn deinit(this: *StringBuilder, allocator: Allocator) void {
if (this.ptr == null or this.cap == 0) return;
allocator.free(this.ptr.?[0..this.cap]);
}
pub fn append(this: *StringBuilder, slice: string) string {
if (comptime Environment.allow_assert) {
assert(this.len <= this.cap); // didn't count everything
assert(this.ptr != null); // must call allocate first
}
bun.copy(u8, this.ptr.?[this.len..this.cap], slice);
const result = this.ptr.?[this.len..this.cap][0..slice.len];
this.len += slice.len;
if (comptime Environment.allow_assert) assert(this.len <= this.cap);
return result;
}
pub fn add(this: *StringBuilder, len: usize) bun.StringPointer {
if (comptime Environment.allow_assert) {
assert(this.len <= this.cap); // didn't count everything
assert(this.ptr != null); // must call allocate first
}
const start = this.len;
this.len += len;
if (comptime Environment.allow_assert) assert(this.len <= this.cap);
return bun.StringPointer{ .offset = @as(u32, @truncate(start)), .length = @as(u32, @truncate(len)) };
}
pub fn appendCount(this: *StringBuilder, slice: string) bun.StringPointer {
if (comptime Environment.allow_assert) {
assert(this.len <= this.cap); // didn't count everything
assert(this.ptr != null); // must call allocate first
}
const start = this.len;
bun.copy(u8, this.ptr.?[this.len..this.cap], slice);
const result = this.ptr.?[this.len..this.cap][0..slice.len];
_ = result;
this.len += slice.len;
if (comptime Environment.allow_assert) assert(this.len <= this.cap);
return bun.StringPointer{ .offset = @as(u32, @truncate(start)), .length = @as(u32, @truncate(slice.len)) };
}
pub fn fmt(this: *StringBuilder, comptime str: string, args: anytype) string {
if (comptime Environment.allow_assert) {
assert(this.len <= this.cap); // didn't count everything
assert(this.ptr != null); // must call allocate first
}
var buf = this.ptr.?[this.len..this.cap];
const out = std.fmt.bufPrint(buf, str, args) catch unreachable;
this.len += out.len;
if (comptime Environment.allow_assert) assert(this.len <= this.cap);
return out;
}
pub fn fmtAppendCount(this: *StringBuilder, comptime str: string, args: anytype) bun.StringPointer {
if (comptime Environment.allow_assert) {
assert(this.len <= this.cap); // didn't count everything
assert(this.ptr != null); // must call allocate first
}
var buf = this.ptr.?[this.len..this.cap];
const out = std.fmt.bufPrint(buf, str, args) catch unreachable;
const off = this.len;
this.len += out.len;
if (comptime Environment.allow_assert) assert(this.len <= this.cap);
return bun.StringPointer{
.offset = @as(u32, @truncate(off)),
.length = @as(u32, @truncate(out.len)),
};
}
pub fn fmtCount(this: *StringBuilder, comptime str: string, args: anytype) void {
this.cap += std.fmt.count(str, args);
}
pub fn allocatedSlice(this: *StringBuilder) []u8 {
var ptr = this.ptr orelse return &[_]u8{};
if (comptime Environment.allow_assert) {
assert(this.cap > 0);
}
return ptr[0..this.cap];
}
pub fn writable(this: *StringBuilder) []u8 {
var ptr = this.ptr orelse return &[_]u8{};
if (comptime Environment.allow_assert) {
assert(this.cap > 0);
}
return ptr[this.len..this.cap];
}
|