reader2.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. "io"
  8. "github.com/ulikunitz/xz/internal/xlog"
  9. )
  10. // Reader2Config stores the parameters for the LZMA2 reader.
  11. // format.
  12. type Reader2Config struct {
  13. DictCap int
  14. }
  15. // fill converts the zero values of the configuration to the default values.
  16. func (c *Reader2Config) fill() {
  17. if c.DictCap == 0 {
  18. c.DictCap = 8 * 1024 * 1024
  19. }
  20. }
  21. // Verify checks the reader configuration for errors. Zero configuration values
  22. // will be replaced by default values.
  23. func (c *Reader2Config) Verify() error {
  24. c.fill()
  25. if !(MinDictCap <= c.DictCap && int64(c.DictCap) <= MaxDictCap) {
  26. return errors.New("lzma: dictionary capacity is out of range")
  27. }
  28. return nil
  29. }
  30. // Reader2 supports the reading of LZMA2 chunk sequences. Note that the
  31. // first chunk should have a dictionary reset and the first compressed
  32. // chunk a properties reset. The chunk sequence may not be terminated by
  33. // an end-of-stream chunk.
  34. type Reader2 struct {
  35. r io.Reader
  36. err error
  37. dict *decoderDict
  38. ur *uncompressedReader
  39. decoder *decoder
  40. chunkReader io.Reader
  41. cstate chunkState
  42. }
  43. // NewReader2 creates a reader for an LZMA2 chunk sequence.
  44. func NewReader2(lzma2 io.Reader) (r *Reader2, err error) {
  45. return Reader2Config{}.NewReader2(lzma2)
  46. }
  47. // NewReader2 creates an LZMA2 reader using the given configuration.
  48. func (c Reader2Config) NewReader2(lzma2 io.Reader) (r *Reader2, err error) {
  49. if err = c.Verify(); err != nil {
  50. return nil, err
  51. }
  52. r = &Reader2{r: lzma2, cstate: start}
  53. r.dict, err = newDecoderDict(c.DictCap)
  54. if err != nil {
  55. return nil, err
  56. }
  57. if err = r.startChunk(); err != nil {
  58. r.err = err
  59. }
  60. return r, nil
  61. }
  62. // uncompressed tests whether the chunk type specifies an uncompressed
  63. // chunk.
  64. func uncompressed(ctype chunkType) bool {
  65. return ctype == cU || ctype == cUD
  66. }
  67. // startChunk parses a new chunk.
  68. func (r *Reader2) startChunk() error {
  69. r.chunkReader = nil
  70. header, err := readChunkHeader(r.r)
  71. if err != nil {
  72. if err == io.EOF {
  73. err = io.ErrUnexpectedEOF
  74. }
  75. return err
  76. }
  77. xlog.Debugf("chunk header %v", header)
  78. if err = r.cstate.next(header.ctype); err != nil {
  79. return err
  80. }
  81. if r.cstate == stop {
  82. return io.EOF
  83. }
  84. if header.ctype == cUD || header.ctype == cLRND {
  85. r.dict.Reset()
  86. }
  87. size := int64(header.uncompressed) + 1
  88. if uncompressed(header.ctype) {
  89. if r.ur != nil {
  90. r.ur.Reopen(r.r, size)
  91. } else {
  92. r.ur = newUncompressedReader(r.r, r.dict, size)
  93. }
  94. r.chunkReader = r.ur
  95. return nil
  96. }
  97. br := ByteReader(io.LimitReader(r.r, int64(header.compressed)+1))
  98. if r.decoder == nil {
  99. state := newState(header.props)
  100. r.decoder, err = newDecoder(br, state, r.dict, size)
  101. if err != nil {
  102. return err
  103. }
  104. r.chunkReader = r.decoder
  105. return nil
  106. }
  107. switch header.ctype {
  108. case cLR:
  109. r.decoder.State.Reset()
  110. case cLRN, cLRND:
  111. r.decoder.State = newState(header.props)
  112. }
  113. err = r.decoder.Reopen(br, size)
  114. if err != nil {
  115. return err
  116. }
  117. r.chunkReader = r.decoder
  118. return nil
  119. }
  120. // Read reads data from the LZMA2 chunk sequence.
  121. func (r *Reader2) Read(p []byte) (n int, err error) {
  122. if r.err != nil {
  123. return 0, r.err
  124. }
  125. for n < len(p) {
  126. var k int
  127. k, err = r.chunkReader.Read(p[n:])
  128. n += k
  129. if err != nil {
  130. if err == io.EOF {
  131. err = r.startChunk()
  132. if err == nil {
  133. continue
  134. }
  135. }
  136. r.err = err
  137. return n, err
  138. }
  139. if k == 0 {
  140. r.err = errors.New("lzma: Reader2 doesn't get data")
  141. return n, r.err
  142. }
  143. }
  144. return n, nil
  145. }
  146. // EOS returns whether the LZMA2 stream has been terminated by an
  147. // end-of-stream chunk.
  148. func (r *Reader2) EOS() bool {
  149. return r.cstate == stop
  150. }
  151. // uncompressedReader is used to read uncompressed chunks.
  152. type uncompressedReader struct {
  153. lr io.LimitedReader
  154. Dict *decoderDict
  155. eof bool
  156. err error
  157. }
  158. // newUncompressedReader initializes a new uncompressedReader.
  159. func newUncompressedReader(r io.Reader, dict *decoderDict, size int64) *uncompressedReader {
  160. ur := &uncompressedReader{
  161. lr: io.LimitedReader{R: r, N: size},
  162. Dict: dict,
  163. }
  164. return ur
  165. }
  166. // Reopen reinitializes an uncompressed reader.
  167. func (ur *uncompressedReader) Reopen(r io.Reader, size int64) {
  168. ur.err = nil
  169. ur.eof = false
  170. ur.lr = io.LimitedReader{R: r, N: size}
  171. }
  172. // fill reads uncompressed data into the dictionary.
  173. func (ur *uncompressedReader) fill() error {
  174. if !ur.eof {
  175. n, err := io.CopyN(ur.Dict, &ur.lr, int64(ur.Dict.Available()))
  176. if err != io.EOF {
  177. return err
  178. }
  179. ur.eof = true
  180. if n > 0 {
  181. return nil
  182. }
  183. }
  184. if ur.lr.N != 0 {
  185. return io.ErrUnexpectedEOF
  186. }
  187. return io.EOF
  188. }
  189. // Read reads uncompressed data from the limited reader.
  190. func (ur *uncompressedReader) Read(p []byte) (n int, err error) {
  191. if ur.err != nil {
  192. return 0, ur.err
  193. }
  194. for {
  195. var k int
  196. k, err = ur.Dict.Read(p[n:])
  197. n += k
  198. if n >= len(p) {
  199. return n, nil
  200. }
  201. if err != nil {
  202. break
  203. }
  204. err = ur.fill()
  205. if err != nil {
  206. break
  207. }
  208. }
  209. ur.err = err
  210. return n, err
  211. }