reader.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package lz4
  2. import (
  3. "io"
  4. "github.com/pierrec/lz4/v4/internal/lz4errors"
  5. "github.com/pierrec/lz4/v4/internal/lz4stream"
  6. )
  7. var readerStates = []aState{
  8. noState: newState,
  9. errorState: newState,
  10. newState: readState,
  11. readState: closedState,
  12. closedState: newState,
  13. }
  14. // NewReader returns a new LZ4 frame decoder.
  15. func NewReader(r io.Reader) *Reader {
  16. zr := &Reader{frame: lz4stream.NewFrame()}
  17. zr.state.init(readerStates)
  18. _ = zr.Apply(defaultOnBlockDone)
  19. zr.Reset(r)
  20. return zr
  21. }
  22. // Reader allows reading an LZ4 stream.
  23. type Reader struct {
  24. state _State
  25. src io.Reader // source reader
  26. frame *lz4stream.Frame // frame being read
  27. data []byte // pending data
  28. idx int // size of pending data
  29. handler func(int)
  30. }
  31. func (*Reader) private() {}
  32. func (r *Reader) Apply(options ...Option) (err error) {
  33. defer r.state.check(&err)
  34. switch r.state.state {
  35. case newState:
  36. case errorState:
  37. return r.state.err
  38. default:
  39. return lz4errors.ErrOptionClosedOrError
  40. }
  41. for _, o := range options {
  42. if err = o(r); err != nil {
  43. return
  44. }
  45. }
  46. return
  47. }
  48. // Size returns the size of the underlying uncompressed data, if set in the stream.
  49. func (r *Reader) Size() int {
  50. switch r.state.state {
  51. case readState, closedState:
  52. if r.frame.Descriptor.Flags.Size() {
  53. return int(r.frame.Descriptor.ContentSize)
  54. }
  55. }
  56. return 0
  57. }
  58. func (r *Reader) init() error {
  59. return r.frame.InitR(r.src)
  60. }
  61. func (r *Reader) Read(buf []byte) (n int, err error) {
  62. defer r.state.check(&err)
  63. switch r.state.state {
  64. case readState:
  65. case closedState, errorState:
  66. return 0, r.state.err
  67. case newState:
  68. // First initialization.
  69. if err = r.init(); r.state.next(err) {
  70. return
  71. }
  72. size := r.frame.Descriptor.Flags.BlockSizeIndex()
  73. r.data = size.Get()
  74. default:
  75. return 0, r.state.fail()
  76. }
  77. if len(buf) == 0 {
  78. return
  79. }
  80. var bn int
  81. if r.idx > 0 {
  82. // Some left over data, use it.
  83. goto fillbuf
  84. }
  85. // No uncompressed data yet.
  86. r.data = r.data[:cap(r.data)]
  87. for len(buf) >= len(r.data) {
  88. // Input buffer large enough and no pending data: uncompress directly into it.
  89. switch bn, err = r.frame.Blocks.Block.Uncompress(r.frame, r.src, buf); err {
  90. case nil:
  91. r.handler(bn)
  92. n += bn
  93. buf = buf[bn:]
  94. case io.EOF:
  95. goto close
  96. default:
  97. return
  98. }
  99. }
  100. if n > 0 {
  101. // Some data was read, done for now.
  102. return
  103. }
  104. // Read the next block.
  105. switch bn, err = r.frame.Blocks.Block.Uncompress(r.frame, r.src, r.data); err {
  106. case nil:
  107. r.handler(bn)
  108. r.data = r.data[:bn]
  109. goto fillbuf
  110. case io.EOF:
  111. default:
  112. return
  113. }
  114. close:
  115. if er := r.frame.CloseR(r.src); er != nil {
  116. err = er
  117. }
  118. r.Reset(nil)
  119. return
  120. fillbuf:
  121. bn = copy(buf, r.data[r.idx:])
  122. n += bn
  123. r.idx += bn
  124. if r.idx == len(r.data) {
  125. // All data read, get ready for the next Read.
  126. r.idx = 0
  127. }
  128. return
  129. }
  130. // Reset clears the state of the Reader r such that it is equivalent to its
  131. // initial state from NewReader, but instead writing to writer.
  132. // No access to reader is performed.
  133. //
  134. // w.Close must be called before Reset.
  135. func (r *Reader) Reset(reader io.Reader) {
  136. size := r.frame.Descriptor.Flags.BlockSizeIndex()
  137. size.Put(r.data)
  138. r.frame.Reset(1)
  139. r.src = reader
  140. r.data = nil
  141. r.idx = 0
  142. r.state.reset()
  143. }
  144. // WriteTo efficiently uncompresses the data from the Reader underlying source to w.
  145. func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
  146. switch r.state.state {
  147. case closedState, errorState:
  148. return 0, r.state.err
  149. case newState:
  150. if err = r.init(); r.state.next(err) {
  151. return
  152. }
  153. default:
  154. return 0, r.state.fail()
  155. }
  156. defer r.state.nextd(&err)
  157. var bn int
  158. block := r.frame.Blocks.Block
  159. size := r.frame.Descriptor.Flags.BlockSizeIndex()
  160. data := size.Get()
  161. defer size.Put(data)
  162. for {
  163. switch bn, err = block.Uncompress(r.frame, r.src, data); err {
  164. case nil:
  165. case io.EOF:
  166. err = r.frame.CloseR(r.src)
  167. return
  168. default:
  169. return
  170. }
  171. r.handler(bn)
  172. bn, err = w.Write(data[:bn])
  173. n += int64(bn)
  174. if err != nil {
  175. return
  176. }
  177. }
  178. }