OSDN Git Service

Update Go compiler, library, and testsuite on gcc 4.7 branch.
[pf3gnuchains/gcc-fork.git] / libgo / go / compress / gzip / gzip.go
index 8860d10..3035dff 100644 (file)
@@ -6,10 +6,11 @@ package gzip
 
 import (
        "compress/flate"
+       "errors"
+       "fmt"
        "hash"
        "hash/crc32"
        "io"
-       "os"
 )
 
 // These constants are copied from the flate package, so that code that imports
@@ -21,9 +22,9 @@ const (
        DefaultCompression = flate.DefaultCompression
 )
 
-// A Compressor is an io.WriteCloser that satisfies writes by compressing data written
+// A Writer is an io.WriteCloser that satisfies writes by compressing data written
 // to its wrapped io.Writer.
-type Compressor struct {
+type Writer struct {
        Header
        w          io.Writer
        level      int
@@ -32,28 +33,43 @@ type Compressor struct {
        size       uint32
        closed     bool
        buf        [10]byte
-       err        os.Error
+       err        error
 }
 
-// NewWriter calls NewWriterLevel with the default compression level.
-func NewWriter(w io.Writer) (*Compressor, os.Error) {
-       return NewWriterLevel(w, DefaultCompression)
+// NewWriter creates a new Writer that satisfies writes by compressing data
+// written to w.
+//
+// It is the caller's responsibility to call Close on the WriteCloser when done.
+// Writes may be buffered and not flushed until Close.
+//
+// Callers that wish to set the fields in Writer.Header must do so before
+// the first call to Write or Close. The Comment and Name header fields are
+// UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
+// 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
+// error on Write.
+func NewWriter(w io.Writer) *Writer {
+       z, _ := NewWriterLevel(w, DefaultCompression)
+       return z
 }
 
-// NewWriterLevel creates a new Compressor writing to the given writer.
-// Writes may be buffered and not flushed until Close.
-// Callers that wish to set the fields in Compressor.Header must
-// do so before the first call to Write or Close.
-// It is the caller's responsibility to call Close on the WriteCloser when done.
-// level is the compression level, which can be DefaultCompression, NoCompression,
-// or any integer value between BestSpeed and BestCompression (inclusive).
-func NewWriterLevel(w io.Writer, level int) (*Compressor, os.Error) {
-       z := new(Compressor)
-       z.OS = 255 // unknown
-       z.w = w
-       z.level = level
-       z.digest = crc32.NewIEEE()
-       return z, nil
+// NewWriterLevel is like NewWriter but specifies the compression level instead
+// of assuming DefaultCompression.
+//
+// The compression level can be DefaultCompression, NoCompression, or any
+// integer value between BestSpeed and BestCompression inclusive. The error
+// returned will be nil if the level is valid.
+func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
+       if level < DefaultCompression || level > BestCompression {
+               return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
+       }
+       return &Writer{
+               Header: Header{
+                       OS: 255, // unknown
+               },
+               w:      w,
+               level:  level,
+               digest: crc32.NewIEEE(),
+       }, nil
 }
 
 // GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
@@ -70,9 +86,9 @@ func put4(p []byte, v uint32) {
 }
 
 // writeBytes writes a length-prefixed byte slice to z.w.
-func (z *Compressor) writeBytes(b []byte) os.Error {
+func (z *Writer) writeBytes(b []byte) error {
        if len(b) > 0xffff {
-               return os.NewError("gzip.Write: Extra data is too large")
+               return errors.New("gzip.Write: Extra data is too large")
        }
        put2(z.buf[0:2], uint16(len(b)))
        _, err := z.w.Write(z.buf[0:2])
@@ -83,16 +99,28 @@ func (z *Compressor) writeBytes(b []byte) os.Error {
        return err
 }
 
-// writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w.
-func (z *Compressor) writeString(s string) os.Error {
-       // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
-       // TODO(nigeltao): Convert from UTF-8 to ISO 8859-1 (Latin-1).
+// writeString writes a UTF-8 string s in GZIP's format to z.w.
+// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
+func (z *Writer) writeString(s string) (err error) {
+       // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
+       needconv := false
        for _, v := range s {
-               if v == 0 || v > 0x7f {
-                       return os.NewError("gzip.Write: non-ASCII header string")
+               if v == 0 || v > 0xff {
+                       return errors.New("gzip.Write: non-Latin-1 header string")
+               }
+               if v > 0x7f {
+                       needconv = true
+               }
+       }
+       if needconv {
+               b := make([]byte, 0, len(s))
+               for _, v := range s {
+                       b = append(b, byte(v))
                }
+               _, err = z.w.Write(b)
+       } else {
+               _, err = io.WriteString(z.w, s)
        }
-       _, err := io.WriteString(z.w, s)
        if err != nil {
                return err
        }
@@ -102,7 +130,9 @@ func (z *Compressor) writeString(s string) os.Error {
        return err
 }
 
-func (z *Compressor) Write(p []byte) (int, os.Error) {
+// Write writes a compressed form of p to the underlying io.Writer. The
+// compressed bytes are not necessarily flushed until the Writer is closed.
+func (z *Writer) Write(p []byte) (int, error) {
        if z.err != nil {
                return 0, z.err
        }
@@ -122,7 +152,7 @@ func (z *Compressor) Write(p []byte) (int, os.Error) {
                if z.Comment != "" {
                        z.buf[3] |= 0x10
                }
-               put4(z.buf[4:8], z.Mtime)
+               put4(z.buf[4:8], uint32(z.ModTime.Unix()))
                if z.level == BestCompression {
                        z.buf[8] = 2
                } else if z.level == BestSpeed {
@@ -153,7 +183,7 @@ func (z *Compressor) Write(p []byte) (int, os.Error) {
                                return n, z.err
                        }
                }
-               z.compressor = flate.NewWriter(z.w, z.level)
+               z.compressor, _ = flate.NewWriter(z.w, z.level)
        }
        z.size += uint32(len(p))
        z.digest.Write(p)
@@ -161,8 +191,8 @@ func (z *Compressor) Write(p []byte) (int, os.Error) {
        return n, z.err
 }
 
-// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
-func (z *Compressor) Close() os.Error {
+// Close closes the Writer. It does not close the underlying io.Writer.
+func (z *Writer) Close() error {
        if z.err != nil {
                return z.err
        }