Browse Source

added Writer.Apply and Reader.Apply

Pierre.Curto 5 năm trước cách đây
mục cha
commit
f777510651
9 tập tin đã thay đổi với 95 bổ sung30 xóa
  1. 1 1
      cmd/lz4c/compress.go
  2. 2 0
      cmd/lz4c/main.go
  3. 1 1
      cmd/lz4c/uncompress.go
  4. 3 0
      go.mod
  5. 6 0
      go.sum
  6. 4 0
      lz4.go
  7. 39 8
      options.go
  8. 24 6
      reader.go
  9. 15 14
      writer.go

+ 1 - 1
cmd/lz4c/compress.go

@@ -86,7 +86,7 @@ func Compress(fs *flag.FlagSet) cmdflag.Handler {
 			}
 
 			// Output file.
-			zfilename := fmt.Sprintf("%s%s", filename, lz4.Extension)
+			zfilename := fmt.Sprintf("%s%s", filename, lz4Extension)
 			zfile, err := os.OpenFile(zfilename, os.O_CREATE|os.O_WRONLY, mode)
 			if err != nil {
 				return fidx, err

+ 2 - 0
cmd/lz4c/main.go

@@ -7,6 +7,8 @@ import (
 	"github.com/pierrec/cmdflag"
 )
 
+const lz4Extension = ".lz4"
+
 func main() {
 	flag.CommandLine.Bool(cmdflag.VersionBoolFlag, false, "print the program version")
 

+ 1 - 1
cmd/lz4c/uncompress.go

@@ -38,7 +38,7 @@ func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
 			mode := zinfo.Mode() // use the same mode for the output file
 
 			// Output file.
-			filename := strings.TrimSuffix(zfilename, lz4.Extension)
+			filename := strings.TrimSuffix(zfilename, lz4Extension)
 			file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, mode)
 			if err != nil {
 				return fidx, err

+ 3 - 0
go.mod

@@ -3,7 +3,10 @@ module github.com/pierrec/lz4
 go 1.14
 
 require (
+	code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48
 	github.com/frankban/quicktest v1.9.0 // indirect
+	github.com/pierrec/cmdflag v0.0.2
 	github.com/pierrec/packer v0.0.0-20200419211718-decbba9fa6fa // indirect
+	github.com/schollz/progressbar v1.0.0
 	golang.org/x/tools v0.0.0-20200420001825-978e26b7c37c // indirect
 )

+ 6 - 0
go.sum

@@ -1,3 +1,5 @@
+code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48 h1:/EMHruHCFXR9xClkGV/t0rmHrdhX4+trQUcBqjwc9xE=
+code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc=
 github.com/frankban/quicktest v1.9.0 h1:jfEA+Psfr/pHsRJYPpHiNu7PGJnGctNxvTaM3K1EyXk=
 github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
 github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
@@ -7,8 +9,12 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pierrec/cmdflag v0.0.2 h1:ybjGJnPr/aURn2IKWjO49znx9N0DL6YfGsIxN0PYuVY=
+github.com/pierrec/cmdflag v0.0.2/go.mod h1:a3zKGZ3cdQUfxjd0RGMLZr8xI3nvpJOB+m6o/1X5BmU=
 github.com/pierrec/packer v0.0.0-20200419211718-decbba9fa6fa h1:yVA4oBytvOmjYjiQzeJL83TlMb/g2y7WbnrspRVtPMk=
 github.com/pierrec/packer v0.0.0-20200419211718-decbba9fa6fa/go.mod h1:GKrs5lzNeoNBN0l+jHHePFsqiNgXrZT5vQvGt28rWjI=
+github.com/schollz/progressbar v1.0.0 h1:gbyFReLHDkZo8mxy/dLWMr+Mpb1MokGJ1FqCiqacjZM=
+github.com/schollz/progressbar v1.0.0/go.mod h1:/l9I7PC3L3erOuz54ghIRKUEFcosiWfLvJv+Eq26UMs=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

+ 4 - 0
lz4.go

@@ -48,4 +48,8 @@ const (
 	ErrInvalidCompressionLevel _error = "lz4: invalid compression level"
 	// ErrCannotApplyOptions
 	ErrCannotApplyOptions _error = "lz4: cannot apply options"
+	// ErrInvalidBlockSize
+	ErrInvalidBlockSize _error = "lz4: invalid block size"
+	// ErrOptionNotApplicable
+	ErrOptionNotApplicable _error = "lz4: option not applicable"
 )

+ 39 - 8
options.go

@@ -9,7 +9,7 @@ import (
 //go:generate go run golang.org/x/tools/cmd/stringer -type=BlockSize,CompressionLevel -output options_gen.go
 
 // Option defines the parameters to setup an LZ4 Writer or Reader.
-type Option func(*Writer) error
+type Option func(*Reader, *Writer) error
 
 // Default options.
 var (
@@ -85,9 +85,12 @@ func (b BlockSizeIndex) put(buf []byte) {
 
 // BlockSizeOption defines the maximum size of compressed blocks (default=Block4Mb).
 func BlockSizeOption(size BlockSize) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		if !size.isValid() {
-			return fmt.Errorf("lz4: invalid block size %d", size)
+			return fmt.Errorf("%w: %d", ErrInvalidBlockSize, size)
 		}
 		w.frame.Descriptor.Flags.BlockSizeIndexSet(size.index())
 		return nil
@@ -96,7 +99,10 @@ func BlockSizeOption(size BlockSize) Option {
 
 // BlockChecksumOption enables or disables block checksum (default=false).
 func BlockChecksumOption(flag bool) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		w.frame.Descriptor.Flags.BlockChecksumSet(flag)
 		return nil
 	}
@@ -104,7 +110,10 @@ func BlockChecksumOption(flag bool) Option {
 
 // ChecksumOption enables/disables all blocks checksum (default=true).
 func ChecksumOption(flag bool) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		w.frame.Descriptor.Flags.ContentChecksumSet(flag)
 		return nil
 	}
@@ -112,7 +121,10 @@ func ChecksumOption(flag bool) Option {
 
 // SizeOption sets the size of the original uncompressed data (default=0).
 func SizeOption(size uint64) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		w.frame.Descriptor.Flags.SizeSet(size > 0)
 		w.frame.Descriptor.ContentSize = size
 		return nil
@@ -122,7 +134,10 @@ func SizeOption(size uint64) Option {
 // ConcurrencyOption sets the number of go routines used for compression.
 // If n<0, then the output of runtime.GOMAXPROCS(0) is used.
 func ConcurrencyOption(n int) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		switch n {
 		case 0, 1:
 		default:
@@ -153,7 +168,10 @@ const (
 
 // CompressionLevelOption defines the compression level (default=Fast).
 func CompressionLevelOption(level CompressionLevel) Option {
-	return func(w *Writer) error {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			return ErrOptionNotApplicable
+		}
 		switch level {
 		case Fast, Level1, Level2, Level3, Level4, Level5, Level6, Level7, Level8, Level9:
 		default:
@@ -163,3 +181,16 @@ func CompressionLevelOption(level CompressionLevel) Option {
 		return nil
 	}
 }
+
+// OnBlockDoneOption is triggered
+func OnBlockDoneOption(handler func(size int)) Option {
+	return func(r *Reader, w *Writer) error {
+		if r != nil {
+			r.handler = handler
+		}
+		if w != nil {
+			w.handler = handler
+		}
+		return nil
+	}
+}

+ 24 - 6
reader.go

@@ -21,12 +21,30 @@ func NewReader(r io.Reader) *Reader {
 }
 
 type Reader struct {
-	state _State
-	buf   [11]byte  // frame descriptor needs at most 2+8+1=11 bytes
-	src   io.Reader // source reader
-	frame Frame     // frame being read
-	data  []byte    // pending data
-	idx   int       // size of pending data
+	state   _State
+	buf     [11]byte  // frame descriptor needs at most 2+8+1=11 bytes
+	src     io.Reader // source reader
+	frame   Frame     // frame being read
+	data    []byte    // pending data
+	idx     int       // size of pending data
+	handler func(int)
+}
+
+func (r *Reader) Apply(options ...Option) (err error) {
+	defer r.state.check(&err)
+	switch r.state.state {
+	case newState:
+	case errorState:
+		return r.state.err
+	default:
+		return ErrCannotApplyOptions
+	}
+	for _, o := range options {
+		if err = o(r, nil); err != nil {
+			return
+		}
+	}
+	return
 }
 
 // Size returns the size of the underlying uncompressed data, if set in the stream.

+ 15 - 14
writer.go

@@ -15,22 +15,23 @@ var writerStates = []aState{
 func NewWriter(w io.Writer) *Writer {
 	zw := new(Writer)
 	zw.state.init(writerStates)
-	_ = defaultBlockSizeOption(zw)
-	_ = defaultChecksumOption(zw)
-	_ = defaultConcurrency(zw)
+	_ = defaultBlockSizeOption(nil, zw)
+	_ = defaultChecksumOption(nil, zw)
+	_ = defaultConcurrency(nil, zw)
 	return zw.Reset(w)
 }
 
 type Writer struct {
-	state _State
-	buf   [11]byte         // frame descriptor needs at most 4+8+1=11 bytes
-	src   io.Writer        // destination writer
-	level CompressionLevel // how hard to try
-	num   int              // concurrency level
-	frame Frame            // frame being built
-	ht    []int            // hash table (set if no concurrency)
-	data  []byte           // pending data
-	idx   int              // size of pending data
+	state   _State
+	buf     [11]byte         // frame descriptor needs at most 4+8+1=11 bytes
+	src     io.Writer        // destination writer
+	level   CompressionLevel // how hard to try
+	num     int              // concurrency level
+	frame   Frame            // frame being built
+	ht      []int            // hash table (set if no concurrency)
+	data    []byte           // pending data
+	idx     int              // size of pending data
+	handler func(int)
 }
 
 func (w *Writer) Apply(options ...Option) (err error) {
@@ -43,8 +44,8 @@ func (w *Writer) Apply(options ...Option) (err error) {
 		return ErrCannotApplyOptions
 	}
 	for _, o := range options {
-		if err := o(w); err != nil {
-			return err
+		if err = o(nil, w); err != nil {
+			return
 		}
 	}
 	return