vxx2 / vlib / strings / builder.js.v
166 lines · 142 sloc · 3.33 KB · 106e6ec1141d9a4382a13e40641aadee6313c717
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module strings
5
6/*
7pub struct Builder {
8mut:
9 buf []u8
10pub mut:
11 len int
12 initial_size int = 1
13}*/
14
15pub type Builder = []u8
16
17pub fn new_builder(initial_size int) Builder {
18 return []u8{cap: initial_size}
19}
20
21pub fn (mut b Builder) write_byte(data u8) {
22 b << data
23}
24
25pub fn (mut b Builder) write_u8(data u8) {
26 b << data
27}
28
29// write_decimal appends a decimal representation of the number `n` into the builder `b`.
30// The higher order digits come first, i.e. 6123 will be written with the digit `6` first,
31// then `1`, then `2` and `3` last.
32pub fn (mut b Builder) write_decimal(n i64) {
33 if n == 0 {
34 b.write_u8(0x30)
35 return
36 }
37 mut mag := u64(n)
38 if n < 0 {
39 b.write_u8(`-`)
40 // Wrapping unsigned negation yields the correct magnitude even for `min_i64`,
41 // whose absolute value does not fit in an i64. It also avoids depending on the
42 // `min_i64` constant, which the JS backend currently lowers incorrectly, so a
43 // runtime `min_i64` (e.g. from `'-9223372036854775808'.i64()`) still formats right.
44 mag = u64(0) - mag
45 }
46 b.write_u_decimal(mag)
47}
48
49// write_u_decimal appends a decimal representation of unsigned `n` to the builder.
50// Unlike `write_decimal`, it covers the entire `u64` range (values above
51// `max_i64`). The higher order digits come first.
52pub fn (mut b Builder) write_u_decimal(n u64) {
53 if n == 0 {
54 b.write_u8(0x30)
55 return
56 }
57 mut buf := [20]u8{} // max_u64 == 18446744073709551615, i.e. 20 digits
58 mut x := n
59 mut i := 19
60 for x != 0 {
61 buf[i] = u8(x % 10) + 0x30
62 x = x / 10
63 i--
64 }
65 for j := i + 1; j <= 19; j++ {
66 b.write_u8(buf[j])
67 }
68}
69
70pub fn (mut b Builder) write(data []u8) ?int {
71 if data.len == 0 {
72 return 0
73 }
74 b << data
75 return data.len
76}
77
78pub fn (b &Builder) byte_at(n int) u8 {
79 unsafe {
80 return b[n]
81 }
82}
83
84pub fn (mut b Builder) write_string(s string) {
85 if s == '' {
86 return
87 }
88
89 for c in s {
90 b << c
91 }
92}
93
94pub fn (mut b Builder) writeln(s string) {
95 if s != '' {
96 b.write_string(s)
97 }
98
99 b << 10
100}
101
102pub fn (mut b Builder) str() string {
103 s := ''
104
105 #for (const c of b.val.arr.arr)
106 #s.str += String.fromCharCode(+c)
107 b.clear()
108 return s
109}
110
111pub fn (mut b Builder) cut_last(n int) string {
112 cut_pos := b.len - n
113 x := unsafe { b[cut_pos..] }
114 res := x.bytestr()
115 b.trim(cut_pos)
116 return res
117}
118
119pub fn (mut b Builder) go_back_to(pos int) {
120 b.trim(pos)
121}
122
123// go_back discards the last `n` bytes from the buffer.
124pub fn (mut b Builder) go_back(n int) {
125 b.trim(b.len - n)
126}
127
128// cut_to cuts the string after `pos` and returns it.
129// if `pos` is superior to builder length, returns an empty string
130// and cancel further operations
131pub fn (mut b Builder) cut_to(pos int) string {
132 if pos > b.len {
133 return ''
134 }
135 return b.cut_last(b.len - pos)
136}
137
138pub fn (mut b Builder) write_runes(runes []rune) {
139 for r in runes {
140 res := r.str()
141 #res.str = String.fromCharCode(r.val)
142 b << res.bytes()
143 }
144}
145
146// after(6) returns 'world'
147// buf == 'hello world'
148pub fn (mut b Builder) after(n int) string {
149 if n >= b.len {
150 return ''
151 }
152
153 x := unsafe { b[n..b.len] }
154 return x.bytestr()
155}
156
157// last_n(5) returns 'world'
158// buf == 'hello world'
159pub fn (mut b Builder) last_n(n int) string {
160 if n >= b.len {
161 return ''
162 }
163
164 x := unsafe { b[b.len - n..b.len] }
165 return x.bytestr()
166}
167