c++: Implement C++26 P2558R2 - Add @, $, and ` to the basic character set [PR110343]
[official-gcc.git] / libgo / go / archive / zip / register.go
blob4389246286f6830c48d120e98ba5ef2ded567664
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 "sync"
14 // A Compressor returns a new compressing writer, writing to w.
15 // The WriteCloser's Close method must be used to flush pending data to w.
16 // The Compressor itself must be safe to invoke from multiple goroutines
17 // simultaneously, but each returned writer will be used only by
18 // one goroutine at a time.
19 type Compressor func(w io.Writer) (io.WriteCloser, error)
21 // A Decompressor returns a new decompressing reader, reading from r.
22 // The ReadCloser's Close method must be used to release associated resources.
23 // The Decompressor itself must be safe to invoke from multiple goroutines
24 // simultaneously, but each returned reader will be used only by
25 // one goroutine at a time.
26 type Decompressor func(r io.Reader) io.ReadCloser
28 var flateWriterPool sync.Pool
30 func newFlateWriter(w io.Writer) io.WriteCloser {
31 fw, ok := flateWriterPool.Get().(*flate.Writer)
32 if ok {
33 fw.Reset(w)
34 } else {
35 fw, _ = flate.NewWriter(w, 5)
37 return &pooledFlateWriter{fw: fw}
40 type pooledFlateWriter struct {
41 mu sync.Mutex // guards Close and Write
42 fw *flate.Writer
45 func (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
46 w.mu.Lock()
47 defer w.mu.Unlock()
48 if w.fw == nil {
49 return 0, errors.New("Write after Close")
51 return w.fw.Write(p)
54 func (w *pooledFlateWriter) Close() error {
55 w.mu.Lock()
56 defer w.mu.Unlock()
57 var err error
58 if w.fw != nil {
59 err = w.fw.Close()
60 flateWriterPool.Put(w.fw)
61 w.fw = nil
63 return err
66 var flateReaderPool sync.Pool
68 func newFlateReader(r io.Reader) io.ReadCloser {
69 fr, ok := flateReaderPool.Get().(io.ReadCloser)
70 if ok {
71 fr.(flate.Resetter).Reset(r, nil)
72 } else {
73 fr = flate.NewReader(r)
75 return &pooledFlateReader{fr: fr}
78 type pooledFlateReader struct {
79 mu sync.Mutex // guards Close and Read
80 fr io.ReadCloser
83 func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
84 r.mu.Lock()
85 defer r.mu.Unlock()
86 if r.fr == nil {
87 return 0, errors.New("Read after Close")
89 return r.fr.Read(p)
92 func (r *pooledFlateReader) Close() error {
93 r.mu.Lock()
94 defer r.mu.Unlock()
95 var err error
96 if r.fr != nil {
97 err = r.fr.Close()
98 flateReaderPool.Put(r.fr)
99 r.fr = nil
101 return err
104 var (
105 compressors sync.Map // map[uint16]Compressor
106 decompressors sync.Map // map[uint16]Decompressor
109 func init() {
110 compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
111 compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
113 decompressors.Store(Store, Decompressor(io.NopCloser))
114 decompressors.Store(Deflate, Decompressor(newFlateReader))
117 // RegisterDecompressor allows custom decompressors for a specified method ID.
118 // The common methods Store and Deflate are built in.
119 func RegisterDecompressor(method uint16, dcomp Decompressor) {
120 if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
121 panic("decompressor already registered")
125 // RegisterCompressor registers custom compressors for a specified method ID.
126 // The common methods Store and Deflate are built in.
127 func RegisterCompressor(method uint16, comp Compressor) {
128 if _, dup := compressors.LoadOrStore(method, comp); dup {
129 panic("compressor already registered")
133 func compressor(method uint16) Compressor {
134 ci, ok := compressors.Load(method)
135 if !ok {
136 return nil
138 return ci.(Compressor)
141 func decompressor(method uint16) Decompressor {
142 di, ok := decompressors.Load(method)
143 if !ok {
144 return nil
146 return di.(Decompressor)