reader.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package lz4
  2. import (
  3. "io"
  4. "github.com/pierrec/lz4/internal/lz4errors"
  5. "github.com/pierrec/lz4/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. return zr.Reset(r)
  20. }
  21. type Reader struct {
  22. state _State
  23. src io.Reader // source reader
  24. frame *lz4stream.Frame // frame being read
  25. data []byte // pending data
  26. idx int // size of pending data
  27. handler func(int)
  28. }
  29. func (*Reader) private() {}
  30. func (r *Reader) Apply(options ...Option) (err error) {
  31. defer r.state.check(&err)
  32. switch r.state.state {
  33. case newState:
  34. case errorState:
  35. return r.state.err
  36. default:
  37. return lz4errors.ErrOptionClosedOrError
  38. }
  39. for _, o := range options {
  40. if err = o(r); err != nil {
  41. return
  42. }
  43. }
  44. return
  45. }
  46. // Size returns the size of the underlying uncompressed data, if set in the stream.
  47. func (r *Reader) Size() int {
  48. switch r.state.state {
  49. case readState, closedState:
  50. if r.frame.Descriptor.Flags.Size() {
  51. return int(r.frame.Descriptor.ContentSize)
  52. }
  53. }
  54. return 0
  55. }
  56. func (r *Reader) Read(buf []byte) (n int, err error) {
  57. defer r.state.check(&err)
  58. switch r.state.state {
  59. case readState:
  60. case closedState, errorState:
  61. return 0, r.state.err
  62. case newState:
  63. // First initialization.
  64. if err = r.frame.InitR(r.src); r.state.next(err) {
  65. return
  66. }
  67. r.data = r.frame.Descriptor.Flags.BlockSizeIndex().Get()
  68. default:
  69. return 0, r.state.fail()
  70. }
  71. if len(buf) == 0 {
  72. return
  73. }
  74. var bn int
  75. if r.idx > 0 {
  76. // Some left over data, use it.
  77. goto fillbuf
  78. }
  79. // No uncompressed data yet.
  80. r.data = r.data[:cap(r.data)]
  81. for len(buf) >= len(r.data) {
  82. // Input buffer large enough and no pending data: uncompress directly into it.
  83. switch bn, err = r.frame.Blocks.Block.Uncompress(r.frame, r.src, buf); err {
  84. case nil:
  85. r.handler(bn)
  86. n += bn
  87. buf = buf[bn:]
  88. case io.EOF:
  89. goto close
  90. default:
  91. return
  92. }
  93. }
  94. if n > 0 {
  95. // Some data was read, done for now.
  96. return
  97. }
  98. // Read the next block.
  99. switch bn, err = r.frame.Blocks.Block.Uncompress(r.frame, r.src, r.data); err {
  100. case nil:
  101. r.handler(bn)
  102. r.data = r.data[:bn]
  103. goto fillbuf
  104. case io.EOF:
  105. default:
  106. return
  107. }
  108. close:
  109. r.handler(bn)
  110. n += bn
  111. if er := r.frame.CloseR(r.src); er != nil {
  112. err = er
  113. }
  114. r.frame.Descriptor.Flags.BlockSizeIndex().Put(r.data)
  115. r.reset(nil)
  116. return
  117. fillbuf:
  118. bn = copy(buf, r.data[r.idx:])
  119. n += bn
  120. r.idx += bn
  121. if r.idx == len(r.data) {
  122. // All data read, get ready for the next Read.
  123. r.idx = 0
  124. }
  125. return
  126. }
  127. func (r *Reader) reset(reader io.Reader) {
  128. r.src = reader
  129. r.data = nil
  130. r.idx = 0
  131. }
  132. // Reset clears the state of the Reader r such that it is equivalent to its
  133. // initial state from NewReader, but instead writing to writer.
  134. // No access to reader is performed.
  135. //
  136. // w.Close must be called before Reset.
  137. func (r *Reader) Reset(reader io.Reader) *Reader {
  138. r.reset(reader)
  139. r.state.state = noState
  140. r.state.next(nil)
  141. return r
  142. }