123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- // Copyright 2010 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package zip
- import (
- "errors"
- "io"
- "io/ioutil"
- "sync"
- "github.com/klauspost/compress/flate"
- )
- // A Compressor returns a new compressing writer, writing to w.
- // The WriteCloser's Close method must be used to flush pending data to w.
- // The Compressor itself must be safe to invoke from multiple goroutines
- // simultaneously, but each returned writer will be used only by
- // one goroutine at a time.
- type Compressor func(w io.Writer) (io.WriteCloser, error)
- // A Decompressor returns a new decompressing reader, reading from r.
- // The ReadCloser's Close method must be used to release associated resources.
- // The Decompressor itself must be safe to invoke from multiple goroutines
- // simultaneously, but each returned reader will be used only by
- // one goroutine at a time.
- type Decompressor func(r io.Reader) io.ReadCloser
- var flateWriterPool sync.Pool
- func newFlateWriter(w io.Writer) io.WriteCloser {
- fw, ok := flateWriterPool.Get().(*flate.Writer)
- if ok {
- fw.Reset(w)
- } else {
- fw, _ = flate.NewWriter(w, 5)
- }
- return &pooledFlateWriter{fw: fw}
- }
- type pooledFlateWriter struct {
- mu sync.Mutex // guards Close and Write
- fw *flate.Writer
- }
- func (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
- w.mu.Lock()
- defer w.mu.Unlock()
- if w.fw == nil {
- return 0, errors.New("Write after Close")
- }
- return w.fw.Write(p)
- }
- func (w *pooledFlateWriter) Close() error {
- w.mu.Lock()
- defer w.mu.Unlock()
- var err error
- if w.fw != nil {
- err = w.fw.Close()
- flateWriterPool.Put(w.fw)
- w.fw = nil
- }
- return err
- }
- var flateReaderPool sync.Pool
- func newFlateReader(r io.Reader) io.ReadCloser {
- fr, ok := flateReaderPool.Get().(io.ReadCloser)
- if ok {
- fr.(flate.Resetter).Reset(r, nil)
- } else {
- fr = flate.NewReader(r)
- }
- return &pooledFlateReader{fr: fr}
- }
- type pooledFlateReader struct {
- mu sync.Mutex // guards Close and Read
- fr io.ReadCloser
- }
- func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
- if r.fr == nil {
- return 0, errors.New("Read after Close")
- }
- return r.fr.Read(p)
- }
- func (r *pooledFlateReader) Close() error {
- r.mu.Lock()
- defer r.mu.Unlock()
- var err error
- if r.fr != nil {
- err = r.fr.Close()
- flateReaderPool.Put(r.fr)
- r.fr = nil
- }
- return err
- }
- var (
- compressors sync.Map // map[uint16]Compressor
- decompressors sync.Map // map[uint16]Decompressor
- )
- func init() {
- compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
- compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
- decompressors.Store(Store, Decompressor(ioutil.NopCloser))
- decompressors.Store(Deflate, Decompressor(newFlateReader))
- }
- // RegisterDecompressor allows custom decompressors for a specified method ID.
- // The common methods Store and Deflate are built in.
- func RegisterDecompressor(method uint16, dcomp Decompressor) {
- if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
- panic("decompressor already registered")
- }
- }
- // RegisterCompressor registers custom compressors for a specified method ID.
- // The common methods Store and Deflate are built in.
- func RegisterCompressor(method uint16, comp Compressor) {
- if _, dup := compressors.LoadOrStore(method, comp); dup {
- panic("compressor already registered")
- }
- }
- func compressor(method uint16) Compressor {
- ci, ok := compressors.Load(method)
- if !ok {
- return nil
- }
- return ci.(Compressor)
- }
- func decompressor(method uint16) Decompressor {
- di, ok := decompressors.Load(method)
- if !ok {
- return nil
- }
- return di.(Decompressor)
- }
|