gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }