xref: /aosp_15_r20/build/soong/third_party/zip/register.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2010 The Go Authors. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style
3*333d2b36SAndroid Build Coastguard Worker// license that can be found in the LICENSE file.
4*333d2b36SAndroid Build Coastguard Worker
5*333d2b36SAndroid Build Coastguard Workerpackage zip
6*333d2b36SAndroid Build Coastguard Worker
7*333d2b36SAndroid Build Coastguard Workerimport (
8*333d2b36SAndroid Build Coastguard Worker	"compress/flate"
9*333d2b36SAndroid Build Coastguard Worker	"errors"
10*333d2b36SAndroid Build Coastguard Worker	"io"
11*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
12*333d2b36SAndroid Build Coastguard Worker	"sync"
13*333d2b36SAndroid Build Coastguard Worker)
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Worker// A Compressor returns a new compressing writer, writing to w.
16*333d2b36SAndroid Build Coastguard Worker// The WriteCloser's Close method must be used to flush pending data to w.
17*333d2b36SAndroid Build Coastguard Worker// The Compressor itself must be safe to invoke from multiple goroutines
18*333d2b36SAndroid Build Coastguard Worker// simultaneously, but each returned writer will be used only by
19*333d2b36SAndroid Build Coastguard Worker// one goroutine at a time.
20*333d2b36SAndroid Build Coastguard Workertype Compressor func(w io.Writer) (io.WriteCloser, error)
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker// A Decompressor returns a new decompressing reader, reading from r.
23*333d2b36SAndroid Build Coastguard Worker// The ReadCloser's Close method must be used to release associated resources.
24*333d2b36SAndroid Build Coastguard Worker// The Decompressor itself must be safe to invoke from multiple goroutines
25*333d2b36SAndroid Build Coastguard Worker// simultaneously, but each returned reader will be used only by
26*333d2b36SAndroid Build Coastguard Worker// one goroutine at a time.
27*333d2b36SAndroid Build Coastguard Workertype Decompressor func(r io.Reader) io.ReadCloser
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Workervar flateWriterPool sync.Pool
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Workerfunc newFlateWriter(w io.Writer) io.WriteCloser {
32*333d2b36SAndroid Build Coastguard Worker	fw, ok := flateWriterPool.Get().(*flate.Writer)
33*333d2b36SAndroid Build Coastguard Worker	if ok {
34*333d2b36SAndroid Build Coastguard Worker		fw.Reset(w)
35*333d2b36SAndroid Build Coastguard Worker	} else {
36*333d2b36SAndroid Build Coastguard Worker		fw, _ = flate.NewWriter(w, 5)
37*333d2b36SAndroid Build Coastguard Worker	}
38*333d2b36SAndroid Build Coastguard Worker	return &pooledFlateWriter{fw: fw}
39*333d2b36SAndroid Build Coastguard Worker}
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Workertype pooledFlateWriter struct {
42*333d2b36SAndroid Build Coastguard Worker	mu sync.Mutex // guards Close and Write
43*333d2b36SAndroid Build Coastguard Worker	fw *flate.Writer
44*333d2b36SAndroid Build Coastguard Worker}
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Workerfunc (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
47*333d2b36SAndroid Build Coastguard Worker	w.mu.Lock()
48*333d2b36SAndroid Build Coastguard Worker	defer w.mu.Unlock()
49*333d2b36SAndroid Build Coastguard Worker	if w.fw == nil {
50*333d2b36SAndroid Build Coastguard Worker		return 0, errors.New("Write after Close")
51*333d2b36SAndroid Build Coastguard Worker	}
52*333d2b36SAndroid Build Coastguard Worker	return w.fw.Write(p)
53*333d2b36SAndroid Build Coastguard Worker}
54*333d2b36SAndroid Build Coastguard Worker
55*333d2b36SAndroid Build Coastguard Workerfunc (w *pooledFlateWriter) Close() error {
56*333d2b36SAndroid Build Coastguard Worker	w.mu.Lock()
57*333d2b36SAndroid Build Coastguard Worker	defer w.mu.Unlock()
58*333d2b36SAndroid Build Coastguard Worker	var err error
59*333d2b36SAndroid Build Coastguard Worker	if w.fw != nil {
60*333d2b36SAndroid Build Coastguard Worker		err = w.fw.Close()
61*333d2b36SAndroid Build Coastguard Worker		flateWriterPool.Put(w.fw)
62*333d2b36SAndroid Build Coastguard Worker		w.fw = nil
63*333d2b36SAndroid Build Coastguard Worker	}
64*333d2b36SAndroid Build Coastguard Worker	return err
65*333d2b36SAndroid Build Coastguard Worker}
66*333d2b36SAndroid Build Coastguard Worker
67*333d2b36SAndroid Build Coastguard Workervar flateReaderPool sync.Pool
68*333d2b36SAndroid Build Coastguard Worker
69*333d2b36SAndroid Build Coastguard Workerfunc newFlateReader(r io.Reader) io.ReadCloser {
70*333d2b36SAndroid Build Coastguard Worker	fr, ok := flateReaderPool.Get().(io.ReadCloser)
71*333d2b36SAndroid Build Coastguard Worker	if ok {
72*333d2b36SAndroid Build Coastguard Worker		fr.(flate.Resetter).Reset(r, nil)
73*333d2b36SAndroid Build Coastguard Worker	} else {
74*333d2b36SAndroid Build Coastguard Worker		fr = flate.NewReader(r)
75*333d2b36SAndroid Build Coastguard Worker	}
76*333d2b36SAndroid Build Coastguard Worker	return &pooledFlateReader{fr: fr}
77*333d2b36SAndroid Build Coastguard Worker}
78*333d2b36SAndroid Build Coastguard Worker
79*333d2b36SAndroid Build Coastguard Workertype pooledFlateReader struct {
80*333d2b36SAndroid Build Coastguard Worker	mu sync.Mutex // guards Close and Read
81*333d2b36SAndroid Build Coastguard Worker	fr io.ReadCloser
82*333d2b36SAndroid Build Coastguard Worker}
83*333d2b36SAndroid Build Coastguard Worker
84*333d2b36SAndroid Build Coastguard Workerfunc (r *pooledFlateReader) Read(p []byte) (n int, err error) {
85*333d2b36SAndroid Build Coastguard Worker	r.mu.Lock()
86*333d2b36SAndroid Build Coastguard Worker	defer r.mu.Unlock()
87*333d2b36SAndroid Build Coastguard Worker	if r.fr == nil {
88*333d2b36SAndroid Build Coastguard Worker		return 0, errors.New("Read after Close")
89*333d2b36SAndroid Build Coastguard Worker	}
90*333d2b36SAndroid Build Coastguard Worker	return r.fr.Read(p)
91*333d2b36SAndroid Build Coastguard Worker}
92*333d2b36SAndroid Build Coastguard Worker
93*333d2b36SAndroid Build Coastguard Workerfunc (r *pooledFlateReader) Close() error {
94*333d2b36SAndroid Build Coastguard Worker	r.mu.Lock()
95*333d2b36SAndroid Build Coastguard Worker	defer r.mu.Unlock()
96*333d2b36SAndroid Build Coastguard Worker	var err error
97*333d2b36SAndroid Build Coastguard Worker	if r.fr != nil {
98*333d2b36SAndroid Build Coastguard Worker		err = r.fr.Close()
99*333d2b36SAndroid Build Coastguard Worker		flateReaderPool.Put(r.fr)
100*333d2b36SAndroid Build Coastguard Worker		r.fr = nil
101*333d2b36SAndroid Build Coastguard Worker	}
102*333d2b36SAndroid Build Coastguard Worker	return err
103*333d2b36SAndroid Build Coastguard Worker}
104*333d2b36SAndroid Build Coastguard Worker
105*333d2b36SAndroid Build Coastguard Workervar (
106*333d2b36SAndroid Build Coastguard Worker	mu sync.RWMutex // guards compressor and decompressor maps
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Worker	compressors = map[uint16]Compressor{
109*333d2b36SAndroid Build Coastguard Worker		Store:   func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil },
110*333d2b36SAndroid Build Coastguard Worker		Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil },
111*333d2b36SAndroid Build Coastguard Worker	}
112*333d2b36SAndroid Build Coastguard Worker
113*333d2b36SAndroid Build Coastguard Worker	decompressors = map[uint16]Decompressor{
114*333d2b36SAndroid Build Coastguard Worker		Store:   ioutil.NopCloser,
115*333d2b36SAndroid Build Coastguard Worker		Deflate: newFlateReader,
116*333d2b36SAndroid Build Coastguard Worker	}
117*333d2b36SAndroid Build Coastguard Worker)
118*333d2b36SAndroid Build Coastguard Worker
119*333d2b36SAndroid Build Coastguard Worker// RegisterDecompressor allows custom decompressors for a specified method ID.
120*333d2b36SAndroid Build Coastguard Worker// The common methods Store and Deflate are built in.
121*333d2b36SAndroid Build Coastguard Workerfunc RegisterDecompressor(method uint16, dcomp Decompressor) {
122*333d2b36SAndroid Build Coastguard Worker	mu.Lock()
123*333d2b36SAndroid Build Coastguard Worker	defer mu.Unlock()
124*333d2b36SAndroid Build Coastguard Worker
125*333d2b36SAndroid Build Coastguard Worker	if _, ok := decompressors[method]; ok {
126*333d2b36SAndroid Build Coastguard Worker		panic("decompressor already registered")
127*333d2b36SAndroid Build Coastguard Worker	}
128*333d2b36SAndroid Build Coastguard Worker	decompressors[method] = dcomp
129*333d2b36SAndroid Build Coastguard Worker}
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Worker// RegisterCompressor registers custom compressors for a specified method ID.
132*333d2b36SAndroid Build Coastguard Worker// The common methods Store and Deflate are built in.
133*333d2b36SAndroid Build Coastguard Workerfunc RegisterCompressor(method uint16, comp Compressor) {
134*333d2b36SAndroid Build Coastguard Worker	mu.Lock()
135*333d2b36SAndroid Build Coastguard Worker	defer mu.Unlock()
136*333d2b36SAndroid Build Coastguard Worker
137*333d2b36SAndroid Build Coastguard Worker	if _, ok := compressors[method]; ok {
138*333d2b36SAndroid Build Coastguard Worker		panic("compressor already registered")
139*333d2b36SAndroid Build Coastguard Worker	}
140*333d2b36SAndroid Build Coastguard Worker	compressors[method] = comp
141*333d2b36SAndroid Build Coastguard Worker}
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Workerfunc compressor(method uint16) Compressor {
144*333d2b36SAndroid Build Coastguard Worker	mu.RLock()
145*333d2b36SAndroid Build Coastguard Worker	defer mu.RUnlock()
146*333d2b36SAndroid Build Coastguard Worker	return compressors[method]
147*333d2b36SAndroid Build Coastguard Worker}
148*333d2b36SAndroid Build Coastguard Worker
149*333d2b36SAndroid Build Coastguard Workerfunc decompressor(method uint16) Decompressor {
150*333d2b36SAndroid Build Coastguard Worker	mu.RLock()
151*333d2b36SAndroid Build Coastguard Worker	defer mu.RUnlock()
152*333d2b36SAndroid Build Coastguard Worker	return decompressors[method]
153*333d2b36SAndroid Build Coastguard Worker}
154