1
0
mirror of https://github.com/golang/go synced 2024-11-22 11:04:40 -07:00

archive/zip: use smarter putUintXX functions to hide offsets

R=bradfitz, r, dsymonds, kyle
CC=golang-dev
https://golang.org/cl/5701055
This commit is contained in:
Andrew Gerrand 2012-02-27 17:37:59 +11:00
parent 228f44a1f5
commit eb825b58cc
2 changed files with 63 additions and 56 deletions

View File

@ -165,7 +165,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment)
}
if len(z.File) != len(zt.File) {
t.Errorf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File))
t.Fatalf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File))
}
// test read of each file

View File

@ -51,24 +51,25 @@ func (w *Writer) Close() error {
// write central directory
start := w.cw.count
for _, h := range w.dir {
var b [directoryHeaderLen]byte
putUint32(b[:], uint32(directoryHeaderSignature))
putUint16(b[4:], h.CreatorVersion)
putUint16(b[6:], h.ReaderVersion)
putUint16(b[8:], h.Flags)
putUint16(b[10:], h.Method)
putUint16(b[12:], h.ModifiedTime)
putUint16(b[14:], h.ModifiedDate)
putUint32(b[16:], h.CRC32)
putUint32(b[20:], h.CompressedSize)
putUint32(b[24:], h.UncompressedSize)
putUint16(b[28:], uint16(len(h.Name)))
putUint16(b[30:], uint16(len(h.Extra)))
putUint16(b[32:], uint16(len(h.Comment)))
// skip two uint16's, disk number start and internal file attributes
putUint32(b[38:], h.ExternalAttrs)
putUint32(b[42:], h.offset)
if _, err := w.cw.Write(b[:]); err != nil {
var buf [directoryHeaderLen]byte
b := writeBuf(buf[:])
b.uint32(uint32(directoryHeaderSignature))
b.uint16(h.CreatorVersion)
b.uint16(h.ReaderVersion)
b.uint16(h.Flags)
b.uint16(h.Method)
b.uint16(h.ModifiedTime)
b.uint16(h.ModifiedDate)
b.uint32(h.CRC32)
b.uint32(h.CompressedSize)
b.uint32(h.UncompressedSize)
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
b.uint16(uint16(len(h.Comment)))
b = b[4:] // skip disk number start and internal file attr (2x uint16)
b.uint32(h.ExternalAttrs)
b.uint32(h.offset)
if _, err := w.cw.Write(buf[:]); err != nil {
return err
}
if _, err := io.WriteString(w.cw, h.Name); err != nil {
@ -84,16 +85,16 @@ func (w *Writer) Close() error {
end := w.cw.count
// write end record
var b [directoryEndLen]byte
putUint32(b[:], uint32(directoryEndSignature))
putUint16(b[4:], uint16(0)) // disk number
putUint16(b[6:], uint16(0)) // disk number where directory starts
putUint16(b[8:], uint16(len(w.dir))) // number of entries this disk
putUint16(b[10:], uint16(len(w.dir))) // number of entries total
putUint32(b[12:], uint32(end-start)) // size of directory
putUint32(b[16:], uint32(start)) // start of directory
var buf [directoryEndLen]byte
b := writeBuf(buf[:])
b.uint32(uint32(directoryEndSignature))
b = b[4:] // skip over disk number and first disk number (2x uint16)
b.uint16(uint16(len(w.dir))) // number of entries this disk
b.uint16(uint16(len(w.dir))) // number of entries total
b.uint32(uint32(end - start)) // size of directory
b.uint32(uint32(start)) // start of directory
// skipped size of comment (always zero)
if _, err := w.cw.Write(b[:]); err != nil {
if _, err := w.cw.Write(buf[:]); err != nil {
return err
}
@ -163,19 +164,20 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
}
func writeHeader(w io.Writer, h *FileHeader) error {
var b [fileHeaderLen]byte
putUint32(b[:], uint32(fileHeaderSignature))
putUint16(b[4:], h.ReaderVersion)
putUint16(b[6:], h.Flags)
putUint16(b[8:], h.Method)
putUint16(b[10:], h.ModifiedTime)
putUint16(b[12:], h.ModifiedDate)
putUint32(b[14:], h.CRC32)
putUint32(b[18:], h.CompressedSize)
putUint32(b[22:], h.UncompressedSize)
putUint16(b[26:], uint16(len(h.Name)))
putUint16(b[28:], uint16(len(h.Extra)))
if _, err := w.Write(b[:]); err != nil {
var buf [fileHeaderLen]byte
b := writeBuf(buf[:])
b.uint32(uint32(fileHeaderSignature))
b.uint16(h.ReaderVersion)
b.uint16(h.Flags)
b.uint16(h.Method)
b.uint16(h.ModifiedTime)
b.uint16(h.ModifiedDate)
b.uint32(h.CRC32)
b.uint32(h.CompressedSize)
b.uint32(h.UncompressedSize)
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
if _, err := w.Write(buf[:]); err != nil {
return err
}
if _, err := io.WriteString(w, h.Name); err != nil {
@ -219,11 +221,12 @@ func (w *fileWriter) close() error {
fh.UncompressedSize = uint32(w.rawCount.count)
// write data descriptor
var b [dataDescriptorLen]byte
putUint32(b[:], fh.CRC32)
putUint32(b[4:], fh.CompressedSize)
putUint32(b[8:], fh.UncompressedSize)
_, err := w.zipw.Write(b[:])
var buf [dataDescriptorLen]byte
b := writeBuf(buf[:])
b.uint32(fh.CRC32)
b.uint32(fh.CompressedSize)
b.uint32(fh.UncompressedSize)
_, err := w.zipw.Write(buf[:])
return err
}
@ -246,17 +249,21 @@ func (w nopCloser) Close() error {
return nil
}
// We use these putUintXX functions instead of encoding/binary's Write to avoid
// reflection. It's easy enough, anyway.
// We use this helper instead of encoding/binary's Write to avoid reflection.
// It's easy enough, anyway.
func putUint16(b []byte, v uint16) {
b[0] = byte(v)
b[1] = byte(v >> 8)
type writeBuf []byte
func (b *writeBuf) uint16(v uint16) {
(*b)[0] = byte(v)
(*b)[1] = byte(v >> 8)
*b = (*b)[2:]
}
func putUint32(b []byte, v uint32) {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
func (b *writeBuf) uint32(v uint32) {
(*b)[0] = byte(v)
(*b)[1] = byte(v >> 8)
(*b)[2] = byte(v >> 16)
(*b)[3] = byte(v >> 24)
*b = (*b)[4:]
}