github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/ringbuffer/ring_buffer.go (about)

     1  package ringbuffer
     2  
     3  import (
     4  	"errors"
     5  	"unsafe"
     6  
     7  	"github.com/angenalZZZ/gofunc/net/internal"
     8  	"github.com/angenalZZZ/gofunc/net/pool/bytebuffer"
     9  )
    10  
    11  const initSize = 1 << 12 // 4096 bytes for the first-time allocation on ring-buffer.
    12  
    13  // ErrIsEmpty will be returned when trying to read a empty ring-buffer.
    14  var ErrIsEmpty = errors.New("ring-buffer is empty")
    15  
    16  // RingBuffer is a circular buffer that implement io.ReaderWriter interface.
    17  type RingBuffer struct {
    18  	buf     []byte
    19  	size    int
    20  	mask    int
    21  	r       int // next position to read
    22  	w       int // next position to write
    23  	isEmpty bool
    24  }
    25  
    26  // New returns a new RingBuffer whose buffer has the given size.
    27  func New(size int) *RingBuffer {
    28  	if size == 0 {
    29  		return &RingBuffer{isEmpty: true}
    30  	}
    31  	size = internal.CeilToPowerOfTwo(size)
    32  	return &RingBuffer{
    33  		buf:     make([]byte, size),
    34  		size:    size,
    35  		mask:    size - 1,
    36  		isEmpty: true,
    37  	}
    38  }
    39  
    40  // LazyRead reads the bytes with given length but will not move the pointer of "read".
    41  func (r *RingBuffer) LazyRead(len int) (head []byte, tail []byte) {
    42  	if r.isEmpty {
    43  		return
    44  	}
    45  
    46  	if len <= 0 {
    47  		return
    48  	}
    49  
    50  	if r.w > r.r {
    51  		n := r.w - r.r // Length
    52  		if n > len {
    53  			n = len
    54  		}
    55  		head = r.buf[r.r : r.r+n]
    56  		return
    57  	}
    58  
    59  	n := r.size - r.r + r.w // Length
    60  	if n > len {
    61  		n = len
    62  	}
    63  
    64  	if r.r+n <= r.size {
    65  		head = r.buf[r.r : r.r+n]
    66  	} else {
    67  		c1 := r.size - r.r
    68  		head = r.buf[r.r:]
    69  		c2 := n - c1
    70  		tail = r.buf[:c2]
    71  	}
    72  
    73  	return
    74  }
    75  
    76  // LazyReadAll reads the all bytes in this ring-buffer but will not move the pointer of "read".
    77  func (r *RingBuffer) LazyReadAll() (head []byte, tail []byte) {
    78  	if r.isEmpty {
    79  		return
    80  	}
    81  
    82  	if r.w > r.r {
    83  		head = r.buf[r.r:r.w]
    84  		return
    85  	}
    86  
    87  	head = r.buf[r.r:]
    88  	if r.w != 0 {
    89  		tail = r.buf[:r.w]
    90  	}
    91  
    92  	return
    93  }
    94  
    95  // Shift shifts the "read" pointer.
    96  func (r *RingBuffer) Shift(n int) {
    97  	if n <= 0 {
    98  		return
    99  	}
   100  
   101  	if n < r.Length() {
   102  		r.r = (r.r + n) & r.mask
   103  		if r.r == r.w {
   104  			r.isEmpty = true
   105  		}
   106  	} else {
   107  		r.Reset()
   108  	}
   109  }
   110  
   111  // Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error
   112  // encountered.
   113  // Even if Read returns n < len(p), it may use all of p as scratch space during the call.
   114  // If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting
   115  // for more.
   116  // When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes,
   117  // it returns the number of bytes read. It may return the (non-nil) error from the same call or return the
   118  // error (and n == 0) from a subsequent call.
   119  // Callers should always process the n > 0 bytes returned before considering the error err.
   120  // Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF
   121  // behaviors.
   122  func (r *RingBuffer) Read(p []byte) (n int, err error) {
   123  	if len(p) == 0 {
   124  		return 0, nil
   125  	}
   126  
   127  	if r.isEmpty {
   128  		return 0, ErrIsEmpty
   129  	}
   130  
   131  	if r.w > r.r {
   132  		n = r.w - r.r
   133  		if n > len(p) {
   134  			n = len(p)
   135  		}
   136  		copy(p, r.buf[r.r:r.r+n])
   137  		r.r = r.r + n
   138  		if r.r == r.w {
   139  			r.isEmpty = true
   140  		}
   141  		return
   142  	}
   143  
   144  	n = r.size - r.r + r.w
   145  	if n > len(p) {
   146  		n = len(p)
   147  	}
   148  
   149  	if r.r+n <= r.size {
   150  		copy(p, r.buf[r.r:r.r+n])
   151  	} else {
   152  		c1 := r.size - r.r
   153  		copy(p, r.buf[r.r:])
   154  		c2 := n - c1
   155  		copy(p[c1:], r.buf[:c2])
   156  	}
   157  	r.r = (r.r + n) & r.mask
   158  	if r.r == r.w {
   159  		r.isEmpty = true
   160  	}
   161  
   162  	return n, err
   163  }
   164  
   165  // ReadByte reads and returns the next byte from the input or ErrIsEmpty.
   166  func (r *RingBuffer) ReadByte() (b byte, err error) {
   167  	if r.isEmpty {
   168  		return 0, ErrIsEmpty
   169  	}
   170  	b = r.buf[r.r]
   171  	r.r++
   172  	if r.r == r.size {
   173  		r.r = 0
   174  	}
   175  	if r.r == r.w {
   176  		r.isEmpty = true
   177  	}
   178  
   179  	return b, err
   180  }
   181  
   182  // Write writes len(p) bytes from p to the underlying buf.
   183  // It returns the number of bytes written from p (n == len(p) > 0) and any error encountered that caused the write to
   184  // stop early.
   185  // If the length of p is greater than the writable capacity of this ring-buffer, it will allocate more memory to
   186  // this ring-buffer.
   187  // Write must not modify the slice data, even temporarily.
   188  func (r *RingBuffer) Write(p []byte) (n int, err error) {
   189  	n = len(p)
   190  	if n == 0 {
   191  		return 0, nil
   192  	}
   193  
   194  	free := r.Free()
   195  	if n > free {
   196  		r.malloc(n - free)
   197  	}
   198  
   199  	if r.w >= r.r {
   200  		c1 := r.size - r.w
   201  		if c1 >= n {
   202  			copy(r.buf[r.w:], p)
   203  			r.w += n
   204  		} else {
   205  			copy(r.buf[r.w:], p[:c1])
   206  			c2 := n - c1
   207  			copy(r.buf, p[c1:])
   208  			r.w = c2
   209  		}
   210  	} else {
   211  		copy(r.buf[r.w:], p)
   212  		r.w += n
   213  	}
   214  
   215  	if r.w == r.size {
   216  		r.w = 0
   217  	}
   218  
   219  	r.isEmpty = false
   220  
   221  	return n, err
   222  }
   223  
   224  // WriteByte writes one byte into buffer
   225  func (r *RingBuffer) WriteByte(c byte) error {
   226  	if r.Free() < 1 {
   227  		r.malloc(1)
   228  	}
   229  	r.buf[r.w] = c
   230  	r.w++
   231  
   232  	if r.w == r.size {
   233  		r.w = 0
   234  	}
   235  	r.isEmpty = false
   236  
   237  	return nil
   238  }
   239  
   240  // Length returns the length of available read bytes.
   241  func (r *RingBuffer) Length() int {
   242  	if r.r == r.w {
   243  		if r.isEmpty {
   244  			return 0
   245  		}
   246  		return r.size
   247  	}
   248  
   249  	if r.w > r.r {
   250  		return r.w - r.r
   251  	}
   252  
   253  	return r.size - r.r + r.w
   254  }
   255  
   256  // Len returns the length of the underlying buffer.
   257  func (r *RingBuffer) Len() int {
   258  	return len(r.buf)
   259  }
   260  
   261  // Cap returns the size of the underlying buffer.
   262  func (r *RingBuffer) Cap() int {
   263  	return r.size
   264  }
   265  
   266  // Free returns the length of available bytes to write.
   267  func (r *RingBuffer) Free() int {
   268  	if r.r == r.w {
   269  		if r.isEmpty {
   270  			return r.size
   271  		}
   272  		return 0
   273  	}
   274  
   275  	if r.w < r.r {
   276  		return r.r - r.w
   277  	}
   278  
   279  	return r.size - r.w + r.r
   280  }
   281  
   282  // WriteString writes the contents of the string s to buffer, which accepts a slice of bytes.
   283  func (r *RingBuffer) WriteString(s string) (n int, err error) {
   284  	x := (*[2]uintptr)(unsafe.Pointer(&s))
   285  	h := [3]uintptr{x[0], x[1], x[1]}
   286  	buf := *(*[]byte)(unsafe.Pointer(&h))
   287  	return r.Write(buf)
   288  }
   289  
   290  // ByteBuffer returns all available read bytes. It does not move the read pointer and only copy the available data.
   291  func (r *RingBuffer) ByteBuffer() *bytebuffer.ByteBuffer {
   292  	if r.isEmpty {
   293  		return nil
   294  	} else if r.w == r.r {
   295  		bb := bytebuffer.Get()
   296  		_, _ = bb.Write(r.buf[r.r:])
   297  		_, _ = bb.Write(r.buf[:r.w])
   298  		return bb
   299  	}
   300  
   301  	bb := bytebuffer.Get()
   302  	if r.w > r.r {
   303  		_, _ = bb.Write(r.buf[r.r:r.w])
   304  		return bb
   305  	}
   306  
   307  	_, _ = bb.Write(r.buf[r.r:])
   308  
   309  	if r.w != 0 {
   310  		_, _ = bb.Write(r.buf[:r.w])
   311  	}
   312  
   313  	return bb
   314  }
   315  
   316  // WithByteBuffer combines the available read bytes and the given bytes. It does not move the read pointer and
   317  // only copy the available data.
   318  func (r *RingBuffer) WithByteBuffer(b []byte) *bytebuffer.ByteBuffer {
   319  	if r.isEmpty {
   320  		return &bytebuffer.ByteBuffer{B: b}
   321  	} else if r.w == r.r {
   322  		bb := bytebuffer.Get()
   323  		_, _ = bb.Write(r.buf[r.r:])
   324  		_, _ = bb.Write(r.buf[:r.w])
   325  		_, _ = bb.Write(b)
   326  		return bb
   327  	}
   328  
   329  	bb := bytebuffer.Get()
   330  	if r.w > r.r {
   331  		_, _ = bb.Write(r.buf[r.r:r.w])
   332  		_, _ = bb.Write(b)
   333  		return bb
   334  	}
   335  
   336  	_, _ = bb.Write(r.buf[r.r:])
   337  
   338  	if r.w != 0 {
   339  		_, _ = bb.Write(r.buf[:r.w])
   340  	}
   341  	_, _ = bb.Write(b)
   342  
   343  	return bb
   344  }
   345  
   346  // IsFull returns this ringbuffer is full.
   347  func (r *RingBuffer) IsFull() bool {
   348  	return r.r == r.w && !r.isEmpty
   349  }
   350  
   351  // IsEmpty returns this ringbuffer is empty.
   352  func (r *RingBuffer) IsEmpty() bool {
   353  	return r.isEmpty
   354  }
   355  
   356  // Reset the read pointer and writer pointer to zero.
   357  func (r *RingBuffer) Reset() {
   358  	r.r = 0
   359  	r.w = 0
   360  	r.isEmpty = true
   361  }
   362  
   363  func (r *RingBuffer) malloc(cap int) {
   364  	var newCap int
   365  	if r.size == 0 && initSize >= cap {
   366  		newCap = initSize
   367  	} else {
   368  		newCap = internal.CeilToPowerOfTwo(r.size + cap)
   369  	}
   370  	newBuf := make([]byte, newCap)
   371  	oldLen := r.Length()
   372  	_, _ = r.Read(newBuf)
   373  	r.r = 0
   374  	r.w = oldLen
   375  	r.size = newCap
   376  	r.mask = newCap - 1
   377  	r.buf = newBuf
   378  }