aboutsummaryrefslogtreecommitdiff
path: root/src/string_builder.zig
blob: 2111ffa1aefc0108419e975a1703cc360f3aade3 (plain) (blame)
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
139
140
141
142
143
144
145
146
147
148
149
150
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 append16(this: *StringBuilder, slice: []const u16) ?[:0]u8 {
    var buf = this.writable();
    const result = bun.simdutf.convert.utf16.to.utf8.with_errors.le(slice, buf);
    if (result.status == .success) {
        this.len += result.count + 1;
        buf[result.count] = 0;
        return buf[0..result.count :0];
    }

    return null;
}

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];
}
3-03-01 13:15:52 -0800'>2023-03-01fix deinit behavior when connection is aborted using ResponseStream and ↵Gravatar Ciro Spaciari 3-34/+174 abort event behavior (#2252) * fix deinit behavior when connection is aborted using ResponseStream * fix abort handling on stream, and get better tests * avoid segfault by trying to deinit 2x when aborted * make tests more reliable * more reliable onResolveStream after aborted * add test case for not firing the abort signal 2023-03-01fix Bun.file.arrayBuffer() segmentation fault on empty file #2248 (#2249)Gravatar Ciro Spaciari 3-7/+23 * fix Bun.file.arrayBuffer() segmentation fault on empty file #2248 * cleanner this.iotask check 2023-03-01Fix async in sqliteGravatar Colin McDonnell 1-2/+2 2023-02-28Forces a specific libdir for c-ares (#2241)Gravatar Justin Whear 1-1/+5 The c-ares build expects lib/libcares.a to exist after cmake, but on my system it was being generated in lib64. This simply sets the cmake variable so that the target ends up where we expect. 2023-02-28Make Bun.gc(true) more aggressiveGravatar Jarred Sumner 1-0/+3 2023-02-28Expose JSC::Options via `BUN_JSC_` prefixGravatar Jarred Sumner 6-8/+47 Example usage: BUN_JSC_logGC=1 bun file.js 2023-02-28fixupGravatar Jarred Sumner 1-1/+1 2023-02-28Fix typecheckGravatar Colin McDonnell 2-1/+4 2023-02-28Fix incorrect Bun version in docs (#2236)Gravatar Derrick Farris 1-1/+1 2023-02-28just some comments fix (#2237)Gravatar Ciro Spaciari 1-4/+2 2023-02-28Add `-D`, `--dev` flags for bun install (#2240)Gravatar Justin Whear 1-9/+9 * remove vendored clap * Update to latest zig-clap Major changes: * Instead of vendoring zig-clap and adding changes, this uses Hejsil/zig-clap directly as a submodule * `cli.zig` and related files have been updated to use new API (no more `flag()` or `option()`) * A workaround for the Run and Auto commands has been implemented that allows us to use the official upstream Minor change: * `-i` now has the long option `--install-fallback`; I didn't spend much time thinking about this name, so suggestions weclome. * add --development and --optional to bun install * Add support for `-D`, `--dev` in bun install, fix `--save` 2023-02-28Document punningGravatar Colin McDonnell 1-1/+18