diff options
author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
commit | 7249ea4df2b4f12a4e7ed446f270cea87e4ffd34 (patch) | |
tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/compress/gzip/gunzip.go | |
parent | acf6ef7a82b3fe61516a1bac4563706552bdf078 (diff) | |
download | golang-7249ea4df2b4f12a4e7ed446f270cea87e4ffd34.tar.gz |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/compress/gzip/gunzip.go')
-rw-r--r-- | src/lib/compress/gzip/gunzip.go | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/src/lib/compress/gzip/gunzip.go b/src/lib/compress/gzip/gunzip.go deleted file mode 100644 index 32cc3ecb0..000000000 --- a/src/lib/compress/gzip/gunzip.go +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2009 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. - -// The gzip package implements reading (and eventually writing) of -// gzip format compressed files, as specified in RFC 1952. -package gzip - -import ( - "bufio"; - "compress/flate"; - "hash"; - "hash/crc32"; - "io"; - "os"; -) - -const ( - gzipID1 = 0x1f; - gzipID2 = 0x8b; - - gzipDeflate = 8; - - flagText = 1<<0; - flagHdrCrc = 1<<1; - flagExtra = 1<<2; - flagName = 1<<3; - flagComment = 1<<4; -) - -func makeReader(r io.Reader) flate.Reader { - if rr, ok := r.(flate.Reader); ok { - return rr; - } - return bufio.NewReader(r); -} - -var HeaderError os.Error = os.ErrorString("invalid gzip header") -var ChecksumError os.Error = os.ErrorString("gzip checksum error") - -// A GzipInflater is an io.Reader that can be read to retrieve -// uncompressed data from a gzip-format compressed file. -// The gzip file stores a header giving metadata about the compressed file. -// That header is exposed as the fields of the GzipInflater struct. -// -// In general, a gzip file can be a concatenation of gzip files, -// each with its own header. Reads from the GzipInflater -// return the concatenation of the uncompressed data of each. -// Only the first header is recorded in the GzipInflater fields. -// -// Gzip files store a length and checksum of the uncompressed data. -// The GzipInflater will return a ChecksumError when Read -// reaches the end of the uncompressed data if it does not -// have the expected length or checksum. Clients should treat data -// returned by Read as tentative until they receive the successful -// (zero length, nil error) Read marking the end of the data. -type GzipInflater struct { - Comment string; // comment - Extra []byte; // "extra data" - Mtime uint32; // modification time (seconds since January 1, 1970) - Name string; // file name - OS byte; // operating system type - - r flate.Reader; - inflater io.Reader; - digest hash.Hash32; - size uint32; - flg byte; - buf [512]byte; - err os.Error; - eof bool; -} - -func (z *GzipInflater) readHeader(save bool) os.Error - -// NewGzipInflater creates a new GzipInflater reading the given reader. -// The implementation buffers input and may read more data than necessary from r. -func NewGzipInflater(r io.Reader) (*GzipInflater, os.Error) { - z := new(GzipInflater); - z.r = makeReader(r); - z.digest = crc32.NewIEEE(); - if err := z.readHeader(true); err != nil { - z.err = err; - return nil, err; - } - return z, nil; -} - -func get4(p []byte) uint32 { - return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24; -} - -func (z *GzipInflater) readString() (string, os.Error) { - var err os.Error; - for i := 0;; i++ { - if i >= len(z.buf) { - return "", HeaderError; - } - z.buf[i], err = z.r.ReadByte(); - if err != nil { - return "", err; - } - if z.buf[i] == 0 { - return string(z.buf[0:i]), nil; - } - } - panic("not reached"); -} - -func (z *GzipInflater) read2() (uint32, os.Error) { - _, err := z.r.Read(z.buf[0:2]); - if err != nil { - return 0, err; - } - return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil; -} - -func (z *GzipInflater) readHeader(save bool) os.Error { - n, err := io.FullRead(z.r, z.buf[0:10]); - if err != nil { - if n != 0 && err == io.ErrEOF { - return HeaderError; - } - return err; - } - if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate { - return HeaderError; - } - z.flg = z.buf[3]; - if save { - z.Mtime = get4(z.buf[4:8]); - // z.buf[8] is xfl, ignored - z.OS = z.buf[9]; - } - z.digest.Reset(); - z.digest.Write(z.buf[0:10]); - - if z.flg & flagExtra != 0{ - n, err := z.read2(); - if err != nil { - return err; - } - data := make([]byte, n); - var nn int; - if nn, err = io.FullRead(z.r, data); err != nil { - return err; - } - if save { - z.Extra = data; - } - } - - var s string; - if z.flg & flagName != 0 { - if s, err = z.readString(); err != nil { - return err; - } - if save { - z.Name = s; - } - } - - if z.flg & flagComment != 0 { - if s, err = z.readString(); err != nil { - return err; - } - if save { - z.Comment = s; - } - } - - if z.flg & flagHdrCrc != 0 { - n, err := z.read2(); - if err != nil { - return err; - } - sum := z.digest.Sum32() & 0xFFFF; - if n != sum { - return HeaderError; - } - } - - z.digest.Reset(); - z.inflater = flate.NewInflater(z.r); - return nil; -} - -func (z *GzipInflater) Read(p []byte) (n int, err os.Error) { - if z.err != nil { - return 0, z.err; - } - if z.eof || len(p) == 0 { - return 0, nil; - } - - n, err = z.inflater.Read(p); - z.digest.Write(p[0:n]); - z.size += uint32(n); - if n != 0 || err != nil { - z.err = err; - return; - } - - // Finished file; check checksum + size. - if _, err := io.FullRead(z.r, z.buf[0:8]); err != nil { - z.err = err; - return 0, err; - } - if err != nil { - z.err = err; - return 0, err; - } - crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8]); - sum := z.digest.Sum32(); - if sum != crc32 || isize != z.size { - z.err = ChecksumError; - return 0, z.err; - } - - // File is ok; is there another? - switch err = z.readHeader(false); { - case err == io.ErrEOF: - err = nil; - z.eof = true; - return; - case err != nil: - z.err = err; - return; - } - - // Yes. Reset and read from it. - z.digest.Reset(); - z.size = 0; - return z.Read(p); -} - |