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 {
r.curOffset = 0
var size uint16
err := binary.Read(r.r, binary.LittleEndian, &size)
dat := make([]byte, 2)
_, err := r.r.Read(dat)
if err != nil {
return err
}
size := binary.LittleEndian.Uint16(dat)
realSize := size &^ 0x8000
r.dat = make([]byte, realSize)
err = binary.Read(r.r, binary.LittleEndian, &r.dat)
_, err = r.r.Read(r.dat)
if err != nil {
return err
}
+1 -3
View File
@@ -1,7 +1,6 @@
package data
import (
"encoding/binary"
"errors"
"io"
"io/fs"
@@ -10,7 +9,6 @@ import (
"sync"
"github.com/CalebQ42/squashfs/internal/decompress"
"github.com/CalebQ42/squashfs/internal/toreader"
)
type FragReaderConstructor func() (io.Reader, error)
@@ -80,7 +78,7 @@ func (r FullReader) process(index uint64, fileOffset uint64, pool *sync.Pool, re
return
}
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 {
ret.data, ret.err = r.d.Decompress(ret.data)
}
+1 -2
View File
@@ -1,7 +1,6 @@
package data
import (
"encoding/binary"
"io"
"io/fs"
@@ -56,7 +55,7 @@ func (r *Reader) advance() error {
return nil
}
r.dat = make([]byte, realSize)
err = binary.Read(r.r, binary.LittleEndian, &r.dat)
_, err = r.r.Read(r.dat)
if err != nil {
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
}
func (b *FileBase) GetFullReader(r *Reader) (data.FullReader, error) {
func (b FileBase) GetFullReader(r *Reader) (data.FullReader, error) {
if !b.IsRegular() {
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
}
func (b *FileBase) GetReader(r *Reader) (data.Reader, error) {
func (b FileBase) GetReader(r *Reader) (data.Reader, error) {
if !b.IsRegular() {
return data.Reader{}, errors.New("not a regular file")
}
+32 -19
View File
@@ -13,7 +13,7 @@ type Directory struct {
ParentNum uint32
}
type eDirectoryInit struct {
type EDirectory struct {
LinkCount uint32
Size uint32
BlockStart uint32
@@ -21,42 +21,55 @@ type eDirectoryInit struct {
IndCount uint16
Offset uint16
XattrInd uint32
}
type EDirectory struct {
eDirectoryInit
Indexes []DirectoryIndex
}
type directoryIndexInit struct {
Ind uint32
Start uint32
NameSize uint32
Indexes []DirectoryIndex
}
type DirectoryIndex struct {
directoryIndexInit
Name []byte
Ind uint32
Start uint32
NameSize uint32
Name []byte
}
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
}
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 {
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)
for i := range d.Indexes {
err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].directoryIndexInit)
for i := range d.IndCount {
dat = make([]byte, 12)
_, err = r.Read(dat)
if err != nil {
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)
err = binary.Read(r, binary.LittleEndian, &d.Indexes[i].Name)
_, err = r.Read(d.Indexes[i].Name)
if err != nil {
return
}
+15 -7
View File
@@ -6,15 +6,11 @@ import (
"math"
)
type fileInit struct {
type File struct {
BlockStart uint32
FragInd uint32
FragOffset uint32
Size uint32
}
type File struct {
fileInit
BlockSizes []uint32
}
@@ -34,16 +30,28 @@ type EFile struct {
}
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 {
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)))
if f.FragInd == 0xFFFFFFFF && f.Size%blockSize > 0 {
toRead++
}
dat = make([]byte, toRead*4)
_, err = r.Read(dat)
if err != nil {
return
}
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
}
Executable
BIN
View File
Binary file not shown.
+20
View File
@@ -68,6 +68,26 @@ func TestMisc(t *testing.T) {
// 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) {
tmpDir := "testing"
fil, err := preTest(tmpDir)