buffer.go (3448B)
1 package byteutil 2 3 import ( 4 "errors" 5 "io" 6 "unicode/utf8" 7 ) 8 9 var ( 10 // ensure we conform to interfaces. 11 _ interface { 12 io.Writer 13 io.ByteWriter 14 WriteRune(rune) (int, error) 15 io.StringWriter 16 io.WriterAt 17 WriteStringAt(string, int64) (int, error) 18 } = (*Buffer)(nil) 19 20 // ErrBeyondBufferLen is returned if .WriteAt() is attempted beyond buffer length. 21 ErrBeyondBufferLen = errors.New("start beyond buffer length") 22 ) 23 24 // Buffer is a simple wrapper around a byte slice. 25 type Buffer struct{ B []byte } 26 27 // WriteByte will append given byte to buffer, fulfilling io.ByteWriter. 28 func (buf *Buffer) WriteByte(c byte) error { 29 buf.B = append(buf.B, c) 30 return nil 31 } 32 33 // WriteRune will append given rune to buffer. 34 func (buf *Buffer) WriteRune(r rune) (int, error) { 35 // Check for single-byte rune 36 if r < utf8.RuneSelf { 37 buf.B = append(buf.B, byte(r)) 38 return 1, nil 39 } 40 41 // Before-len 42 l := len(buf.B) 43 44 // Grow to max size rune 45 buf.Grow(utf8.UTFMax) 46 47 // Write encoded rune to buffer 48 n := utf8.EncodeRune(buf.B[l:len(buf.B)], r) 49 buf.B = buf.B[:l+n] 50 51 return n, nil 52 } 53 54 // Write will append given byte slice to buffer, fulfilling io.Writer. 55 func (buf *Buffer) Write(b []byte) (int, error) { 56 buf.B = append(buf.B, b...) 57 return len(b), nil 58 } 59 60 // WriteString will append given string to buffer, fulfilling io.StringWriter. 61 func (buf *Buffer) WriteString(s string) (int, error) { 62 buf.B = append(buf.B, s...) 63 return len(s), nil 64 } 65 66 // WriteAt will append given byte slice to buffer at index 'start', fulfilling io.WriterAt. 67 func (buf *Buffer) WriteAt(b []byte, start int64) (int, error) { 68 if start > int64(len(buf.B)) { 69 return 0, ErrBeyondBufferLen 70 } 71 buf.Grow(len(b) - int(int64(len(buf.B))-start)) 72 return copy(buf.B[start:], b), nil 73 } 74 75 // WriteStringAt will append given string to buffer at index 'start'. 76 func (buf *Buffer) WriteStringAt(s string, start int64) (int, error) { 77 if start > int64(len(buf.B)) { 78 return 0, ErrBeyondBufferLen 79 } 80 buf.Grow(len(s) - int(int64(len(buf.B))-start)) 81 return copy(buf.B[start:], s), nil 82 } 83 84 // Len returns the length of the buffer's underlying byte slice. 85 func (buf *Buffer) Len() int { 86 return len(buf.B) 87 } 88 89 // Cap returns the capacity of the buffer's underlying byte slice. 90 func (buf *Buffer) Cap() int { 91 return cap(buf.B) 92 } 93 94 // Grow will increase the buffers length by 'sz', and the capacity by at least this. 95 func (buf *Buffer) Grow(sz int) { 96 buf.Guarantee(sz) 97 buf.B = buf.B[:len(buf.B)+sz] 98 } 99 100 // Guarantee will guarantee buffer containers at least 'sz' remaining capacity. 101 func (buf *Buffer) Guarantee(sz int) { 102 if sz > cap(buf.B)-len(buf.B) { 103 nb := make([]byte, 2*cap(buf.B)+sz) 104 copy(nb, buf.B) 105 buf.B = nb[:len(buf.B)] 106 } 107 } 108 109 // Truncate will reduce the length of the buffer by 'n'. 110 func (buf *Buffer) Truncate(n int) { 111 if n > len(buf.B) { 112 n = len(buf.B) 113 } 114 buf.B = buf.B[:len(buf.B)-n] 115 } 116 117 // Reset will reset the buffer length to 0 (retains capacity). 118 func (buf *Buffer) Reset() { 119 buf.B = buf.B[:0] 120 } 121 122 // String returns the underlying byte slice as a string. Please note 123 // this value is tied directly to the underlying byte slice, if you 124 // write to the buffer then returned string values will also change. 125 // 126 // To get an immutable string from buffered data, use string(buf.B). 127 func (buf *Buffer) String() string { 128 return B2S(buf.B) 129 } 130 131 // Full returns the full capacity byteslice allocated for this buffer. 132 func (buf *Buffer) Full() []byte { 133 return buf.B[0:cap(buf.B)] 134 }