Reduce use of binary.Read and, by extention, reflection

This commit is contained in:
Caleb Gardner
2025-04-10 06:26:41 -05:00
parent 4490fc3873
commit 6b0e9ef2c6
8 changed files with 75 additions and 36 deletions
+4 -3
View File
@@ -23,14 +23,15 @@ func NewReader(r io.Reader, d decompress.Decompressor) *Reader {
func (r *Reader) advance() error { func (r *Reader) advance() error {
r.curOffset = 0 r.curOffset = 0
var size uint16 dat := make([]byte, 2)
err := binary.Read(r.r, binary.LittleEndian, &size) _, err := r.r.Read(dat)
if err != nil { if err != nil {
return err return err
} }
size := binary.LittleEndian.Uint16(dat)
realSize := size &^ 0x8000 realSize := size &^ 0x8000
r.dat = make([]byte, realSize) r.dat = make([]byte, realSize)
err = binary.Read(r.r, binary.LittleEndian, &r.dat) _, err = r.r.Read(r.dat)
if err != nil { if err != nil {
return err return err
} }
+1 -3
View File
@@ -1,7 +1,6 @@
package data package data
import ( import (
"encoding/binary"
"errors" "errors"
"io" "io"
"io/fs" "io/fs"
@@ -10,7 +9,6 @@ import (
"sync" "sync"
"github.com/CalebQ42/squashfs/internal/decompress" "github.com/CalebQ42/squashfs/internal/decompress"
"github.com/CalebQ42/squashfs/internal/toreader"
) )
type FragReaderConstructor func() (io.Reader, error) type FragReaderConstructor func() (io.Reader, error)
@@ -80,7 +78,7 @@ func (r FullReader) process(index uint64, fileOffset uint64, pool *sync.Pool, re
return return
} }
ret.data = make([]byte, realSize) ret.data = make([]byte, realSize)
ret.err = binary.Read(toreader.NewReader(r.r, int64(r.initialOffset)+int64(fileOffset)), binary.LittleEndian, &ret.data) _, ret.err = r.r.ReadAt(ret.data, r.initialOffset+int64(fileOffset))
if r.sizes[index] == realSize { if r.sizes[index] == realSize {
ret.data, ret.err = r.d.Decompress(ret.data) ret.data, ret.err = r.d.Decompress(ret.data)
} }
+1 -2
View File
@@ -1,7 +1,6 @@
package data package data
import ( import (
"encoding/binary"
"io" "io"
"io/fs" "io/fs"
@@ -56,7 +55,7 @@ func (r *Reader) advance() error {
return nil return nil
} }
r.dat = make([]byte, realSize) r.dat = make([]byte, realSize)
err = binary.Read(r.r, binary.LittleEndian, &r.dat) _, err = r.r.Read(r.dat)
if err != nil { if err != nil {
return err return err
} }
+2 -2
View File
@@ -130,7 +130,7 @@ func (b FileBase) GetRegFileReaders(r Reader) (data.Reader, data.FullReader, err
return outRdr, outFull, nil return outRdr, outFull, nil
} }
func (b *FileBase) GetFullReader(r *Reader) (data.FullReader, error) { func (b FileBase) GetFullReader(r *Reader) (data.FullReader, error) {
if !b.IsRegular() { if !b.IsRegular() {
return data.FullReader{}, errors.New("not a regular file") return data.FullReader{}, errors.New("not a regular file")
} }
@@ -167,7 +167,7 @@ func (b *FileBase) GetFullReader(r *Reader) (data.FullReader, error) {
return outFull, nil return outFull, nil
} }
func (b *FileBase) GetReader(r *Reader) (data.Reader, error) { func (b FileBase) GetReader(r *Reader) (data.Reader, error) {
if !b.IsRegular() { if !b.IsRegular() {
return data.Reader{}, errors.New("not a regular file") return data.Reader{}, errors.New("not a regular file")
} }
+28 -15
View File
@@ -13,7 +13,7 @@ type Directory struct {
ParentNum uint32 ParentNum uint32
} }
type eDirectoryInit struct { type EDirectory struct {
LinkCount uint32 LinkCount uint32
Size uint32 Size uint32
BlockStart uint32 BlockStart uint32
@@ -21,42 +21,55 @@ type eDirectoryInit struct {
IndCount uint16 IndCount uint16
Offset uint16 Offset uint16
XattrInd uint32 XattrInd uint32
}
type EDirectory struct {
eDirectoryInit
Indexes []DirectoryIndex Indexes []DirectoryIndex
} }
type directoryIndexInit struct { type DirectoryIndex struct {
Ind uint32 Ind uint32
Start uint32 Start uint32
NameSize uint32 NameSize uint32
}
type DirectoryIndex struct {
directoryIndexInit
Name []byte Name []byte
} }
func ReadDir(r io.Reader) (d Directory, err error) { func ReadDir(r io.Reader) (d Directory, err error) {
err = binary.Read(r, binary.LittleEndian, &d) dat := make([]byte, 16)
_, err = r.Read(dat)
if err != nil {
return
}
d.BlockStart = binary.LittleEndian.Uint32(dat)
d.LinkCount = binary.LittleEndian.Uint32(dat[4:])
d.Size = binary.LittleEndian.Uint16(dat[8:])
d.Offset = binary.LittleEndian.Uint16(dat[10:])
d.ParentNum = binary.LittleEndian.Uint32(dat[12:])
return return
} }
func ReadEDir(r io.Reader) (d EDirectory, err error) { func ReadEDir(r io.Reader) (d EDirectory, err error) {
err = binary.Read(r, binary.LittleEndian, &d.eDirectoryInit) dat := make([]byte, 24)
_, err = r.Read(dat)
if err != nil { if err != nil {
return return
} }
d.LinkCount = binary.LittleEndian.Uint32(dat)
d.Size = binary.LittleEndian.Uint32(dat[4:])
d.BlockStart = binary.LittleEndian.Uint32(dat[8:])
d.ParentNum = binary.LittleEndian.Uint32(dat[12:])
d.IndCount = binary.LittleEndian.Uint16(dat[16:])
d.Offset = binary.LittleEndian.Uint16(dat[18:])
d.XattrInd = binary.LittleEndian.Uint32(dat[20:])
d.Indexes = make([]DirectoryIndex, d.IndCount) d.Indexes = make([]DirectoryIndex, d.IndCount)
for i := range d.Indexes { for i := range d.IndCount {
err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].directoryIndexInit) dat = make([]byte, 12)
_, err = r.Read(dat)
if err != nil { if err != nil {
return return
} }
d.Indexes[i].Ind = binary.LittleEndian.Uint32(dat)
d.Indexes[i].Start = binary.LittleEndian.Uint32(dat[4:])
d.Indexes[i].NameSize = binary.LittleEndian.Uint32(dat[8:])
d.Indexes[i].Name = make([]byte, d.Indexes[i].NameSize+1) d.Indexes[i].Name = make([]byte, d.Indexes[i].NameSize+1)
err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].Name) _, err = r.Read(d.Indexes[i].Name)
if err != nil { if err != nil {
return return
} }
+15 -7
View File
@@ -6,15 +6,11 @@ import (
"math" "math"
) )
type fileInit struct { type File struct {
BlockStart uint32 BlockStart uint32
FragInd uint32 FragInd uint32
FragOffset uint32 FragOffset uint32
Size uint32 Size uint32
}
type File struct {
fileInit
BlockSizes []uint32 BlockSizes []uint32
} }
@@ -34,16 +30,28 @@ type EFile struct {
} }
func ReadFile(r io.Reader, blockSize uint32) (f File, err error) { func ReadFile(r io.Reader, blockSize uint32) (f File, err error) {
err = binary.Read(r, binary.LittleEndian, &f.fileInit) dat := make([]byte, 16)
_, err = r.Read(dat)
if err != nil { if err != nil {
return return
} }
f.BlockStart = binary.LittleEndian.Uint32(dat)
f.FragInd = binary.LittleEndian.Uint32(dat[4:])
f.FragOffset = binary.LittleEndian.Uint32(dat[8:])
f.Size = binary.LittleEndian.Uint32(dat[12:])
toRead := int(math.Floor(float64(f.Size) / float64(blockSize))) toRead := int(math.Floor(float64(f.Size) / float64(blockSize)))
if f.FragInd == 0xFFFFFFFF && f.Size%blockSize > 0 { if f.FragInd == 0xFFFFFFFF && f.Size%blockSize > 0 {
toRead++ toRead++
} }
dat = make([]byte, toRead*4)
_, err = r.Read(dat)
if err != nil {
return
}
f.BlockSizes = make([]uint32, toRead) f.BlockSizes = make([]uint32, toRead)
err = binary.Read(r, binary.LittleEndian, &f.BlockSizes) for i := range toRead {
f.BlockSizes[i] = binary.LittleEndian.Uint32(dat[i*4:])
}
return return
} }
Executable
BIN
View File
Binary file not shown.
+20
View File
@@ -68,6 +68,26 @@ func TestMisc(t *testing.T) {
// t.Fatal("UM") // t.Fatal("UM")
} }
func BenchmarkExtract(b *testing.B) {
tmpDir := "testing"
fil, err := preTest(tmpDir)
if err != nil {
b.Fatal(err)
}
libPath := filepath.Join(tmpDir, "ExtractLib")
os.RemoveAll(libPath)
op := FastOptions()
op.IgnorePerm = true
rdr, err := NewReader(fil)
if err != nil {
b.Fatal(err)
}
err = rdr.ExtractWithOptions(libPath, op)
if err != nil {
b.Fatal(err)
}
}
func BenchmarkRace(b *testing.B) { func BenchmarkRace(b *testing.B) {
tmpDir := "testing" tmpDir := "testing"
fil, err := preTest(tmpDir) fil, err := preTest(tmpDir)