encoderdict.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2014-2022 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. package lzma
  5. import (
  6. "errors"
  7. "fmt"
  8. "io"
  9. )
  10. // matcher is an interface that supports the identification of the next
  11. // operation.
  12. type matcher interface {
  13. io.Writer
  14. SetDict(d *encoderDict)
  15. NextOp(rep [4]uint32) operation
  16. }
  17. // encoderDict provides the dictionary of the encoder. It includes an
  18. // additional buffer atop of the actual dictionary.
  19. type encoderDict struct {
  20. buf buffer
  21. m matcher
  22. head int64
  23. capacity int
  24. // preallocated array
  25. data [maxMatchLen]byte
  26. }
  27. // newEncoderDict creates the encoder dictionary. The argument bufSize
  28. // defines the size of the additional buffer.
  29. func newEncoderDict(dictCap, bufSize int, m matcher) (d *encoderDict, err error) {
  30. if !(1 <= dictCap && int64(dictCap) <= MaxDictCap) {
  31. return nil, errors.New(
  32. "lzma: dictionary capacity out of range")
  33. }
  34. if bufSize < 1 {
  35. return nil, errors.New(
  36. "lzma: buffer size must be larger than zero")
  37. }
  38. d = &encoderDict{
  39. buf: *newBuffer(dictCap + bufSize),
  40. capacity: dictCap,
  41. m: m,
  42. }
  43. m.SetDict(d)
  44. return d, nil
  45. }
  46. // Discard discards n bytes. Note that n must not be larger than
  47. // MaxMatchLen.
  48. func (d *encoderDict) Discard(n int) {
  49. p := d.data[:n]
  50. k, _ := d.buf.Read(p)
  51. if k < n {
  52. panic(fmt.Errorf("lzma: can't discard %d bytes", n))
  53. }
  54. d.head += int64(n)
  55. d.m.Write(p)
  56. }
  57. // Len returns the data available in the encoder dictionary.
  58. func (d *encoderDict) Len() int {
  59. n := d.buf.Available()
  60. if int64(n) > d.head {
  61. return int(d.head)
  62. }
  63. return n
  64. }
  65. // DictLen returns the actual length of data in the dictionary.
  66. func (d *encoderDict) DictLen() int {
  67. if d.head < int64(d.capacity) {
  68. return int(d.head)
  69. }
  70. return d.capacity
  71. }
  72. // Available returns the number of bytes that can be written by a
  73. // following Write call.
  74. func (d *encoderDict) Available() int {
  75. return d.buf.Available() - d.DictLen()
  76. }
  77. // Write writes data into the dictionary buffer. Note that the position
  78. // of the dictionary head will not be moved. If there is not enough
  79. // space in the buffer ErrNoSpace will be returned.
  80. func (d *encoderDict) Write(p []byte) (n int, err error) {
  81. m := d.Available()
  82. if len(p) > m {
  83. p = p[:m]
  84. err = ErrNoSpace
  85. }
  86. var e error
  87. if n, e = d.buf.Write(p); e != nil {
  88. err = e
  89. }
  90. return n, err
  91. }
  92. // Pos returns the position of the head.
  93. func (d *encoderDict) Pos() int64 { return d.head }
  94. // ByteAt returns the byte at the given distance.
  95. func (d *encoderDict) ByteAt(distance int) byte {
  96. if !(0 < distance && distance <= d.Len()) {
  97. return 0
  98. }
  99. i := d.buf.rear - distance
  100. if i < 0 {
  101. i += len(d.buf.data)
  102. }
  103. return d.buf.data[i]
  104. }
  105. // CopyN copies the last n bytes from the dictionary into the provided
  106. // writer. This is used for copying uncompressed data into an
  107. // uncompressed segment.
  108. func (d *encoderDict) CopyN(w io.Writer, n int) (written int, err error) {
  109. if n <= 0 {
  110. return 0, nil
  111. }
  112. m := d.Len()
  113. if n > m {
  114. n = m
  115. err = ErrNoSpace
  116. }
  117. i := d.buf.rear - n
  118. var e error
  119. if i < 0 {
  120. i += len(d.buf.data)
  121. if written, e = w.Write(d.buf.data[i:]); e != nil {
  122. return written, e
  123. }
  124. i = 0
  125. }
  126. var k int
  127. k, e = w.Write(d.buf.data[i:d.buf.rear])
  128. written += k
  129. if e != nil {
  130. err = e
  131. }
  132. return written, err
  133. }
  134. // Buffered returns the number of bytes in the buffer.
  135. func (d *encoderDict) Buffered() int { return d.buf.Buffered() }