github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/common/buf/buffer.go (about)

     1  package buf
     2  
     3  import (
     4  	"io"
     5  
     6  	"v2ray.com/core/common/bytespool"
     7  )
     8  
     9  const (
    10  	// Size of a regular buffer.
    11  	Size = 2048
    12  )
    13  
    14  // Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
    15  // the buffer into an internal buffer pool, in order to recreate a buffer more
    16  // quickly.
    17  type Buffer struct {
    18  	v     []byte
    19  	start int32
    20  	end   int32
    21  }
    22  
    23  // Release recycles the buffer into an internal buffer pool.
    24  func (b *Buffer) Release() {
    25  	if b == nil || b.v == nil {
    26  		return
    27  	}
    28  
    29  	p := b.v
    30  	b.v = nil
    31  	b.Clear()
    32  	pool.Put(p)
    33  }
    34  
    35  // Clear clears the content of the buffer, results an empty buffer with
    36  // Len() = 0.
    37  func (b *Buffer) Clear() {
    38  	b.start = 0
    39  	b.end = 0
    40  }
    41  
    42  // Byte returns the bytes at index.
    43  func (b *Buffer) Byte(index int32) byte {
    44  	return b.v[b.start+index]
    45  }
    46  
    47  // SetByte sets the byte value at index.
    48  func (b *Buffer) SetByte(index int32, value byte) {
    49  	b.v[b.start+index] = value
    50  }
    51  
    52  // Bytes returns the content bytes of this Buffer.
    53  func (b *Buffer) Bytes() []byte {
    54  	return b.v[b.start:b.end]
    55  }
    56  
    57  // Extend increases the buffer size by n bytes, and returns the extended part.
    58  // It panics if result size is larger than buf.Size.
    59  func (b *Buffer) Extend(n int32) []byte {
    60  	end := b.end + n
    61  	if end > int32(len(b.v)) {
    62  		panic("extending out of bound")
    63  	}
    64  	ext := b.v[b.end:end]
    65  	b.end = end
    66  	return ext
    67  }
    68  
    69  // BytesRange returns a slice of this buffer with given from and to boundary.
    70  func (b *Buffer) BytesRange(from, to int32) []byte {
    71  	if from < 0 {
    72  		from += b.Len()
    73  	}
    74  	if to < 0 {
    75  		to += b.Len()
    76  	}
    77  	return b.v[b.start+from : b.start+to]
    78  }
    79  
    80  // BytesFrom returns a slice of this Buffer starting from the given position.
    81  func (b *Buffer) BytesFrom(from int32) []byte {
    82  	if from < 0 {
    83  		from += b.Len()
    84  	}
    85  	return b.v[b.start+from : b.end]
    86  }
    87  
    88  // BytesTo returns a slice of this Buffer from start to the given position.
    89  func (b *Buffer) BytesTo(to int32) []byte {
    90  	if to < 0 {
    91  		to += b.Len()
    92  	}
    93  	return b.v[b.start : b.start+to]
    94  }
    95  
    96  // Resize cuts the buffer at the given position.
    97  func (b *Buffer) Resize(from, to int32) {
    98  	if from < 0 {
    99  		from += b.Len()
   100  	}
   101  	if to < 0 {
   102  		to += b.Len()
   103  	}
   104  	if to < from {
   105  		panic("Invalid slice")
   106  	}
   107  	b.end = b.start + to
   108  	b.start += from
   109  }
   110  
   111  // Advance cuts the buffer at the given position.
   112  func (b *Buffer) Advance(from int32) {
   113  	if from < 0 {
   114  		from += b.Len()
   115  	}
   116  	b.start += from
   117  }
   118  
   119  // Len returns the length of the buffer content.
   120  func (b *Buffer) Len() int32 {
   121  	if b == nil {
   122  		return 0
   123  	}
   124  	return b.end - b.start
   125  }
   126  
   127  // IsEmpty returns true if the buffer is empty.
   128  func (b *Buffer) IsEmpty() bool {
   129  	return b.Len() == 0
   130  }
   131  
   132  // IsFull returns true if the buffer has no more room to grow.
   133  func (b *Buffer) IsFull() bool {
   134  	return b != nil && b.end == int32(len(b.v))
   135  }
   136  
   137  // Write implements Write method in io.Writer.
   138  func (b *Buffer) Write(data []byte) (int, error) {
   139  	nBytes := copy(b.v[b.end:], data)
   140  	b.end += int32(nBytes)
   141  	return nBytes, nil
   142  }
   143  
   144  // WriteByte writes a single byte into the buffer.
   145  func (b *Buffer) WriteByte(v byte) error {
   146  	if b.IsFull() {
   147  		return newError("buffer full")
   148  	}
   149  	b.v[b.end] = v
   150  	b.end++
   151  	return nil
   152  }
   153  
   154  // WriteString implements io.StringWriter.
   155  func (b *Buffer) WriteString(s string) (int, error) {
   156  	return b.Write([]byte(s))
   157  }
   158  
   159  // Read implements io.Reader.Read().
   160  func (b *Buffer) Read(data []byte) (int, error) {
   161  	if b.Len() == 0 {
   162  		return 0, io.EOF
   163  	}
   164  	nBytes := copy(data, b.v[b.start:b.end])
   165  	if int32(nBytes) == b.Len() {
   166  		b.Clear()
   167  	} else {
   168  		b.start += int32(nBytes)
   169  	}
   170  	return nBytes, nil
   171  }
   172  
   173  // ReadFrom implements io.ReaderFrom.
   174  func (b *Buffer) ReadFrom(reader io.Reader) (int64, error) {
   175  	n, err := reader.Read(b.v[b.end:])
   176  	b.end += int32(n)
   177  	return int64(n), err
   178  }
   179  
   180  // ReadFullFrom reads exact size of bytes from given reader, or until error occurs.
   181  func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, error) {
   182  	end := b.end + size
   183  	if end > int32(len(b.v)) {
   184  		v := end
   185  		return 0, newError("out of bound: ", v)
   186  	}
   187  	n, err := io.ReadFull(reader, b.v[b.end:end])
   188  	b.end += int32(n)
   189  	return int64(n), err
   190  }
   191  
   192  // String returns the string form of this Buffer.
   193  func (b *Buffer) String() string {
   194  	return string(b.Bytes())
   195  }
   196  
   197  var pool = bytespool.GetPool(Size)
   198  
   199  // New creates a Buffer with 0 length and 2K capacity.
   200  func New() *Buffer {
   201  	return &Buffer{
   202  		v: pool.Get().([]byte),
   203  	}
   204  }
   205  
   206  // StackNew creates a new Buffer object on stack.
   207  // This method is for buffers that is released in the same function.
   208  func StackNew() Buffer {
   209  	return Buffer{
   210  		v: pool.Get().([]byte),
   211  	}
   212  }