// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package zstd // window stores up to size bytes of data. // It is implemented as a circular buffer: // sequential save calls append to the data slice until // its length reaches configured size and after that, // save calls overwrite previously saved data at off // and update off such that it always points at // the byte stored before others. type window struct { size int data []byte off int } // reset clears stored data and configures window size. func (w *window) reset(size int) { b := w.data[:0] if cap(b) < size { b = make([]byte, 0, size) } w.data = b w.off = 0 w.size = size } // len returns the number of stored bytes. func (w *window) len() uint32 { return uint32(len(w.data)) } // save stores up to size last bytes from the buf. func (w *window) save(buf []byte) { if w.size == 0 { return } if len(buf) == 0 { return } if len(buf) >= w.size { from := len(buf) - w.size w.data = append(w.data[:0], buf[from:]...) w.off = 0 return } // Update off to point to the oldest remaining byte. free := w.size - len(w.data) if free == 0 { n := copy(w.data[w.off:], buf) if n == len(buf) { w.off += n } else { w.off = copy(w.data, buf[n:]) } } else { if free >= len(buf) { w.data = append(w.data, buf...) } else { w.data = append(w.data, buf[:free]...) w.off = copy(w.data, buf[free:]) } } } // appendTo appends stored bytes between from and to indices to the buf. // Index from must be less or equal to index to and to must be less or equal to w.len(). func (w *window) appendTo(buf []byte, from, to uint32) []byte { dataLen := uint32(len(w.data)) from += uint32(w.off) to += uint32(w.off) wrap := false if from > dataLen { from -= dataLen wrap = !wrap } if to > dataLen { to -= dataLen wrap = !wrap } if wrap { buf = append(buf, w.data[from:]...) return append(buf, w.data[:to]...) } else { return append(buf, w.data[from:to]...) } }