diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-09-14 17:11:35 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-09-14 17:11:35 +0000 |
commit | e104cab8d4ab9422a0ca55bb24c00c9fea9a5d4d (patch) | |
tree | 8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/go/archive/zip | |
parent | 4a85c0b16ef3722655012f596b7e3e7e272eeb56 (diff) | |
download | gcc-e104cab8d4ab9422a0ca55bb24c00c9fea9a5d4d.tar.gz |
libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252767 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/archive/zip')
-rw-r--r-- | libgo/go/archive/zip/register.go | 47 | ||||
-rw-r--r-- | libgo/go/archive/zip/struct.go | 2 | ||||
-rw-r--r-- | libgo/go/archive/zip/writer.go | 21 | ||||
-rw-r--r-- | libgo/go/archive/zip/writer_test.go | 90 | ||||
-rw-r--r-- | libgo/go/archive/zip/zip_test.go | 14 |
5 files changed, 134 insertions, 40 deletions
diff --git a/libgo/go/archive/zip/register.go b/libgo/go/archive/zip/register.go index 2e76386b1fd..51e9c3e4d4b 100644 --- a/libgo/go/archive/zip/register.go +++ b/libgo/go/archive/zip/register.go @@ -103,51 +103,46 @@ func (r *pooledFlateReader) Close() error { } var ( - mu sync.RWMutex // guards compressor and decompressor maps + compressors sync.Map // map[uint16]Compressor + decompressors sync.Map // map[uint16]Decompressor +) - compressors = map[uint16]Compressor{ - Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }, - Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }, - } +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 = map[uint16]Decompressor{ - Store: ioutil.NopCloser, - Deflate: newFlateReader, - } -) + 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) { - mu.Lock() - defer mu.Unlock() - - if _, ok := decompressors[method]; ok { + if _, dup := decompressors.LoadOrStore(method, dcomp); dup { panic("decompressor already registered") } - decompressors[method] = dcomp } // RegisterCompressor registers custom compressors for a specified method ID. // The common methods Store and Deflate are built in. func RegisterCompressor(method uint16, comp Compressor) { - mu.Lock() - defer mu.Unlock() - - if _, ok := compressors[method]; ok { + if _, dup := compressors.LoadOrStore(method, comp); dup { panic("compressor already registered") } - compressors[method] = comp } func compressor(method uint16) Compressor { - mu.RLock() - defer mu.RUnlock() - return compressors[method] + ci, ok := compressors.Load(method) + if !ok { + return nil + } + return ci.(Compressor) } func decompressor(method uint16) Decompressor { - mu.RLock() - defer mu.RUnlock() - return decompressors[method] + di, ok := decompressors.Load(method) + if !ok { + return nil + } + return di.(Decompressor) } diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go index e92d02f8a2e..0be210e8e73 100644 --- a/libgo/go/archive/zip/struct.go +++ b/libgo/go/archive/zip/struct.go @@ -5,7 +5,7 @@ /* Package zip provides support for reading and writing ZIP archives. -See: https://www.pkware.com/documents/casestudies/APPNOTE.TXT +See: https://www.pkware.com/appnote This package does not support disk spanning. diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go index 8940e25560e..9f4fceee844 100644 --- a/libgo/go/archive/zip/writer.go +++ b/libgo/go/archive/zip/writer.go @@ -11,10 +11,9 @@ import ( "hash" "hash/crc32" "io" + "unicode/utf8" ) -// TODO(adg): support zip file comments - // Writer implements a zip file writer. type Writer struct { cw *countWriter @@ -201,6 +200,20 @@ func (w *Writer) Create(name string) (io.Writer, error) { return w.CreateHeader(header) } +func hasValidUTF8(s string) bool { + n := 0 + for _, r := range s { + // By default, ZIP uses CP437, which is only identical to ASCII for the printable characters. + if r < 0x20 || r >= 0x7f { + if !utf8.ValidRune(r) { + return false + } + n++ + } + } + return n > 0 +} + // CreateHeader adds a file to the zip file using the provided FileHeader // for the file metadata. // It returns a Writer to which the file contents should be written. @@ -221,6 +234,10 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { fh.Flags |= 0x8 // we will write a data descriptor + if hasValidUTF8(fh.Name) || hasValidUTF8(fh.Comment) { + fh.Flags |= 0x800 // filename or comment have valid utf-8 string + } + fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte fh.ReaderVersion = zipVersion20 diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index 86841c755f1..92fb6ecf0ed 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -87,6 +87,69 @@ func TestWriter(t *testing.T) { } } +func TestWriterUTF8(t *testing.T) { + var utf8Tests = []struct { + name string + comment string + expect uint16 + }{ + { + name: "hi, hello", + comment: "in the world", + expect: 0x8, + }, + { + name: "hi, こんにちわ", + comment: "in the world", + expect: 0x808, + }, + { + name: "hi, hello", + comment: "in the 世界", + expect: 0x808, + }, + { + name: "hi, こんにちわ", + comment: "in the 世界", + expect: 0x808, + }, + } + + // write a zip file + buf := new(bytes.Buffer) + w := NewWriter(buf) + + for _, test := range utf8Tests { + h := &FileHeader{ + Name: test.name, + Comment: test.comment, + Method: Deflate, + } + w, err := w.CreateHeader(h) + if err != nil { + t.Fatal(err) + } + w.Write([]byte{}) + } + + if err := w.Close(); err != nil { + t.Fatal(err) + } + + // read it back + r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) + if err != nil { + t.Fatal(err) + } + for i, test := range utf8Tests { + got := r.File[i].Flags + t.Logf("name %v, comment %v", test.name, test.comment) + if got != test.expect { + t.Fatalf("Flags: got %v, want %v", got, test.expect) + } + } +} + func TestWriterOffset(t *testing.T) { largeData := make([]byte, 1<<17) for i := range largeData { @@ -181,12 +244,11 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) { } func BenchmarkCompressedZipGarbage(b *testing.B) { - b.ReportAllocs() - var buf bytes.Buffer bigBuf := bytes.Repeat([]byte("a"), 1<<20) - for i := 0; i <= b.N; i++ { + + runOnce := func(buf *bytes.Buffer) { buf.Reset() - zw := NewWriter(&buf) + zw := NewWriter(buf) for j := 0; j < 3; j++ { w, _ := zw.CreateHeader(&FileHeader{ Name: "foo", @@ -195,11 +257,19 @@ func BenchmarkCompressedZipGarbage(b *testing.B) { w.Write(bigBuf) } zw.Close() - if i == 0 { - // Reset the timer after the first time through. - // This effectively discards the very large initial flate setup cost, - // as well as the initialization of bigBuf. - b.ResetTimer() - } } + + b.ReportAllocs() + // Run once and then reset the timer. + // This effectively discards the very large initial flate setup cost, + // as well as the initialization of bigBuf. + runOnce(&bytes.Buffer{}) + b.ResetTimer() + + b.RunParallel(func(pb *testing.PB) { + var buf bytes.Buffer + for pb.Next() { + runOnce(&buf) + } + }) } diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go index 57edb2cabf4..18c2171ba6c 100644 --- a/libgo/go/archive/zip/zip_test.go +++ b/libgo/go/archive/zip/zip_test.go @@ -255,7 +255,7 @@ func TestZip64EdgeCase(t *testing.T) { testZip64DirectoryRecordLength(buf, t) } -// Tests that we generate a zip64 file if the the directory at offset +// Tests that we generate a zip64 file if the directory at offset // 0xFFFFFFFF, but not before. func TestZip64DirectoryOffset(t *testing.T) { if testing.Short() && race.Enabled { @@ -681,6 +681,18 @@ func BenchmarkZip64Test(b *testing.B) { } } +func BenchmarkZip64TestSizes(b *testing.B) { + for _, size := range []int64{1 << 12, 1 << 20, 1 << 26} { + b.Run(fmt.Sprint(size), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + testZip64(b, size) + } + }) + }) + } +} + func TestSuffixSaver(t *testing.T) { const keep = 10 ss := &suffixSaver{keep: keep} |