github.com/mitranim/gg@v0.1.17/buf.go (about) 1 package gg 2 3 import ( 4 "fmt" 5 "io" 6 "strconv" 7 "unicode/utf8" 8 ) 9 10 /* 11 Short for "buffer". Simpler, cleaner, more usable alternative to 12 `strings.Builder` and `bytes.Buffer`. 13 */ 14 type Buf []byte 15 16 var ( 17 _ = fmt.Stringer(Zero[Buf]()) 18 _ = AppenderTo(Zero[Buf]()) 19 _ = io.Writer(Zero[*Buf]()) 20 _ = io.StringWriter(Zero[*Buf]()) 21 ) 22 23 /* 24 Free cast to a string. Mutation of the original buffer affects the resulting 25 string. 26 */ 27 func (self Buf) String() string { return ToString(self) } 28 29 /* 30 Implement `AppenderTo`. Appends its own content to the given buffer. 31 If the given buffer has no capacity, returns itself. 32 */ 33 func (self Buf) AppendTo(val []byte) []byte { 34 if !(cap(val) > 0) { 35 return self 36 } 37 return append(val, self...) 38 } 39 40 /* 41 Implement `io.StringWriter`, appending the input to the buffer. 42 The error is always nil and may be ignored. 43 */ 44 func (self *Buf) WriteString(val string) (int, error) { 45 *self = append(*self, val...) 46 return len(val), nil 47 } 48 49 /* 50 Implement `io.Writer`, appending the input to the buffer. 51 The error is always nil and may be ignored. 52 */ 53 func (self *Buf) Write(val []byte) (int, error) { 54 *self = append(*self, val...) 55 return len(val), nil 56 } 57 58 // Appends the given string. Mutates the receiver. 59 func (self *Buf) AppendString(val string) { *self = append(*self, val...) } 60 61 // Appends the given string N times. Mutates the receiver. 62 func (self *Buf) AppendStringN(val string, count int) { 63 if len(val) > 0 { 64 for count > 0 { 65 count-- 66 self.AppendString(val) 67 } 68 } 69 } 70 71 // Appends `Indent`. Mutates the receiver. 72 func (self *Buf) AppendIndent() { self.AppendString(Indent) } 73 74 // Appends `Indent` N times. Mutates the receiver. 75 func (self *Buf) AppendIndents(lvl int) { self.AppendStringN(Indent, lvl) } 76 77 // Appends the given bytes. Mutates the receiver. 78 func (self *Buf) AppendBytes(val []byte) { *self = append(*self, val...) } 79 80 // Appends the given byte. Mutates the receiver. 81 func (self *Buf) AppendByte(val byte) { *self = append(*self, val) } 82 83 // Appends the given rune. Mutates the receiver. 84 func (self *Buf) AppendRune(val rune) { *self = utf8.AppendRune(*self, val) } 85 86 // Appends the given rune N times. Mutates the receiver. 87 func (self *Buf) AppendRuneN(val rune, count int) { 88 for count > 0 { 89 count-- 90 self.AppendRune(val) 91 } 92 } 93 94 // Appends a single space. Mutates the receiver. 95 func (self *Buf) AppendSpace() { self.AppendByte(' ') } 96 97 // Appends a space N times. Mutates the receiver. 98 func (self *Buf) AppendSpaces(count int) { self.AppendByteN(' ', count) } 99 100 // Appends the given byte N times. Mutates the receiver. 101 func (self *Buf) AppendByteN(val byte, count int) { 102 for count > 0 { 103 count-- 104 self.AppendByte(val) 105 } 106 } 107 108 // Appends `Newline`. Mutates the receiver. 109 func (self *Buf) AppendNewline() { self.AppendString(Newline) } 110 111 /* 112 If the buffer is non-empty and doesn't end with a newline, appends a newline. 113 Otherwise does nothing. Uses `HasNewlineSuffix`. Mutates the receiver. 114 */ 115 func (self *Buf) AppendNewlineOpt() { 116 if self.Len() > 0 && !HasNewlineSuffix(*self) { 117 self.AppendNewline() 118 } 119 } 120 121 // Appends `Newline` N times. Mutates the receiver. 122 func (self *Buf) AppendNewlines(count int) { self.AppendStringN(Newline, count) } 123 124 /* 125 Appends text representation of the numeric value of the given byte in base 16. 126 Always uses exactly 2 characters, for consistent width, which is the common 127 convention for printing binary data. Mutates the receiver. 128 */ 129 func (self *Buf) AppendByteHex(val byte) { 130 if val < 16 { 131 self.AppendByte('0') 132 } 133 *self = strconv.AppendUint(*self, uint64(val), 16) 134 } 135 136 // Appends text representation of the input. Mutates the receiver. 137 func (self *Buf) AppendUint(val uint) { 138 *self = strconv.AppendUint(*self, uint64(val), 10) 139 } 140 141 // Appends text representation of the input. Mutates the receiver. 142 func (self *Buf) AppendUint64(val uint64) { 143 *self = strconv.AppendUint(*self, val, 10) 144 } 145 146 /* 147 Appends text representation of the input in base 16. Mutates the receiver. 148 Also see `.AppendByteHex`. 149 */ 150 func (self *Buf) AppendUint64Hex(val uint64) { 151 *self = strconv.AppendUint(*self, val, 16) 152 } 153 154 // Appends text representation of the input. Mutates the receiver. 155 func (self *Buf) AppendInt(val int) { 156 *self = strconv.AppendInt(*self, int64(val), 10) 157 } 158 159 // Appends text representation of the input. Mutates the receiver. 160 func (self *Buf) AppendInt64(val int64) { 161 *self = strconv.AppendInt(*self, val, 10) 162 } 163 164 // Appends text representation of the input. Mutates the receiver. 165 func (self *Buf) AppendFloat32(val float32) { 166 *self = strconv.AppendFloat(*self, float64(val), 'f', -1, 32) 167 } 168 169 // Appends text representation of the input. Mutates the receiver. 170 func (self *Buf) AppendFloat64(val float64) { 171 *self = strconv.AppendFloat(*self, val, 'f', -1, 64) 172 } 173 174 // Appends text representation of the input. Mutates the receiver. 175 func (self *Buf) AppendBool(val bool) { *self = strconv.AppendBool(*self, val) } 176 177 /* 178 Appends the string representation of the given error. If the input is nil, this 179 is a nop. Mutates the receiver. 180 */ 181 func (self *Buf) AppendError(val error) { 182 if val == nil { 183 return 184 } 185 186 impl, _ := val.(AppenderTo) 187 if impl != nil { 188 *self = impl.AppendTo(*self) 189 return 190 } 191 192 self.AppendString(val.Error()) 193 } 194 195 /* 196 Appends the text representation of the input, using the `AppendTo` function. 197 Mutates the receiver. 198 */ 199 func (self *Buf) AppendAny(val any) { *self = AppendTo(*self, val) } 200 201 // Like `(*Buf).AppendAny` but variadic. TODO better name. 202 func (self *Buf) AppendAnys(val ...any) { 203 for _, val := range val { 204 self.AppendAny(val) 205 } 206 } 207 208 /* 209 Like `(*Buf).AppendAnys` but ensures a trailing newline in the appended content, 210 similarly to `fmt.Println`. As a special case, if the buffer was empty and the 211 appended content is empty, no newline is appended. TODO better name. 212 */ 213 func (self *Buf) AppendAnysln(val ...any) { 214 start := self.Len() 215 self.AppendAnys(val...) 216 end := self.Len() 217 218 if end > start { 219 self.AppendNewlineOpt() 220 } else if end > 0 { 221 self.AppendNewline() 222 } 223 } 224 225 /* 226 Appends the text representation of the input, using the `AppendGoString` 227 function. Mutates the receiver. 228 */ 229 func (self *Buf) AppendGoString(val any) { *self = AppendGoString(*self, val) } 230 231 // Shortcut for appending a formatted string. 232 func (self *Buf) Fprintf(pat string, arg ...any) { 233 _, _ = fmt.Fprintf(self, pat, NoEscUnsafe(arg)...) 234 } 235 236 // Shortcut for appending a formatted string with an idempotent trailing newline. 237 func (self *Buf) Fprintlnf(pat string, arg ...any) { 238 prev := self.Len() 239 self.Fprintf(pat, arg...) 240 if self.Len() > prev { 241 self.AppendNewlineOpt() 242 } 243 } 244 245 // Same as `len(buf)`. 246 func (self Buf) Len() int { return len(self) } 247 248 // Replaces the buffer with the given slice. 249 func (self *Buf) Reset(src []byte) { *self = src } 250 251 // Increases the buffer's length by N zero values. Mutates the receiver. 252 func (self *Buf) GrowLen(size int) { *self = GrowLen(*self, size) } 253 254 /* 255 Increases the buffer's capacity sufficiently to accommodate N additional 256 elements. Mutates the receiver. 257 */ 258 func (self *Buf) GrowCap(size int) { *self = GrowCap(*self, size) } 259 260 /* 261 Reduces the current length to the given size. If the current length is already 262 shorter, it's unaffected. 263 */ 264 func (self *Buf) TruncLen(size int) { *self = TruncLen(*self, size) } 265 266 /* 267 Truncates the buffer's length, preserving the capacity. Does not modify the 268 content. Mutates the receiver. 269 */ 270 func (self *Buf) Clear() { 271 if self != nil { 272 *self = (*self)[:0] 273 } 274 }