| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- // Copyright 2014-2022 Ulrich Kunitz. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package lzma
- import (
- "errors"
- "fmt"
- "io"
- )
- // matcher is an interface that supports the identification of the next
- // operation.
- type matcher interface {
- io.Writer
- SetDict(d *encoderDict)
- NextOp(rep [4]uint32) operation
- }
- // encoderDict provides the dictionary of the encoder. It includes an
- // additional buffer atop of the actual dictionary.
- type encoderDict struct {
- buf buffer
- m matcher
- head int64
- capacity int
- // preallocated array
- data [maxMatchLen]byte
- }
- // newEncoderDict creates the encoder dictionary. The argument bufSize
- // defines the size of the additional buffer.
- func newEncoderDict(dictCap, bufSize int, m matcher) (d *encoderDict, err error) {
- if !(1 <= dictCap && int64(dictCap) <= MaxDictCap) {
- return nil, errors.New(
- "lzma: dictionary capacity out of range")
- }
- if bufSize < 1 {
- return nil, errors.New(
- "lzma: buffer size must be larger than zero")
- }
- d = &encoderDict{
- buf: *newBuffer(dictCap + bufSize),
- capacity: dictCap,
- m: m,
- }
- m.SetDict(d)
- return d, nil
- }
- // Discard discards n bytes. Note that n must not be larger than
- // MaxMatchLen.
- func (d *encoderDict) Discard(n int) {
- p := d.data[:n]
- k, _ := d.buf.Read(p)
- if k < n {
- panic(fmt.Errorf("lzma: can't discard %d bytes", n))
- }
- d.head += int64(n)
- d.m.Write(p)
- }
- // Len returns the data available in the encoder dictionary.
- func (d *encoderDict) Len() int {
- n := d.buf.Available()
- if int64(n) > d.head {
- return int(d.head)
- }
- return n
- }
- // DictLen returns the actual length of data in the dictionary.
- func (d *encoderDict) DictLen() int {
- if d.head < int64(d.capacity) {
- return int(d.head)
- }
- return d.capacity
- }
- // Available returns the number of bytes that can be written by a
- // following Write call.
- func (d *encoderDict) Available() int {
- return d.buf.Available() - d.DictLen()
- }
- // Write writes data into the dictionary buffer. Note that the position
- // of the dictionary head will not be moved. If there is not enough
- // space in the buffer ErrNoSpace will be returned.
- func (d *encoderDict) Write(p []byte) (n int, err error) {
- m := d.Available()
- if len(p) > m {
- p = p[:m]
- err = ErrNoSpace
- }
- var e error
- if n, e = d.buf.Write(p); e != nil {
- err = e
- }
- return n, err
- }
- // Pos returns the position of the head.
- func (d *encoderDict) Pos() int64 { return d.head }
- // ByteAt returns the byte at the given distance.
- func (d *encoderDict) ByteAt(distance int) byte {
- if !(0 < distance && distance <= d.Len()) {
- return 0
- }
- i := d.buf.rear - distance
- if i < 0 {
- i += len(d.buf.data)
- }
- return d.buf.data[i]
- }
- // CopyN copies the last n bytes from the dictionary into the provided
- // writer. This is used for copying uncompressed data into an
- // uncompressed segment.
- func (d *encoderDict) CopyN(w io.Writer, n int) (written int, err error) {
- if n <= 0 {
- return 0, nil
- }
- m := d.Len()
- if n > m {
- n = m
- err = ErrNoSpace
- }
- i := d.buf.rear - n
- var e error
- if i < 0 {
- i += len(d.buf.data)
- if written, e = w.Write(d.buf.data[i:]); e != nil {
- return written, e
- }
- i = 0
- }
- var k int
- k, e = w.Write(d.buf.data[i:d.buf.rear])
- written += k
- if e != nil {
- err = e
- }
- return written, err
- }
- // Buffered returns the number of bytes in the buffer.
- func (d *encoderDict) Buffered() int { return d.buf.Buffered() }
|