1// Copyright 2014-2017 Ulrich Kunitz. 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
5package lzma
6
7import (
8	"errors"
9	"fmt"
10)
11
12// decoderDict provides the dictionary for the decoder. The whole
13// dictionary is used as reader buffer.
14type decoderDict struct {
15	buf  buffer
16	head int64
17}
18
19// newDecoderDict creates a new decoder dictionary. The whole dictionary
20// will be used as reader buffer.
21func newDecoderDict(dictCap int) (d *decoderDict, err error) {
22	// lower limit supports easy test cases
23	if !(1 <= dictCap && int64(dictCap) <= MaxDictCap) {
24		return nil, errors.New("lzma: dictCap out of range")
25	}
26	d = &decoderDict{buf: *newBuffer(dictCap)}
27	return d, nil
28}
29
30// Reset clears the dictionary. The read buffer is not changed, so the
31// buffered data can still be read.
32func (d *decoderDict) Reset() {
33	d.head = 0
34}
35
36// WriteByte writes a single byte into the dictionary. It is used to
37// write literals into the dictionary.
38func (d *decoderDict) WriteByte(c byte) error {
39	if err := d.buf.WriteByte(c); err != nil {
40		return err
41	}
42	d.head++
43	return nil
44}
45
46// pos returns the position of the dictionary head.
47func (d *decoderDict) pos() int64 { return d.head }
48
49// dictLen returns the actual length of the dictionary.
50func (d *decoderDict) dictLen() int {
51	capacity := d.buf.Cap()
52	if d.head >= int64(capacity) {
53		return capacity
54	}
55	return int(d.head)
56}
57
58// byteAt returns a byte stored in the dictionary. If the distance is
59// non-positive or exceeds the current length of the dictionary the zero
60// byte is returned.
61func (d *decoderDict) byteAt(dist int) byte {
62	if !(0 < dist && dist <= d.dictLen()) {
63		return 0
64	}
65	i := d.buf.front - dist
66	if i < 0 {
67		i += len(d.buf.data)
68	}
69	return d.buf.data[i]
70}
71
72// writeMatch writes the match at the top of the dictionary. The given
73// distance must point in the current dictionary and the length must not
74// exceed the maximum length 273 supported in LZMA.
75//
76// The error value ErrNoSpace indicates that no space is available in
77// the dictionary for writing. You need to read from the dictionary
78// first.
79func (d *decoderDict) writeMatch(dist int64, length int) error {
80	if !(0 < dist && dist <= int64(d.dictLen())) {
81		return errors.New("writeMatch: distance out of range")
82	}
83	if !(0 < length && length <= maxMatchLen) {
84		return errors.New("writeMatch: length out of range")
85	}
86	if length > d.buf.Available() {
87		return ErrNoSpace
88	}
89	d.head += int64(length)
90
91	i := d.buf.front - int(dist)
92	if i < 0 {
93		i += len(d.buf.data)
94	}
95	for length > 0 {
96		var p []byte
97		if i >= d.buf.front {
98			p = d.buf.data[i:]
99			i = 0
100		} else {
101			p = d.buf.data[i:d.buf.front]
102			i = d.buf.front
103		}
104		if len(p) > length {
105			p = p[:length]
106		}
107		if _, err := d.buf.Write(p); err != nil {
108			panic(fmt.Errorf("d.buf.Write returned error %s", err))
109		}
110		length -= len(p)
111	}
112	return nil
113}
114
115// Write writes the given bytes into the dictionary and advances the
116// head.
117func (d *decoderDict) Write(p []byte) (n int, err error) {
118	n, err = d.buf.Write(p)
119	d.head += int64(n)
120	return n, err
121}
122
123// Available returns the number of available bytes for writing into the
124// decoder dictionary.
125func (d *decoderDict) Available() int { return d.buf.Available() }
126
127// Read reads data from the buffer contained in the decoder dictionary.
128func (d *decoderDict) Read(p []byte) (n int, err error) { return d.buf.Read(p) }
129
130// Buffered returns the number of bytes currently buffered in the
131// decoder dictionary.
132func (d *decoderDict) buffered() int { return d.buf.Buffered() }
133
134// Peek gets data from the buffer without advancing the rear index.
135func (d *decoderDict) peek(p []byte) (n int, err error) { return d.buf.Peek(p) }
136