@@ -298,6 +298,14 @@ const (
298
298
huffmanGenericReader
299
299
)
300
300
301
+ // flushMode tells decompressor when to return data
302
+ type flushMode uint8
303
+
304
+ const (
305
+ syncFlush flushMode = iota // return data after sync flush block
306
+ partialFlush // return data after each block
307
+ )
308
+
301
309
// Decompress state.
302
310
type decompressor struct {
303
311
// Input source.
@@ -332,6 +340,8 @@ type decompressor struct {
332
340
333
341
nb uint
334
342
final bool
343
+
344
+ flushMode flushMode
335
345
}
336
346
337
347
func (f * decompressor ) nextBlock () {
@@ -618,7 +628,10 @@ func (f *decompressor) dataBlock() {
618
628
}
619
629
620
630
if n == 0 {
621
- f .toRead = f .dict .readFlush ()
631
+ if f .flushMode == syncFlush {
632
+ f .toRead = f .dict .readFlush ()
633
+ }
634
+
622
635
f .finishBlock ()
623
636
return
624
637
}
@@ -657,8 +670,12 @@ func (f *decompressor) finishBlock() {
657
670
if f .dict .availRead () > 0 {
658
671
f .toRead = f .dict .readFlush ()
659
672
}
673
+
660
674
f .err = io .EOF
675
+ } else if f .flushMode == partialFlush && f .dict .availRead () > 0 {
676
+ f .toRead = f .dict .readFlush ()
661
677
}
678
+
662
679
f .step = nextBlock
663
680
}
664
681
@@ -789,15 +806,25 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error {
789
806
return nil
790
807
}
791
808
792
- // NewReader returns a new ReadCloser that can be used
793
- // to read the uncompressed version of r.
794
- // If r does not also implement io.ByteReader,
795
- // the decompressor may read more data than necessary from r.
796
- // It is the caller's responsibility to call Close on the ReadCloser
797
- // when finished reading.
798
- //
799
- // The ReadCloser returned by NewReader also implements Resetter.
800
- func NewReader (r io.Reader ) io.ReadCloser {
809
+ type ReaderOpt func (* decompressor )
810
+
811
+ // WithPartialBlock tells decompressor to return after each block,
812
+ // so it can read data written with partial flush
813
+ func WithPartialBlock () ReaderOpt {
814
+ return func (f * decompressor ) {
815
+ f .flushMode = partialFlush
816
+ }
817
+ }
818
+
819
+ // WithDict initializes the reader with a preset dictionary
820
+ func WithDict (dict []byte ) ReaderOpt {
821
+ return func (f * decompressor ) {
822
+ f .dict .init (maxMatchOffset , dict )
823
+ }
824
+ }
825
+
826
+ // NewReaderOpts returns new reader with provided options
827
+ func NewReaderOpts (r io.Reader , opts ... ReaderOpt ) io.ReadCloser {
801
828
fixedHuffmanDecoderInit ()
802
829
803
830
var f decompressor
@@ -806,9 +833,26 @@ func NewReader(r io.Reader) io.ReadCloser {
806
833
f .codebits = new ([numCodes ]int )
807
834
f .step = nextBlock
808
835
f .dict .init (maxMatchOffset , nil )
836
+
837
+ for _ , opt := range opts {
838
+ opt (& f )
839
+ }
840
+
809
841
return & f
810
842
}
811
843
844
+ // NewReader returns a new ReadCloser that can be used
845
+ // to read the uncompressed version of r.
846
+ // If r does not also implement io.ByteReader,
847
+ // the decompressor may read more data than necessary from r.
848
+ // It is the caller's responsibility to call Close on the ReadCloser
849
+ // when finished reading.
850
+ //
851
+ // The ReadCloser returned by NewReader also implements Resetter.
852
+ func NewReader (r io.Reader ) io.ReadCloser {
853
+ return NewReaderOpts (r )
854
+ }
855
+
812
856
// NewReaderDict is like NewReader but initializes the reader
813
857
// with a preset dictionary. The returned Reader behaves as if
814
858
// the uncompressed data stream started with the given dictionary,
@@ -817,13 +861,5 @@ func NewReader(r io.Reader) io.ReadCloser {
817
861
//
818
862
// The ReadCloser returned by NewReader also implements Resetter.
819
863
func NewReaderDict (r io.Reader , dict []byte ) io.ReadCloser {
820
- fixedHuffmanDecoderInit ()
821
-
822
- var f decompressor
823
- f .r = makeReader (r )
824
- f .bits = new ([maxNumLit + maxNumDist ]int )
825
- f .codebits = new ([numCodes ]int )
826
- f .step = nextBlock
827
- f .dict .init (maxMatchOffset , dict )
828
- return & f
864
+ return NewReaderOpts (r , WithDict (dict ))
829
865
}
0 commit comments