Change strings.Builder to be distinct [dynamic]byte from a struct wrapper

This commit is contained in:
gingerBill
2026-06-09 13:56:10 +01:00
parent d80720e30d
commit 2f3aefbb3d
12 changed files with 108 additions and 111 deletions

View File

@@ -207,7 +207,7 @@ encode :: encode_into
encode_into_bytes :: proc(v: Value, flags := ENCODE_SMALL, allocator := context.allocator, temp_allocator := context.temp_allocator, loc := #caller_location) -> (data: []byte, err: Encode_Error) {
b := strings.builder_make(allocator, loc) or_return
encode_into_builder(&b, v, flags, temp_allocator) or_return
return b.buf[:], nil
return b[:], nil
}
// Encodes the CBOR value into binary CBOR written to the given builder.
@@ -396,7 +396,7 @@ _decode_bytes :: proc(d: Decoder, add: Add, type: Major = .Bytes, allocator := c
if iter_n == -1 {
return nil, .Nested_Indefinite_Length
}
reserve(&buf.buf, len(buf.buf) + iter_cap) or_return
reserve(&buf, len(buf) + iter_cap) or_return
io.copy_n(buf_stream, d.reader, i64(iter_n)) or_return
case .Other:
@@ -411,12 +411,12 @@ _decode_bytes :: proc(d: Decoder, add: Add, type: Major = .Bytes, allocator := c
io.copy_n(buf_stream, d.reader, i64(n)) or_return
}
v = buf.buf[:]
v = buf[:]
// Write zero byte so this can be converted to cstring.
strings.write_byte(&buf, 0)
if .Shrink_Excess in d.flags { shrink(&buf.buf) }
if .Shrink_Excess in d.flags { shrink(&buf) }
return
}
@@ -561,7 +561,7 @@ _encode_map :: proc(e: Encoder, m: Map) -> (err: Encode_Error) {
ke.writer = strings.to_stream(&buf)
encode(ke, entry.entry.key) or_return
entry.encoded_key = buf.buf[:]
entry.encoded_key = buf[:]
}
// Sort lexicographic on the bytes of the key.

View File

@@ -58,7 +58,7 @@ marshal_into_bytes :: proc(v: any, flags := ENCODE_SMALL, allocator := context.a
return
}
return b.buf[:], nil
return b[:], nil
}
// Marshals the given value into a CBOR byte stream written to the given builder.
@@ -379,7 +379,7 @@ _marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (er
err := _encode_u64(e, u64(len(str)), .Text)
assert(err == nil)
res[9] = u8(len(builder.buf))
res[9] = u8(len(builder))
assert(res[9] < 10)
return
}
@@ -476,7 +476,7 @@ _marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (er
key := rawptr(runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index))
key_builder := strings.builder_make(0, 8, e.temp_allocator) or_return
marshal_into(Encoder{e.flags, strings.to_stream(&key_builder), e.temp_allocator}, any{ key, info.key.id }) or_return
append(&entries, Encoded_Entry{ &key_builder.buf, bucket_index }) or_return
append(&entries, Encoded_Entry{ (^[dynamic]byte)(&key_builder), bucket_index }) or_return
}
slice.sort_by_cmp(entries[:], proc(a, b: Encoded_Entry) -> slice.Ordering {
@@ -555,7 +555,7 @@ _marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (er
key_builder := strings.builder_make(e.temp_allocator) or_return
err_conv(_encode_text(Encoder{e.flags, strings.to_stream(&key_builder), e.temp_allocator}, fname)) or_return
append(&entries, Name{key_builder.buf[:], i}) or_return
append(&entries, Name{key_builder[:], i}) or_return
}
// Sort lexicographic on the bytes of the key.

View File

@@ -311,7 +311,7 @@ tag_base64_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number,
b64_decode_into(strings.to_stream(&builder), bytes) or_return
raw := (^cstring)(v.data)
raw^ = cstring(raw_data(builder.buf))
raw^ = cstring(raw_data(builder))
} else {
raw := (^string)(v.data)
raw^ = string(b64_decode(bytes) or_return)

View File

@@ -146,8 +146,8 @@ marshal :: proc(v: any, opt: Marshal_Options = {}, allocator := context.allocato
opt := opt
marshal_to_builder(&b, v, &opt) or_return
if len(b.buf) != 0 {
data = b.buf[:]
if len(b) != 0 {
data = b[:]
}
return data, nil

View File

@@ -161,7 +161,7 @@ decode :: proc(data: []byte, allocator := context.allocator) -> (blk: ^Block, re
@(require_results)
encode :: proc(label: string, data: []byte, newline := false, allocator := context.allocator) -> (res: []byte, err: runtime.Allocator_Error) #optional_allocator_error {
sanitize_sb := proc(sb: ^strings.Builder) {
buf := sb.buf[:]
buf := sb[:]
b, l := raw_data(buf), len(buf)
crypto.zero_explicit(b, l)
strings.builder_destroy(sb)

View File

@@ -120,11 +120,11 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
switch header.format {
// Compressed binary
case .P4:
header_buf := data.buf[:]
header_buf := data[:]
pixels := img.pixels.buf[:]
p4_buffer_size := (img.width / 8 + 1) * img.height
reserve(&data.buf, len(header_buf) + p4_buffer_size)
reserve(&data, len(header_buf) + p4_buffer_size)
// we build up a byte value until it is completely filled
// or we reach the end the row
@@ -138,39 +138,39 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
b |= (v << bit)
if bit == 0 {
append(&data.buf, b)
append(&data, b)
b = 0
}
}
if b != 0 {
append(&data.buf, b)
append(&data, b)
b = 0
}
}
// Simple binary
case .P5, .P6, .P7, .Pf, .PF:
header_buf := data.buf[:]
header_buf := data[:]
pixels := img.pixels.buf[:]
resize(&data.buf, len(header_buf) + len(pixels))
mem.copy(raw_data(data.buf[len(header_buf):]), raw_data(pixels), len(pixels))
resize(&data, len(header_buf) + len(pixels))
mem.copy(raw_data(data[len(header_buf):]), raw_data(pixels), len(pixels))
// convert from native endianness
if img.depth == 16 {
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
pixels := mem.slice_data_cast([]u16be, data[len(header_buf):])
for &p in pixels {
p = u16be(transmute(u16) p)
}
} else if header.format in PFM {
if header.little_endian {
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
pixels := mem.slice_data_cast([]f32le, data[len(header_buf):])
for &p in pixels {
p = f32le(transmute(f32) p)
}
} else {
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
pixels := mem.slice_data_cast([]f32be, data[len(header_buf):])
for &p in pixels {
p = f32be(transmute(f32) p)
}
@@ -183,9 +183,9 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
for y in 0 ..< img.height {
for x in 0 ..< img.width {
i := y * img.width + x
append(&data.buf, '0' if pixels[i] == 0 else '1')
append(&data, '0' if pixels[i] == 0 else '1')
}
append(&data.buf, '\n')
append(&data, '\n')
}
// Token ASCII
@@ -220,14 +220,14 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
}
case:
return data.buf[:], .Invalid_Image_Depth
return data[:], .Invalid_Image_Depth
}
case:
return data.buf[:], .Invalid_Format
return data[:], .Invalid_Format
}
return data.buf[:], Format_Error.None
return data[:], Format_Error.None
}
parse_header :: proc(data: []byte, allocator := context.allocator) -> (header: Header, length: int, err: Error) {
@@ -405,7 +405,7 @@ _parse_header_pam :: proc(data: []byte, allocator := context.allocator) -> (head
return
}
if len(tupltype.buf) == 0 {
if len(tupltype) == 0 {
fmt.sbprint(&tupltype, value)
} else {
fmt.sbprint(&tupltype, "", value)

View File

@@ -188,7 +188,7 @@ debug :: proc(contents: ..Debuggable, location := #caller_location) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
b: strings.Builder
b.buf.allocator = context.temp_allocator
b.allocator = context.temp_allocator
strings.write_string(&b, "[nbio] ")

View File

@@ -19,9 +19,8 @@ A dynamic byte buffer / string builder with helper procedures
The dynamic array is wrapped inside the struct to be more opaque
You can use `fmt.sbprint*` procedures with a `^strings.Builder` directly
*/
Builder :: struct {
buf: [dynamic]byte,
}
Builder :: distinct [dynamic]byte
/*
Produces an empty Builder
@@ -35,7 +34,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_none :: proc(allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, allocator, loc) or_return }, nil
return Builder(make([dynamic]byte, allocator, loc) or_return), nil
}
/*
Produces a Builder with specified length and capacity `len`.
@@ -51,7 +50,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_len :: proc(len: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, allocator, loc) or_return }, nil
return Builder(make([dynamic]byte, len, allocator, loc) or_return), nil
}
/*
Produces a Builder with specified length `len` and capacity `cap`.
@@ -68,7 +67,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error {
return Builder{buf=make([dynamic]byte, len, cap, allocator, loc) or_return }, nil
return Builder(make([dynamic]byte, len, cap, allocator, loc) or_return), nil
}
/*
Produces a String Builder
@@ -116,7 +115,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_none :: proc(b: ^Builder, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, allocator, loc) or_return
b^ = make(Builder, allocator, loc) or_return
return b, nil
}
/*
@@ -135,7 +134,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, allocator, loc) or_return
b^ = make(Builder, len, allocator, loc) or_return
return b, nil
}
/*
@@ -153,7 +152,7 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error {
b.buf = make([dynamic]byte, len, cap, allocator, loc) or_return
b^ = make(Builder, len, cap, allocator, loc) or_return
return b, nil
}
// Overload simple `builder_init_*` with or without len / ap parameters
@@ -173,7 +172,7 @@ _builder_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byt
}
return
case .Size:
n = i64(len(b.buf))
n = i64(len(b))
return
case .Destroy:
builder_destroy(b)
@@ -215,8 +214,8 @@ Inputs:
- b: A pointer to the Builder
*/
builder_destroy :: proc(b: ^Builder) {
delete(b.buf)
b.buf = nil
delete(b^)
b^ = nil
}
/*
Reserves the Builder byte buffer to a specific capacity, when it's higher than before
@@ -226,7 +225,7 @@ Inputs:
- cap: The desired capacity for the Builder's buffer
*/
builder_grow :: proc(b: ^Builder, cap: int) {
reserve(&b.buf, cap)
reserve(b, cap)
}
/*
Clears the Builder byte buffer content (sets len to zero)
@@ -235,7 +234,7 @@ Inputs:
- b: A pointer to the Builder
*/
builder_reset :: proc(b: ^Builder) {
clear(&b.buf)
clear(b)
}
/*
Creates a Builder from a slice of bytes with the same slice length as its capacity. Used in fmt.bprint*
@@ -268,15 +267,13 @@ Output:
*/
builder_from_bytes :: proc(backing: []byte) -> (res: Builder) {
return Builder{
buf = transmute([dynamic]byte)runtime.Raw_Dynamic_Array{
data = raw_data(backing),
len = 0,
cap = len(backing),
allocator = runtime.Allocator{
procedure = runtime.nil_allocator_proc,
data = nil,
},
return transmute(Builder)runtime.Raw_Dynamic_Array{
data = raw_data(backing),
len = 0,
cap = len(backing),
allocator = runtime.Allocator{
procedure = runtime.nil_allocator_proc,
data = nil,
},
}
}
@@ -293,7 +290,7 @@ Returns:
- res: The contents of the Builder's buffer, as a string
*/
to_string :: proc(b: Builder) -> (res: string) {
return string(b.buf[:])
return string(b[:])
}
/*
Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring
@@ -307,9 +304,9 @@ Returns:
- res: A cstring of the Builder's buffer
*/
unsafe_to_cstring :: proc(b: ^Builder, loc := #caller_location) -> (res: cstring) {
append(&b.buf, 0, loc)
pop(&b.buf)
return cstring(raw_data(b.buf))
append(b, 0, loc)
pop(b)
return cstring(raw_data(b^))
}
/*
Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring
@@ -322,15 +319,15 @@ Returns:
- err: An optional allocator error if one occured, `nil` otherwise
*/
to_cstring :: proc(b: ^Builder, loc := #caller_location) -> (res: cstring, err: runtime.Allocator_Error) #optional_allocator_error {
n := append(&b.buf, 0, loc) or_return
n := append(b, 0, loc) or_return
if n != 1 {
return nil, .Out_Of_Memory
}
pop(&b.buf)
pop(b)
#no_bounds_check {
assert(b.buf[len(b.buf)] == 0)
assert(b[len(b)] == 0)
}
return cstring(raw_data(b.buf)), nil
return cstring(raw_data(b^)), nil
}
/*
Returns the length of the Builder's buffer, in bytes
@@ -342,7 +339,7 @@ Returns:
- res: The length of the Builder's buffer
*/
builder_len :: proc(b: Builder) -> (res: int) {
return len(b.buf)
return len(b)
}
/*
Returns the capacity of the Builder's buffer, in bytes
@@ -354,7 +351,7 @@ Returns:
- res: The capacity of the Builder's buffer
*/
builder_cap :: proc(b: Builder) -> (res: int) {
return cap(b.buf)
return cap(b)
}
/*
The free space left in the Builder's buffer, in bytes
@@ -366,7 +363,7 @@ Returns:
- res: The available space left in the Builder's buffer
*/
builder_space :: proc(b: Builder) -> (res: int) {
return cap(b.buf) - len(b.buf)
return cap(b) - len(b)
}
/*
Appends a byte to the Builder and returns the number of bytes appended
@@ -398,9 +395,9 @@ Output:
*/
write_byte :: proc(b: ^Builder, x: byte, loc := #caller_location) -> (n: int) {
n0 := len(b.buf)
append(&b.buf, x, loc)
n1 := len(b.buf)
n0 := len(b)
append(b, x, loc)
n1 := len(b)
return n1-n0
}
/*
@@ -428,9 +425,9 @@ Returns:
- n: The number of bytes appended
*/
write_bytes :: proc(b: ^Builder, x: []byte, loc := #caller_location) -> (n: int) {
n0 := len(b.buf)
append(&b.buf, ..x, loc=loc)
n1 := len(b.buf)
n0 := len(b)
append(b, ..x, loc=loc)
n1 := len(b)
return n1-n0
}
/*
@@ -529,9 +526,9 @@ Output:
*/
write_string :: proc(b: ^Builder, s: string, loc := #caller_location) -> (n: int) {
n0 := len(b.buf)
append(&b.buf, s, loc)
n1 := len(b.buf)
n0 := len(b)
append(b, s, loc)
n1 := len(b)
return n1-n0
}
/*
@@ -544,12 +541,12 @@ Returns:
- r: The last byte in the Builder or 0 if empty
*/
pop_byte :: proc(b: ^Builder) -> (r: byte) {
if len(b.buf) == 0 {
if len(b) == 0 {
return 0
}
r = b.buf[len(b.buf)-1]
d := (^runtime.Raw_Dynamic_Array)(&b.buf)
r = b[len(b)-1]
d := (^runtime.Raw_Dynamic_Array)(b)
d.len = max(d.len-1, 0)
return
}
@@ -564,12 +561,12 @@ Returns:
- width: The rune width or 0 if the builder was empty
*/
pop_rune :: proc(b: ^Builder) -> (r: rune, width: int) {
if len(b.buf) == 0 {
if len(b) == 0 {
return 0, 0
}
r, width = utf8.decode_last_rune(b.buf[:])
d := (^runtime.Raw_Dynamic_Array)(&b.buf)
r, width = utf8.decode_last_rune(b[:])
d := (^runtime.Raw_Dynamic_Array)(b)
d.len = max(d.len-width, 0)
return
}
@@ -892,7 +889,7 @@ builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_lo
if len(old) == 0 {
// NOTE(bill): reserve the necessary memory
found := 0
for i := 0; i <= len(b.buf); i += len(new)+1 {
for i := 0; i <= len(b); i += len(new)+1 {
if n > 0 && found == n {
break
}
@@ -901,29 +898,29 @@ builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_lo
if found == 0 {
return
}
reserve(&b.buf, len(b.buf) + len(new)*found) or_return
reserve(b, len(b) + len(new)*found) or_return
for i := 0; i <= len(b.buf); i += len(new)+1 {
for i := 0; i <= len(b); i += len(new)+1 {
if n > 0 && replaced == n {
break
}
resize(&b.buf, len(b.buf)+len(new), loc) or_return
copy(b.buf[i+len(new):], b.buf[i:])
copy(b.buf[i:], new)
resize(b, len(b)+len(new), loc) or_return
copy(b[i+len(new):], b[i:])
copy(b[i:], new)
replaced += 1
}
} else {
if len(new) > len(old) {
// NOTE(bill): reserve the necessary memory
found := 0
for i := 0; i < len(b.buf); /**/ {
for i := 0; i < len(b); /**/ {
if n > 0 && found == n {
break
}
j := index(string(b.buf[i:]), old)
j := index(string(b[i:]), old)
if j < 0 {
break
}
@@ -933,24 +930,24 @@ builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_lo
if found == 0 {
return
}
reserve(&b.buf, len(b.buf) + (len(new)-len(old))*found) or_return
reserve(b, len(b) + (len(new)-len(old))*found) or_return
}
for i := 0; i < len(b.buf); /**/ {
for i := 0; i < len(b); /**/ {
if n > 0 && replaced == n {
break
}
j := index(string(b.buf[i:]), old)
j := index(string(b[i:]), old)
if j < 0 {
break
}
if len(new) > len(old) {
resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return
resize(b, len(b) + len(new)-len(old)) or_return
}
cur := b.buf[i+j:]
cur := b[i+j:]
src := cur[len(old):]
dst := cur[len(new):]
copy(dst, src)
@@ -961,7 +958,7 @@ builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_lo
replaced += 1
if len(new) < len(old) {
resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return
resize(b, len(b) + len(new)-len(old)) or_return
}
}
}

View File

@@ -68,9 +68,9 @@ _os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (
build = string(cstring(raw_data(build_buf[:])))
}
ws(&b, " (build ")
build_start := len(b.buf)
build_start := len(b)
ws(&b, build)
res.release = string(b.buf[build_start:][:len(build)])
res.release = string(b[build_start:][:len(build)])
}
{

View File

@@ -65,7 +65,7 @@ _os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (
release_i := strings.builder_len(b)
strings.write_string(&b, string(cstring(&uts.release[0])))
release_str := string(b.buf[release_i:])
release_str := string(b[release_i:])
res.full = strings.to_string(b)

View File

@@ -94,7 +94,7 @@ begin :: proc(s: ^State, id: u64, builder: ^strings.Builder) {
end(s)
}
s.id = id
s.selection = {len(builder.buf), 0}
s.selection = {len(builder), 0}
s.builder = builder
update_time(s)
undo_clear(s, &s.undo)
@@ -118,7 +118,7 @@ update_time :: proc(s: ^State) {
// setup the builder, selection and undo|redo state once allowing to retain selection
setup_once :: proc(s: ^State, builder: ^strings.Builder) {
s.builder = builder
s.selection = { len(builder.buf), 0 }
s.selection = { len(builder), 0 }
undo_clear(s, &s.undo)
undo_clear(s, &s.redo)
}
@@ -126,8 +126,8 @@ setup_once :: proc(s: ^State, builder: ^strings.Builder) {
// returns true when the builder had content to be cleared
// clear builder&selection and the undo|redo stacks
clear_all :: proc(s: ^State) -> (cleared: bool) {
if s.builder != nil && len(s.builder.buf) > 0 {
clear(&s.builder.buf)
if s.builder != nil && len(s.builder) > 0 {
clear(s.builder)
s.selection = {}
cleared = true
}
@@ -142,7 +142,7 @@ undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator
if s.builder == nil {
return nil
}
text := string(s.builder.buf[:])
text := string(s.builder[:])
item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator) or_return)
item.selection = s.selection
item.len = len(text)
@@ -234,13 +234,13 @@ input_rune :: proc(s: ^State, r: rune) {
insert :: proc(s: ^State, at: int, text: string) -> int {
undo_check(s)
if s.builder != nil {
if ok, _ := inject_at(&s.builder.buf, at, text); !ok {
n := cap(s.builder.buf) - len(s.builder.buf)
if ok, _ := inject_at(s.builder, at, text); !ok {
n := cap(s.builder) - len(s.builder)
assert(n < len(text))
for is_continuation_byte(text[n]) {
n -= 1
}
if ok2, _ := inject_at(&s.builder.buf, at, text[:n]); !ok2 {
if ok2, _ := inject_at(s.builder, at, text[:n]); !ok2 {
n = 0
}
return n
@@ -254,7 +254,7 @@ insert :: proc(s: ^State, at: int, text: string) -> int {
remove :: proc(s: ^State, lo, hi: int) {
undo_check(s)
if s.builder != nil {
remove_range(&s.builder.buf, lo, hi)
remove_range(s.builder, lo, hi)
}
}
@@ -269,8 +269,8 @@ has_selection :: proc(s: ^State) -> bool {
sorted_selection :: proc(s: ^State) -> (lo, hi: int) {
lo = min(s.selection[0], s.selection[1])
hi = max(s.selection[0], s.selection[1])
lo = clamp(lo, 0, len(s.builder.buf) if s.builder != nil else 0)
hi = clamp(hi, 0, len(s.builder.buf) if s.builder != nil else 0)
lo = clamp(lo, 0, len(s.builder) if s.builder != nil else 0)
hi = clamp(hi, 0, len(s.builder) if s.builder != nil else 0)
return
}
@@ -293,7 +293,7 @@ translate_position :: proc(s: ^State, t: Translation) -> int {
buf: []byte
if s.builder != nil {
buf = s.builder.buf[:]
buf = s.builder[:]
}
pos := clamp(s.selection[0], 0, len(buf))
@@ -400,7 +400,7 @@ delete_to :: proc(s: ^State, t: Translation) {
current_selected_text :: proc(s: ^State) -> string {
lo, hi := sorted_selection(s)
if s.builder != nil {
return string(s.builder.buf[lo:hi])
return string(s.builder[lo:hi])
}
return ""
}
@@ -481,7 +481,7 @@ perform_command :: proc(s: ^State, cmd: Command) {
case .Cut: cut(s)
case .Copy: copy(s)
case .Paste: paste(s)
case .Select_All: s.selection = {len(s.builder.buf) if s.builder != nil else 0, 0}
case .Select_All: s.selection = {len(s.builder) if s.builder != nil else 0, 0}
case .Backspace: delete_to(s, .Left)
case .Delete: delete_to(s, .Right)
case .Delete_Word_Left: delete_to(s, .Word_Left)

View File

@@ -996,7 +996,7 @@ textbox_raw :: proc(ctx: ^Context, textbuf: []u8, textlen: ^int, id: Id, r: Rect
if ctx.focus_id == id {
/* create a builder backed by the user's buffer */
builder := strings.builder_from_bytes(textbuf)
non_zero_resize(&builder.buf, textlen^)
non_zero_resize(&builder, textlen^)
ctx.textbox_state.builder = &builder
if ctx.textbox_state.id != u64(id) {
ctx.textbox_state.id = u64(id)