Skip to content

Commit

Permalink
File is now ordered in traversal order
Browse files Browse the repository at this point in the history
  • Loading branch information
richardlehane committed May 10, 2016
1 parent 1fbe839 commit 17dbb2d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 35 deletions.
26 changes: 10 additions & 16 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (r *Reader) setDirEntries() error {
if r.header.numDirectorySectors > 0 {
c = int(r.header.numDirectorySectors)
}
fs, de := make([]*File, 0, c), make([]int, 0, c)
de := make([]*File, 0, c)
cycles := make(map[uint32]bool)
num := int(sectorSize / 128)
sn := r.header.directorySectorLoc
Expand All @@ -92,14 +92,11 @@ func (r *Reader) setDirEntries() error {
return Error{ErrRead, "directory entries read error (" + err.Error() + ")", fileOffset(sn)}
}
for i := 0; i < num; i++ {
de = append(de, len(fs))
f := &File{r: r}
f.directoryEntryFields = makeDirEntry(buf[i*128:])
if f.directoryEntryFields.objectType != unknown {
fixFile(r.header.majorVersion, f)
f.readSector = f.startingSectorLoc
fs = append(fs, f)
}
fixFile(r.header.majorVersion, f)
f.readSector = f.startingSectorLoc
de = append(de, f)
}
nsn, err := r.findNext(sn, false)
if err != nil {
Expand All @@ -113,7 +110,7 @@ func (r *Reader) setDirEntries() error {
}
sn = nsn
}
r.File, r.direntries = fs, de
r.direntries = de
return nil
}

Expand Down Expand Up @@ -144,26 +141,24 @@ func fixName(f *File) {
}

func (r *Reader) traverse() error {
r.indexes = make([]int, len(r.File))
var idx int
r.File = make([]*File, 0, len(r.direntries))
var recurse func(int, []string)
var err error
recurse = func(i int, path []string) {
if i < 0 || i >= len(r.direntries) || r.direntries[i] >= len(r.File) {
if i < 0 || i >= len(r.direntries) {
err = Error{ErrTraverse, "illegal traversal index", int64(i)}
return
}
file := r.File[r.direntries[i]]
file := r.direntries[i]
if file.leftSibID != noStream {
recurse(int(file.leftSibID), path)
}
if idx >= len(r.indexes) {
if len(r.File) >= cap(r.File) {
err = Error{ErrTraverse, "traversal counter overflow", int64(i)}
return
}
r.indexes[idx] = r.direntries[i]
r.File = append(r.File, file)
file.Path = path
idx++
if file.childID != noStream {
if i > 0 {
recurse(int(file.childID), append(path, file.Name))
Expand All @@ -177,7 +172,6 @@ func (r *Reader) traverse() error {
return
}
recurse(0, []string{})
r.indexes = r.indexes[:idx]
return err
}

Expand Down
20 changes: 10 additions & 10 deletions mscfb.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (r *Reader) setDifats() error {
// set the ministream FAT and sector slices in the header
func (r *Reader) setMiniStream() error {
// do nothing if there is no ministream
if r.File[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 {
if r.direntries[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 {
return nil
}
// build a slice of minifat sectors (akin to the DIFAT slice)
Expand All @@ -201,7 +201,7 @@ func (r *Reader) setMiniStream() error {
// build a slice of ministream sectors
c = int(sectorSize / 4 * r.header.numMiniFatSectors)
r.header.miniStreamLocs = make([]uint32, 0, c)
sn := r.File[0].startingSectorLoc
sn := r.direntries[0].startingSectorLoc
var err error
for sn != endOfChain {
r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn)
Expand Down Expand Up @@ -273,11 +273,11 @@ type Reader struct {
slicer bool
buf []byte
header *header
File []*File // File is a slice of directory entries. Not necessarily in correct order. Use Next() for order.
File []*File // File is an ordered slice of final directory entries.
direntries []*File // unordered raw directory entries
entry int
indexes []int
direntries []int
ra io.ReaderAt

ra io.ReaderAt
}

// New returns a MSCFB reader
Expand Down Expand Up @@ -329,18 +329,18 @@ func (r *Reader) Modified() time.Time {
// This isn't necessarily an adjacent *File within the File slice, but is based on the Left Sibling, Right Sibling and Child information in directory entries.
func (r *Reader) Next() (*File, error) {
r.entry++
if r.entry >= len(r.indexes) {
if r.entry >= len(r.File) {
return nil, io.EOF
}
return r.File[r.indexes[r.entry]], nil
return r.File[r.entry], nil
}

// Read the current directory entry
func (r *Reader) Read(b []byte) (n int, err error) {
if r.entry >= len(r.indexes) {
if r.entry >= len(r.File) {
return 0, io.EOF
}
return r.File[r.indexes[r.entry]].Read(b)
return r.File[r.entry].Read(b)
}

// Debug provides granular information from an mscfb file to assist with debugging
Expand Down
23 changes: 14 additions & 9 deletions mscfb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,27 @@ func testFile(t *testing.T, path string) {

func TestTraverse(t *testing.T) {
r := new(Reader)
r.File = testEntries
r.direntries = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
r.direntries = testEntries
if r.traverse() != nil {
t.Error("Error traversing")
}
expect := []int{0, 1, 2, 4, 5, 8, 9, 11, 6, 3, 7, 10}
for i, v := range r.indexes {
if v != expect[i] {
t.Errorf("Error traversing: expecting %d at index %d; got %d", expect[i], i, v)
if len(r.File) != len(expect) {
t.Fatalf("Error traversing: expecting %d entries, got %d", len(expect), len(r.File))
}
for i, v := range r.File {
if v != testEntries[expect[i]] {
t.Errorf("Error traversing: expecting %d at index %d; got %v", expect[i], i, v)
}
}
if r.File[10].Path[0] != "Charlie" {
t.Errorf("Error traversing: expecting Charlie got %s", r.File[10].Path[0])
if len(r.File[len(r.File)-1].Path) != 2 {
t.Fatalf("Error traversing: expecting a path length of %d, got %d", 2, len(r.File[len(r.File)-1].Path))
}
if r.File[len(r.File)-1].Path[0] != "Charlie" {
t.Errorf("Error traversing: expecting Charlie got %s", r.File[expect[10]].Path[0])
}
if r.File[10].Path[1] != "Golf" {
t.Errorf("Error traversing: expecting Golf got %s", r.File[10].Path[1])
if r.File[len(r.File)-1].Path[1] != "Golf" {
t.Errorf("Error traversing: expecting Golf got %s", r.File[expect[10]].Path[1])
}
}

Expand Down

0 comments on commit 17dbb2d

Please sign in to comment.