// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module strings /* pub struct Builder { mut: buf []u8 pub mut: len int initial_size int = 1 }*/ pub type Builder = []u8 pub fn new_builder(initial_size int) Builder { return []u8{cap: initial_size} } pub fn (mut b Builder) write_byte(data u8) { b << data } pub fn (mut b Builder) write_u8(data u8) { b << data } // write_decimal appends a decimal representation of the number `n` into the builder `b`. // The higher order digits come first, i.e. 6123 will be written with the digit `6` first, // then `1`, then `2` and `3` last. pub fn (mut b Builder) write_decimal(n i64) { if n == 0 { b.write_u8(0x30) return } mut mag := u64(n) if n < 0 { b.write_u8(`-`) // Wrapping unsigned negation yields the correct magnitude even for `min_i64`, // whose absolute value does not fit in an i64. It also avoids depending on the // `min_i64` constant, which the JS backend currently lowers incorrectly, so a // runtime `min_i64` (e.g. from `'-9223372036854775808'.i64()`) still formats right. mag = u64(0) - mag } b.write_u_decimal(mag) } // write_u_decimal appends a decimal representation of the unsigned number `n` into the // builder `b`. Unlike `write_decimal`, it covers the entire `u64` range (values above // `max_i64`). The higher order digits come first. pub fn (mut b Builder) write_u_decimal(n u64) { if n == 0 { b.write_u8(0x30) return } mut buf := [20]u8{} // max_u64 == 18446744073709551615, i.e. 20 digits mut x := n mut i := 19 for x != 0 { buf[i] = u8(x % 10) + 0x30 x = x / 10 i-- } for j := i + 1; j <= 19; j++ { b.write_u8(buf[j]) } } pub fn (mut b Builder) write(data []u8) ?int { if data.len == 0 { return 0 } b << data return data.len } pub fn (b &Builder) byte_at(n int) u8 { unsafe { return b[n] } } pub fn (mut b Builder) write_string(s string) { if s == '' { return } for c in s { b << c } } pub fn (mut b Builder) writeln(s string) { if s != '' { b.write_string(s) } b << 10 } pub fn (mut b Builder) str() string { s := '' #for (const c of b.val.arr.arr) #s.str += String.fromCharCode(+c) b.clear() return s } pub fn (mut b Builder) cut_last(n int) string { cut_pos := b.len - n x := unsafe { b[cut_pos..] } res := x.bytestr() b.trim(cut_pos) return res } pub fn (mut b Builder) go_back_to(pos int) { b.trim(pos) } // go_back discards the last `n` bytes from the buffer. pub fn (mut b Builder) go_back(n int) { b.trim(b.len - n) } // cut_to cuts the string after `pos` and returns it. // if `pos` is superior to builder length, returns an empty string // and cancel further operations pub fn (mut b Builder) cut_to(pos int) string { if pos > b.len { return '' } return b.cut_last(b.len - pos) } pub fn (mut b Builder) write_runes(runes []rune) { for r in runes { res := r.str() #res.str = String.fromCharCode(r.val) b << res.bytes() } } // after(6) returns 'world' // buf == 'hello world' pub fn (mut b Builder) after(n int) string { if n >= b.len { return '' } x := unsafe { b[n..b.len] } return x.bytestr() } // last_n(5) returns 'world' // buf == 'hello world' pub fn (mut b Builder) last_n(n int) string { if n >= b.len { return '' } x := unsafe { b[b.len - n..b.len] } return x.bytestr() }