libgo: update to go1.9
[official-gcc.git] / libgo / go / archive / zip / register.go
blob51e9c3e4d4b7103e878f06894b2b10d013797965
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package zip
7 import (
8 "compress/flate"
9 "errors"
10 "io"
11 "io/ioutil"
12 "sync"
15 // A Compressor returns a new compressing writer, writing to w.
16 // The WriteCloser's Close method must be used to flush pending data to w.
17 // The Compressor itself must be safe to invoke from multiple goroutines
18 // simultaneously, but each returned writer will be used only by
19 // one goroutine at a time.
20 type Compressor func(w io.Writer) (io.WriteCloser, error)
22 // A Decompressor returns a new decompressing reader, reading from r.
23 // The ReadCloser's Close method must be used to release associated resources.
24 // The Decompressor itself must be safe to invoke from multiple goroutines
25 // simultaneously, but each returned reader will be used only by
26 // one goroutine at a time.
27 type Decompressor func(r io.Reader) io.ReadCloser
29 var flateWriterPool sync.Pool
31 func newFlateWriter(w io.Writer) io.WriteCloser {
32 fw, ok := flateWriterPool.Get().(*flate.Writer)
33 if ok {
34 fw.Reset(w)
35 } else {
36 fw, _ = flate.NewWriter(w, 5)
38 return &pooledFlateWriter{fw: fw}
41 type pooledFlateWriter struct {
42 mu sync.Mutex // guards Close and Write
43 fw *flate.Writer
46 func (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
47 w.mu.Lock()
48 defer w.mu.Unlock()
49 if w.fw == nil {
50 return 0, errors.New("Write after Close")
52 return w.fw.Write(p)
55 func (w *pooledFlateWriter) Close() error {
56 w.mu.Lock()
57 defer w.mu.Unlock()
58 var err error
59 if w.fw != nil {
60 err = w.fw.Close()
61 flateWriterPool.Put(w.fw)
62 w.fw = nil
64 return err
67 var flateReaderPool sync.Pool
69 func newFlateReader(r io.Reader) io.ReadCloser {
70 fr, ok := flateReaderPool.Get().(io.ReadCloser)
71 if ok {
72 fr.(flate.Resetter).Reset(r, nil)
73 } else {
74 fr = flate.NewReader(r)
76 return &pooledFlateReader{fr: fr}
79 type pooledFlateReader struct {
80 mu sync.Mutex // guards Close and Read
81 fr io.ReadCloser
84 func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
85 r.mu.Lock()
86 defer r.mu.Unlock()
87 if r.fr == nil {
88 return 0, errors.New("Read after Close")
90 return r.fr.Read(p)
93 func (r *pooledFlateReader) Close() error {
94 r.mu.Lock()
95 defer r.mu.Unlock()
96 var err error
97 if r.fr != nil {
98 err = r.fr.Close()
99 flateReaderPool.Put(r.fr)
100 r.fr = nil
102 return err
105 var (
106 compressors sync.Map // map[uint16]Compressor
107 decompressors sync.Map // map[uint16]Decompressor
110 func init() {
111 compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
112 compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
114 decompressors.Store(Store, Decompressor(ioutil.NopCloser))
115 decompressors.Store(Deflate, Decompressor(newFlateReader))
118 // RegisterDecompressor allows custom decompressors for a specified method ID.
119 // The common methods Store and Deflate are built in.
120 func RegisterDecompressor(method uint16, dcomp Decompressor) {
121 if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
122 panic("decompressor already registered")
126 // RegisterCompressor registers custom compressors for a specified method ID.
127 // The common methods Store and Deflate are built in.
128 func RegisterCompressor(method uint16, comp Compressor) {
129 if _, dup := compressors.LoadOrStore(method, comp); dup {
130 panic("compressor already registered")
134 func compressor(method uint16) Compressor {
135 ci, ok := compressors.Load(method)
136 if !ok {
137 return nil
139 return ci.(Compressor)
142 func decompressor(method uint16) Decompressor {
143 di, ok := decompressors.Load(method)
144 if !ok {
145 return nil
147 return di.(Decompressor)