github.com/bir3/gocompiler@v0.9.2202/src/internal/zstd/window.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package zstd 6 7 // window stores up to size bytes of data. 8 // It is implemented as a circular buffer: 9 // sequential save calls append to the data slice until 10 // its length reaches configured size and after that, 11 // save calls overwrite previously saved data at off 12 // and update off such that it always points at 13 // the byte stored before others. 14 type window struct { 15 size int 16 data []byte 17 off int 18 } 19 20 // reset clears stored data and configures window size. 21 func (w *window) reset(size int) { 22 w.data = w.data[:0] 23 w.off = 0 24 w.size = size 25 } 26 27 // len returns the number of stored bytes. 28 func (w *window) len() uint32 { 29 return uint32(len(w.data)) 30 } 31 32 // save stores up to size last bytes from the buf. 33 func (w *window) save(buf []byte) { 34 if w.size == 0 { 35 return 36 } 37 if len(buf) == 0 { 38 return 39 } 40 41 if len(buf) >= w.size { 42 from := len(buf) - w.size 43 w.data = append(w.data[:0], buf[from:]...) 44 w.off = 0 45 return 46 } 47 48 // Update off to point to the oldest remaining byte. 49 free := w.size - len(w.data) 50 if free == 0 { 51 n := copy(w.data[w.off:], buf) 52 if n == len(buf) { 53 w.off += n 54 } else { 55 w.off = copy(w.data, buf[n:]) 56 } 57 } else { 58 if free >= len(buf) { 59 w.data = append(w.data, buf...) 60 } else { 61 w.data = append(w.data, buf[:free]...) 62 w.off = copy(w.data, buf[free:]) 63 } 64 } 65 } 66 67 // appendTo appends stored bytes between from and to indices to the buf. 68 // Index from must be less or equal to index to and to must be less or equal to w.len(). 69 func (w *window) appendTo(buf []byte, from, to uint32) []byte { 70 dataLen := uint32(len(w.data)) 71 from += uint32(w.off) 72 to += uint32(w.off) 73 74 wrap := false 75 if from > dataLen { 76 from -= dataLen 77 wrap = !wrap 78 } 79 if to > dataLen { 80 to -= dataLen 81 wrap = !wrap 82 } 83 84 if wrap { 85 buf = append(buf, w.data[from:]...) 86 return append(buf, w.data[:to]...) 87 } else { 88 return append(buf, w.data[from:to]...) 89 } 90 }