aboutsummaryrefslogtreecommitdiffstats
path: root/formats/packfile/scanner.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-10-31 14:56:38 +0000
committerGitHub <noreply@github.com>2016-10-31 14:56:38 +0000
commit659386309f36c482ddc0bb9e854ebda3da216491 (patch)
treeeb156bfbfad599f3dd88e184a7f690f67c64337d /formats/packfile/scanner.go
parent5944d8a185ff1f91e0e108dab1d756fd88692c3b (diff)
downloadgo-git-659386309f36c482ddc0bb9e854ebda3da216491.tar.gz
utils: binary, new package that collect all the spare helper functions about binary operations (#102)
Diffstat (limited to 'formats/packfile/scanner.go')
-rw-r--r--formats/packfile/scanner.go126
1 files changed, 23 insertions, 103 deletions
diff --git a/formats/packfile/scanner.go b/formats/packfile/scanner.go
index a5e4215..69cc7d0 100644
--- a/formats/packfile/scanner.go
+++ b/formats/packfile/scanner.go
@@ -4,7 +4,6 @@ import (
"bufio"
"bytes"
"compress/zlib"
- "encoding/binary"
"fmt"
"hash"
"hash/crc32"
@@ -12,6 +11,7 @@ import (
"io/ioutil"
"gopkg.in/src-d/go-git.v4/core"
+ "gopkg.in/src-d/go-git.v4/utils/binary"
)
var (
@@ -129,7 +129,7 @@ func (s *Scanner) isValidSignature(sig []byte) bool {
// readVersion reads and returns the version field of a packfile.
func (s *Scanner) readVersion() (uint32, error) {
- return s.readInt32()
+ return binary.ReadUint32(s.r)
}
// isSupportedVersion returns whether version v is supported by the parser.
@@ -140,17 +140,7 @@ func (s *Scanner) isSupportedVersion(v uint32) bool {
// readCount reads and returns the count of objects field of a packfile.
func (s *Scanner) readCount() (uint32, error) {
- return s.readInt32()
-}
-
-// ReadInt32 reads 4 bytes and returns them as a Big Endian int32.
-func (s *Scanner) readInt32() (uint32, error) {
- var v uint32
- if err := binary.Read(s.r, binary.BigEndian, &v); err != nil {
- return 0, err
- }
-
- return v, nil
+ return binary.ReadUint32(s.r)
}
// NextObjectHeader returns the ObjectHeader for the next object in the reader
@@ -177,15 +167,15 @@ func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) {
switch h.Type {
case core.OFSDeltaObject:
- no, err := s.readNegativeOffset()
+ no, err := binary.ReadVariableWidthInt(s.r)
if err != nil {
return nil, err
}
- h.OffsetReference = h.Offset + no
+ h.OffsetReference = h.Offset - no
case core.REFDeltaObject:
var err error
- h.Reference, err = s.readHash()
+ h.Reference, err = binary.ReadHash(s.r)
if err != nil {
return nil, err
}
@@ -240,10 +230,19 @@ func (s *Scanner) readObjectTypeAndLength() (core.ObjectType, int64, error) {
return t, l, err
}
+const (
+ maskType = uint8(112) // 0111 0000
+ maskFirstLength = uint8(15) // 0000 1111
+ maskContinue = uint8(128) // 1000 000
+ firstLengthBits = uint8(4) // the first byte has 4 bits to store the length
+ maskLength = uint8(127) // 0111 1111
+ lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
+)
+
func (s *Scanner) readType() (core.ObjectType, byte, error) {
var c byte
var err error
- if c, err = s.readByte(); err != nil {
+ if c, err = s.r.ReadByte(); err != nil {
return core.ObjectType(0), 0, err
}
@@ -252,6 +251,10 @@ func (s *Scanner) readType() (core.ObjectType, byte, error) {
return typ, c, nil
}
+func parseType(b byte) core.ObjectType {
+ return core.ObjectType((b & maskType) >> firstLengthBits)
+}
+
// the length is codified in the last 4 bits of the first byte and in
// the last 7 bits of subsequent bytes. Last byte has a 0 MSB.
func (s *Scanner) readLength(first byte) (int64, error) {
@@ -260,8 +263,8 @@ func (s *Scanner) readLength(first byte) (int64, error) {
c := first
shift := firstLengthBits
var err error
- for moreBytesInLength(c) {
- if c, err = s.readByte(); err != nil {
+ for c&maskContinue > 0 {
+ if c, err = s.r.ReadByte(); err != nil {
return 0, err
}
@@ -324,73 +327,7 @@ func (s *Scanner) Checksum() (core.Hash, error) {
return core.ZeroHash, err
}
- return s.readHash()
-}
-
-// ReadHash reads a hash.
-func (s *Scanner) readHash() (core.Hash, error) {
- var h core.Hash
- if _, err := io.ReadFull(s.r, h[:]); err != nil {
- return core.ZeroHash, err
- }
-
- return h, nil
-}
-
-// ReadNegativeOffset reads and returns an offset from a OFS DELTA
-// object entry in a packfile. OFS DELTA offsets are specified in Git
-// VLQ special format:
-//
-// Ordinary VLQ has some redundancies, example: the number 358 can be
-// encoded as the 2-octet VLQ 0x8166 or the 3-octet VLQ 0x808166 or the
-// 4-octet VLQ 0x80808166 and so forth.
-//
-// To avoid these redundancies, the VLQ format used in Git removes this
-// prepending redundancy and extends the representable range of shorter
-// VLQs by adding an offset to VLQs of 2 or more octets in such a way
-// that the lowest possible value for such an (N+1)-octet VLQ becomes
-// exactly one more than the maximum possible value for an N-octet VLQ.
-// In particular, since a 1-octet VLQ can store a maximum value of 127,
-// the minimum 2-octet VLQ (0x8000) is assigned the value 128 instead of
-// 0. Conversely, the maximum value of such a 2-octet VLQ (0xff7f) is
-// 16511 instead of just 16383. Similarly, the minimum 3-octet VLQ
-// (0x808000) has a value of 16512 instead of zero, which means
-// that the maximum 3-octet VLQ (0xffff7f) is 2113663 instead of
-// just 2097151. And so forth.
-//
-// This is how the offset is saved in C:
-//
-// dheader[pos] = ofs & 127;
-// while (ofs >>= 7)
-// dheader[--pos] = 128 | (--ofs & 127);
-//
-func (s *Scanner) readNegativeOffset() (int64, error) {
- var c byte
- var err error
-
- if c, err = s.readByte(); err != nil {
- return 0, err
- }
-
- var offset = int64(c & maskLength)
- for moreBytesInLength(c) {
- offset++
- if c, err = s.readByte(); err != nil {
- return 0, err
- }
- offset = (offset << lengthBits) + int64(c&maskLength)
- }
-
- return -offset, nil
-}
-
-func (s *Scanner) readByte() (byte, error) {
- b, err := s.r.ReadByte()
- if err != nil {
- return 0, err
- }
-
- return b, err
+ return binary.ReadHash(s.r)
}
// Close reads the reader until io.EOF
@@ -399,23 +336,6 @@ func (s *Scanner) Close() error {
return err
}
-func moreBytesInLength(c byte) bool {
- return c&maskContinue > 0
-}
-
-var (
- maskContinue = uint8(128) // 1000 0000
- maskType = uint8(112) // 0111 0000
- maskFirstLength = uint8(15) // 0000 1111
- firstLengthBits = uint8(4) // the first byte has 4 bits to store the length
- maskLength = uint8(127) // 0111 1111
- lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
-)
-
-func parseType(b byte) core.ObjectType {
- return core.ObjectType((b & maskType) >> firstLengthBits)
-}
-
type trackableReader struct {
count int64
io.Reader