This commit is contained in:
parent
df92f55df6
commit
154893d9f7
19 changed files with 410 additions and 11 deletions
8
src/fs/File.go
Normal file
8
src/fs/File.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package fs
|
||||
|
||||
// File represents a single source file.
|
||||
type File struct {
|
||||
Path string
|
||||
Package string
|
||||
Bytes []byte
|
||||
}
|
61
src/fs/Walk_fast.go
Normal file
61
src/fs/Walk_fast.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
//go:build linux || darwin
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Walk calls your callback function for every file name inside the directory.
|
||||
// It doesn't distinguish between files and directories.
|
||||
func Walk(directory string, callBack func(string)) error {
|
||||
fd, err := syscall.Open(directory, 0, 0)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer syscall.Close(fd)
|
||||
buffer := make([]byte, 1024)
|
||||
|
||||
for {
|
||||
n, err := syscall.ReadDirent(fd, buffer)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
readBuffer := buffer[:n]
|
||||
|
||||
for len(readBuffer) > 0 {
|
||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&readBuffer[0]))
|
||||
readBuffer = readBuffer[dirent.Reclen:]
|
||||
|
||||
if dirent.Ino == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if dirent.Name[0] == '.' {
|
||||
continue
|
||||
}
|
||||
|
||||
for i, c := range dirent.Name {
|
||||
if c != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
bytePointer := (*byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
name := unsafe.String(bytePointer, i)
|
||||
callBack(name)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
28
src/fs/Walk_slow.go
Normal file
28
src/fs/Walk_slow.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
//go:build !linux && !darwin
|
||||
|
||||
package fs
|
||||
|
||||
import "os"
|
||||
|
||||
// Walk calls your callback function for every file name inside the directory.
|
||||
// It doesn't distinguish between files and directories.
|
||||
func Walk(directory string, callBack func(string)) error {
|
||||
f, err := os.Open(directory)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, err := f.Readdirnames(0)
|
||||
f.Close()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
callBack(file)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
29
src/fs/Walk_test.go
Normal file
29
src/fs/Walk_test.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package fs_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/fs"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestWalk(t *testing.T) {
|
||||
var files []string
|
||||
|
||||
err := fs.Walk(".", func(file string) {
|
||||
files = append(files, file)
|
||||
})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Contains(t, files, "Walk_test.go")
|
||||
}
|
||||
|
||||
func TestWalkNotDirectory(t *testing.T) {
|
||||
err := fs.Walk("Walk_test.go", func(file string) {})
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestWalkNotExisting(t *testing.T) {
|
||||
err := fs.Walk("_", func(file string) {})
|
||||
assert.NotNil(t, err)
|
||||
}
|
42
src/fs/bench_test.go
Normal file
42
src/fs/bench_test.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package fs_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/fs"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func BenchmarkReadDir(b *testing.B) {
|
||||
for b.Loop() {
|
||||
files, err := os.ReadDir(".")
|
||||
assert.Nil(b, err)
|
||||
|
||||
for _, file := range files {
|
||||
func(string) {}(file.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReaddirnames(b *testing.B) {
|
||||
for b.Loop() {
|
||||
f, err := os.Open(".")
|
||||
assert.Nil(b, err)
|
||||
files, err := f.Readdirnames(0)
|
||||
assert.Nil(b, err)
|
||||
|
||||
for _, file := range files {
|
||||
func(string) {}(file)
|
||||
}
|
||||
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWalk(b *testing.B) {
|
||||
for b.Loop() {
|
||||
err := fs.Walk(".", func(string) {})
|
||||
assert.Nil(b, err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue