github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/ds/ring.go (about)

     1  package ds
     2  
     3  import (
     4  	"github.com/15mga/kiwi/util"
     5  )
     6  
     7  type (
     8  	ringOption[T any] struct {
     9  		maxCap      int
    10  		minCap      int
    11  		shrinkCount int
    12  		slow        int
    13  		resize      func(int)
    14  	}
    15  	RingOption[T any] func(o *ringOption[T])
    16  )
    17  
    18  func RingMaxCap[T any](c int) RingOption[T] {
    19  	return func(o *ringOption[T]) {
    20  		o.maxCap = c
    21  	}
    22  }
    23  
    24  func RingMinCap[T any](c int) RingOption[T] {
    25  	return func(o *ringOption[T]) {
    26  		o.minCap = c
    27  	}
    28  }
    29  
    30  func RingResize[T any](r func(int)) RingOption[T] {
    31  	return func(o *ringOption[T]) {
    32  		o.resize = r
    33  	}
    34  }
    35  
    36  func RingSlow[T any](r func(int)) RingOption[T] {
    37  	return func(o *ringOption[T]) {
    38  		o.resize = r
    39  	}
    40  }
    41  
    42  func NewRing[T any](opts ...RingOption[T]) *Ring[T] {
    43  	opt := &ringOption[T]{
    44  		maxCap:      0,
    45  		minCap:      32,
    46  		shrinkCount: 64,
    47  		slow:        1024,
    48  	}
    49  	for _, o := range opts {
    50  		o(opt)
    51  	}
    52  	r := &Ring[T]{
    53  		opt:         opt,
    54  		buffer:      make([]T, opt.minCap),
    55  		bufferCap:   opt.minCap,
    56  		halfBuffCap: opt.minCap >> 1,
    57  		shrink:      opt.shrinkCount,
    58  	}
    59  	r.defVal = r.buffer[0]
    60  	return r
    61  }
    62  
    63  type Ring[T any] struct {
    64  	opt         *ringOption[T]
    65  	defVal      T
    66  	available   int
    67  	readIdx     int
    68  	writeIdx    int
    69  	buffer      []T
    70  	bufferCap   int
    71  	halfBuffCap int
    72  	shrink      int
    73  }
    74  
    75  func (r *Ring[T]) Available() int {
    76  	return r.available
    77  }
    78  
    79  func (r *Ring[T]) testCap(c int) *util.Err {
    80  	if c > r.bufferCap {
    81  		c, ok := util.NextCap(c, r.bufferCap, r.opt.slow)
    82  		if ok {
    83  			if r.opt.maxCap > 0 && c >= r.opt.maxCap {
    84  				return util.NewErr(util.EcTooLong, util.M{
    85  					"total": c,
    86  				})
    87  			}
    88  			r.resetBuffer(c)
    89  		}
    90  		return nil
    91  	}
    92  	if r.opt.minCap == r.bufferCap {
    93  		return nil
    94  	}
    95  	if c > r.halfBuffCap {
    96  		r.shrink = r.opt.shrinkCount
    97  		return nil
    98  	}
    99  	r.shrink--
   100  	if r.shrink > 0 {
   101  		return nil
   102  	}
   103  	r.resetBuffer(r.halfBuffCap)
   104  	return nil
   105  }
   106  
   107  func (r *Ring[T]) resetBuffer(cap int) {
   108  	buf := make([]T, cap)
   109  	if r.available > 0 {
   110  		if r.writeIdx > r.readIdx {
   111  			copy(buf, r.buffer[r.readIdx:r.writeIdx])
   112  		} else {
   113  			n := copy(buf, r.buffer[r.readIdx:])
   114  			copy(buf[n:], r.buffer[:r.writeIdx])
   115  		}
   116  	}
   117  	r.writeIdx = r.available
   118  	r.readIdx = 0
   119  	r.bufferCap = cap
   120  	r.halfBuffCap = cap >> 1
   121  	r.buffer = buf
   122  	r.shrink = r.opt.shrinkCount
   123  	if r.opt.resize != nil {
   124  		r.opt.resize(cap)
   125  	}
   126  }
   127  
   128  func (r *Ring[T]) Put(items ...T) *util.Err {
   129  	l := len(items)
   130  	c := r.available + l
   131  	err := r.testCap(c)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	r.available = c
   136  	i := r.writeIdx + l
   137  	if i <= r.bufferCap {
   138  		copy(r.buffer[r.writeIdx:], items)
   139  		r.writeIdx = i
   140  	} else {
   141  		copy(r.buffer[r.writeIdx:r.bufferCap], items)
   142  		j := r.bufferCap - r.writeIdx
   143  		copy(r.buffer, items[j:l])
   144  		r.writeIdx = l - j
   145  	}
   146  	return nil
   147  }
   148  
   149  func (r *Ring[T]) Pop() (item T, err *util.Err) {
   150  	if r.available == 0 {
   151  		return util.Default[T](), util.NewErr(util.EcNotEnough, util.M{
   152  			"available": r.available,
   153  		})
   154  	}
   155  	item = r.buffer[r.readIdx]
   156  	r.readIdx++
   157  	if r.readIdx == r.bufferCap {
   158  		r.readIdx = 0
   159  	}
   160  	r.available--
   161  	return
   162  }
   163  
   164  func (r *Ring[T]) Read(s []T, l int) *util.Err {
   165  	sl := len(s)
   166  	if l > sl || l > r.available {
   167  		return util.NewErr(util.EcNotEnough, util.M{
   168  			"length":    l,
   169  			"slice":     sl,
   170  			"available": r.available,
   171  		})
   172  	}
   173  	r.read(s, l)
   174  	return nil
   175  }
   176  
   177  func (r *Ring[T]) read(s []T, l int) {
   178  	p := r.readIdx + l
   179  	if p < r.bufferCap {
   180  		copy(s, r.buffer[r.readIdx:p])
   181  		r.readIdx = p
   182  	} else {
   183  		p -= r.bufferCap
   184  		copy(s, r.buffer[r.readIdx:r.bufferCap])
   185  		copy(s[r.bufferCap-r.readIdx:], r.buffer[:p])
   186  		r.readIdx = p
   187  	}
   188  	r.available -= l
   189  }
   190  
   191  func (r *Ring[T]) ReadMax(s []T) int {
   192  	l := util.MaxInt(len(s), r.available)
   193  	r.read(s, l)
   194  	return l
   195  }
   196  
   197  func (r *Ring[T]) IterAll(fn func(T)) {
   198  	if r.readIdx < r.writeIdx {
   199  		for ; r.readIdx < r.writeIdx; r.readIdx++ {
   200  			fn(r.buffer[r.readIdx])
   201  		}
   202  		return
   203  	}
   204  	for ; r.readIdx < r.bufferCap; r.readIdx++ {
   205  		fn(r.buffer[r.readIdx])
   206  	}
   207  	for r.readIdx = 0; r.readIdx < r.writeIdx; r.readIdx++ {
   208  		fn(r.buffer[r.readIdx])
   209  	}
   210  }
   211  
   212  func (r *Ring[T]) Iter(fn func([]T)) {
   213  	if r.readIdx == r.writeIdx {
   214  		return
   215  	}
   216  	if r.readIdx < r.writeIdx {
   217  		fn(r.buffer[r.readIdx:r.writeIdx])
   218  		return
   219  	}
   220  	fn(r.buffer[r.readIdx:])
   221  	fn(r.buffer[:r.writeIdx])
   222  }
   223  
   224  func (r *Ring[T]) Reset() {
   225  	r.readIdx = 0
   226  	r.writeIdx = 0
   227  }