Retro68/gcc/libgo/go/archive/zip/register.go

149 lines
3.7 KiB
Go
Raw Normal View History

2014-09-21 17:33:12 +00:00
// 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 (
"compress/flate"
2015-08-28 15:33:40 +00:00
"errors"
2014-09-21 17:33:12 +00:00
"io"
"io/ioutil"
"sync"
)
2017-04-10 11:32:00 +00:00
// 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
2014-09-21 17:33:12 +00:00
2015-08-28 15:33:40 +00:00
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
}
2014-09-21 17:33:12 +00:00
var (
2018-12-28 15:30:48 +00:00
compressors sync.Map // map[uint16]Compressor
decompressors sync.Map // map[uint16]Decompressor
)
2014-09-21 17:33:12 +00:00
2018-12-28 15:30:48 +00:00
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 }))
2014-09-21 17:33:12 +00:00
2018-12-28 15:30:48 +00:00
decompressors.Store(Store, Decompressor(ioutil.NopCloser))
decompressors.Store(Deflate, Decompressor(newFlateReader))
}
2014-09-21 17:33:12 +00:00
// RegisterDecompressor allows custom decompressors for a specified method ID.
2017-04-10 11:32:00 +00:00
// The common methods Store and Deflate are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
2018-12-28 15:30:48 +00:00
if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
2014-09-21 17:33:12 +00:00
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) {
2018-12-28 15:30:48 +00:00
if _, dup := compressors.LoadOrStore(method, comp); dup {
2014-09-21 17:33:12 +00:00
panic("compressor already registered")
}
}
func compressor(method uint16) Compressor {
2018-12-28 15:30:48 +00:00
ci, ok := compressors.Load(method)
if !ok {
return nil
}
return ci.(Compressor)
2014-09-21 17:33:12 +00:00
}
func decompressor(method uint16) Decompressor {
2018-12-28 15:30:48 +00:00
di, ok := decompressors.Load(method)
if !ok {
return nil
}
return di.(Decompressor)
2014-09-21 17:33:12 +00:00
}