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  }