github.com/richardwilkes/toolbox@v1.121.0/xio/byte_buffer.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package xio 11 12 import ( 13 "io" 14 "unicode/utf8" 15 16 "github.com/richardwilkes/toolbox/errs" 17 ) 18 19 // ByteBuffer is a variable-sized buffer of bytes with Write and Insert methods. The zero value for ByteBuffer is an 20 // empty buffer ready to use. 21 type ByteBuffer struct { 22 data []byte 23 } 24 25 // Bytes returns the underlying buffer of bytes. 26 func (b *ByteBuffer) Bytes() []byte { 27 return b.data 28 } 29 30 // String returns the underlying buffer of bytes as a string. If the ByteBuffer is a nil pointer, it returns "<nil>". 31 func (b *ByteBuffer) String() string { 32 if b == nil { 33 return "<nil>" 34 } 35 return string(b.data) 36 } 37 38 // Len returns the number of bytes contained by the buffer. 39 func (b *ByteBuffer) Len() int { 40 return len(b.data) 41 } 42 43 // Cap returns the capacity of the buffer. 44 func (b *ByteBuffer) Cap() int { 45 return cap(b.data) 46 } 47 48 // Truncate discards all but the first n bytes from the buffer. 49 func (b *ByteBuffer) Truncate(n int) { 50 b.data = b.data[:n] 51 } 52 53 // Reset resets the buffer to be empty. 54 func (b *ByteBuffer) Reset() { 55 b.data = b.data[:0] 56 } 57 58 // Insert data at the given offset. 59 func (b *ByteBuffer) Insert(index int, data []byte) error { 60 if index < 0 || index > len(b.data) { 61 return errs.New("invalid index") 62 } 63 if len(data) != 0 { 64 b.data = append(b.data, data...) 65 copy(b.data[index+len(data):], b.data[index:]) 66 copy(b.data[index:], data) 67 } 68 return nil 69 } 70 71 // InsertByte inserts a byte at the given offset. 72 func (b *ByteBuffer) InsertByte(index int, ch byte) error { 73 if index < 0 || index > len(b.data) { 74 return errs.New("invalid index") 75 } 76 b.data = append(b.data, 0) 77 copy(b.data[index+1:], b.data[index:]) 78 b.data[index] = ch 79 return nil 80 } 81 82 // InsertRune inserts the UTF-8 encoding of the rune at the given offset. 83 func (b *ByteBuffer) InsertRune(index int, r rune) error { 84 if uint32(r) < utf8.RuneSelf { 85 return b.InsertByte(index, byte(r)) 86 } 87 var buffer [4]byte 88 n := utf8.EncodeRune(buffer[:], r) 89 return b.Insert(index, buffer[:n]) 90 } 91 92 // InsertString inserts the string at the given offset. 93 func (b *ByteBuffer) InsertString(index int, s string) error { 94 return b.Insert(index, []byte(s)) 95 } 96 97 // Write appends the contents of data to the buffer. 98 func (b *ByteBuffer) Write(data []byte) (int, error) { 99 b.data = append(b.data, data...) 100 return len(data), nil 101 } 102 103 // WriteByte appends the byte to the buffer. 104 func (b *ByteBuffer) WriteByte(ch byte) error { 105 b.data = append(b.data, ch) 106 return nil 107 } 108 109 // WriteRune appends the UTF-8 encoding of the rune to the buffer. 110 func (b *ByteBuffer) WriteRune(r rune) (int, error) { 111 if uint32(r) < utf8.RuneSelf { 112 b.data = append(b.data, byte(r)) 113 return 1, nil 114 } 115 i := len(b.data) 116 b.data = append(b.data, 0, 0, 0, 0) 117 n := utf8.EncodeRune(b.data[i:i+4], r) 118 b.data = b.data[:i+n] 119 return n, nil 120 } 121 122 // WriteString appends the string to the buffer. 123 func (b *ByteBuffer) WriteString(s string) (int, error) { 124 b.data = append(b.data, []byte(s)...) 125 return len(s), nil 126 } 127 128 // WriteTo writes data to w until the buffer is drained or an error occurs. 129 func (b *ByteBuffer) WriteTo(w io.Writer) (int64, error) { 130 var n int64 131 if nBytes := b.Len(); nBytes > 0 { 132 m, err := w.Write(b.data) 133 n = int64(m) 134 if err != nil { 135 return n, err 136 } 137 if m != nBytes { 138 return n, io.ErrShortWrite 139 } 140 } 141 return n, nil 142 }