Skip to content

Commit

Permalink
Optimize element lookup in FileSystemFinder by switching from []strin…
Browse files Browse the repository at this point in the history
…g to map[string]struct{} (#115)

* changed []string to map[string]struct{} in FileSystemFinder struct fields because of optimization (arrays were used only to check the occurrence of an element)

* Changed field Extensions type in FileType from []string to map[string]struct{}

* added requested changes

---------

Co-authored-by: Yaroslav <=>
  • Loading branch information
SkobelkinYaroslav authored Mar 18, 2024
1 parent b48fa22 commit c824e2a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 33 deletions.
23 changes: 12 additions & 11 deletions pkg/filetype/file_type.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package filetype

import (
"github.com/Boeing/config-file-validator/pkg/misc"
"github.com/Boeing/config-file-validator/pkg/validator"
)

Expand All @@ -10,87 +11,87 @@ import (
// to be able to validate the file
type FileType struct {
Name string
Extensions []string
Extensions map[string]struct{}
Validator validator.Validator
}

// Instance of the FileType object to
// represent a JSON file
var JsonFileType = FileType{
"json",
[]string{"json"},
misc.ArrToMap("json"),
validator.JsonValidator{},
}

// Instance of the FileType object to
// represent a YAML file
var YamlFileType = FileType{
"yaml",
[]string{"yml", "yaml"},
misc.ArrToMap("yml", "yaml"),
validator.YamlValidator{},
}

// Instance of FileType object to
// represent a XML file
var XmlFileType = FileType{
"xml",
[]string{"xml"},
misc.ArrToMap("xml"),
validator.XmlValidator{},
}

// Instance of FileType object to
// represent a Toml file
var TomlFileType = FileType{
"toml",
[]string{"toml"},
misc.ArrToMap("toml"),
validator.TomlValidator{},
}

// Instance of FileType object to
// represent a Ini file
var IniFileType = FileType{
"ini",
[]string{"ini"},
misc.ArrToMap("ini"),
validator.IniValidator{},
}

// Instance of FileType object to
// represent a Properties file
var PropFileType = FileType{
"properties",
[]string{"properties"},
misc.ArrToMap("properties"),
validator.PropValidator{},
}

// Instance of the FileType object to
// represent a HCL file
var HclFileType = FileType{
"hcl",
[]string{"hcl"},
misc.ArrToMap("hcl"),
validator.HclValidator{},
}

// Instance of the FileType object to
// represent a Plist file
var PlistFileType = FileType{
"plist",
[]string{"plist"},
misc.ArrToMap("plist"),
validator.PlistValidator{},
}

// Instance of the FileType object to
// represent a CSV file
var CsvFileType = FileType{
"csv",
[]string{"csv"},
misc.ArrToMap("csv"),
validator.CsvValidator{},
}

// Instance of the FileType object to
// represent a HOCON file
var HoconFileType = FileType{
"hocon",
[]string{"hocon"},
misc.ArrToMap("hocon"),
validator.HoconValidator{},
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/finder/finder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package finder

import (
"fmt"
"github.com/Boeing/config-file-validator/pkg/misc"
"path/filepath"
"testing"

Expand Down Expand Up @@ -112,7 +113,7 @@ func Test_fsFinderWithDepth(t *testing.T) {
func Test_fsFinderCustomTypes(t *testing.T) {
jsonFileType := filetype.FileType{
Name: "json",
Extensions: []string{"json"},
Extensions: misc.ArrToMap("json"),
Validator: validator.JsonValidator{},
}
fsFinder := FileSystemFinderInit(
Expand Down
36 changes: 15 additions & 21 deletions pkg/finder/fsfinder.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package finder

import (
"github.com/Boeing/config-file-validator/pkg/misc"
"io/fs"
"os"
"path/filepath"
"strings"

"slices"

"github.com/Boeing/config-file-validator/pkg/filetype"
)

type FileSystemFinder struct {
PathRoots []string
FileTypes []filetype.FileType
ExcludeDirs []string
ExcludeFileTypes []string
ExcludeDirs map[string]struct{}
ExcludeFileTypes map[string]struct{}
Depth *int
}

Expand All @@ -38,14 +37,14 @@ func WithFileTypes(fileTypes []filetype.FileType) FSFinderOptions {
// Add a custom list of file types to the FSFinder
func WithExcludeDirs(excludeDirs []string) FSFinderOptions {
return func(fsf *FileSystemFinder) {
fsf.ExcludeDirs = excludeDirs
fsf.ExcludeDirs = misc.ArrToMap(excludeDirs...)
}
}

// WithExcludeFileTypes adds excluded file types to FSFinder.
func WithExcludeFileTypes(types []string) FSFinderOptions {
return func(fsf *FileSystemFinder) {
fsf.ExcludeFileTypes = types
fsf.ExcludeFileTypes = misc.ArrToMap(types...)
}
}

Expand All @@ -56,7 +55,7 @@ func WithDepth(depthVal int) FSFinderOptions {
}
}
func FileSystemFinderInit(opts ...FSFinderOptions) *FileSystemFinder {
var defaultExcludeDirs []string
defaultExcludeDirs := make(map[string]struct{})
defaultPathRoots := []string{"."}

fsfinder := &FileSystemFinder{
Expand Down Expand Up @@ -125,29 +124,24 @@ func (fsf FileSystemFinder) findOne(pathRoot string) ([]FileMetadata, error) {
return fs.SkipDir // This is not reported as an error by filepath.WalkDir
}

for _, dir := range fsf.ExcludeDirs {
if dirEntry.IsDir() && dirEntry.Name() == dir {
err := filepath.SkipDir
if err != nil {
return err
}
}
if _, ok := fsf.ExcludeDirs[dirEntry.Name()]; dirEntry.IsDir() && ok {
return filepath.SkipDir
}

if !dirEntry.IsDir() {
// filepath.Ext() returns the extension name with a dot so it
// needs to be removed.
walkFileExtension := strings.TrimPrefix(filepath.Ext(path), ".")
if slices.Contains[[]string](fsf.ExcludeFileTypes, walkFileExtension) {

if _, ok := fsf.ExcludeFileTypes[walkFileExtension]; ok {
return nil
}

extensionLowerCase := strings.ToLower(walkFileExtension)
for _, fileType := range fsf.FileTypes {
for _, extension := range fileType.Extensions {
if strings.EqualFold(extension, walkFileExtension) {
fileMetadata := FileMetadata{dirEntry.Name(), path, fileType}
matchingFiles = append(matchingFiles, fileMetadata)
}
if _, ok := fileType.Extensions[extensionLowerCase]; ok {
fileMetadata := FileMetadata{dirEntry.Name(), path, fileType}
matchingFiles = append(matchingFiles, fileMetadata)
break
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions pkg/misc/arrToMap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package misc

// ArrToMap converts a string array
// to a map with keys from the array
// and empty struct values, optimizing string presence checks.
func ArrToMap(arg ...string) map[string]struct{} {
m := make(map[string]struct{}, 0)
for _, item := range arg {
m[item] = struct{}{}
}
return m
}

0 comments on commit c824e2a

Please sign in to comment.