diff --git a/node_generate.go b/node_generate.go index 91b8bb5..0ea1c91 100644 --- a/node_generate.go +++ b/node_generate.go @@ -8,34 +8,33 @@ import ( ) type rootGenerator struct { - r io.Reader - st spaceType + counter *counter + scanner *bufio.Scanner + strategy nodeGenerateStrategy } func newRootGenerator(r io.Reader, st spaceType) *rootGenerator { return &rootGenerator{ - r: r, - st: st, + counter: newCounter(), + scanner: bufio.NewScanner(r), + strategy: newStrategy(st), } } func (rg *rootGenerator) generate() ([]*Node, error) { var ( - scanner = bufio.NewScanner(rg.r) - stack *stack - counter = newCounter() - generateNodeFunc = rg.st.decideGenerateFunc() - roots []*Node + stack *stack + roots []*Node ) - for scanner.Scan() { - currentNode := generateNodeFunc(scanner.Text(), counter.next()) + for rg.scanner.Scan() { + currentNode := rg.strategy.generate(rg.scanner.Text(), rg.counter.next()) if err := currentNode.validate(); err != nil { return nil, err } if currentNode.isRoot() { - counter.reset() + rg.counter.reset() roots = append(roots, currentNode) stack = newStack() stack.push(currentNode) @@ -49,7 +48,7 @@ func (rg *rootGenerator) generate() ([]*Node, error) { stack.dfs(currentNode) } - if err := scanner.Err(); err != nil { + if err := rg.scanner.Err(); err != nil { return nil, err } return roots, nil @@ -69,147 +68,3 @@ func (n *Node) validate() error { } return nil } - -type generateFunc func(row string, idx uint) *Node - -type spaceType int - -const ( - spacesTab spaceType = iota - spacesTwo - spacesFour -) - -func (st spaceType) decideGenerateFunc() generateFunc { - switch st { - case spacesTwo: - return generateFuncTwoSpaces - case spacesFour: - return generateFuncFourSpaces - default: - return generateFuncTab - } -} - -// https://ja.wikipedia.org/wiki/ASCII -const ( - hyphen = 45 - space = 32 - tab = 9 -) - -const ( - rootHierarchyNum = uint(1) -) - -func generateFuncTab(row string, idx uint) *Node { - var ( - text = "" - hierarchy = rootHierarchyNum - ) - var ( - isPrevChar = false - isRoot = false - ) - - for i, r := range row { - switch r { - case hyphen: - if i == 0 { - isRoot = true - } - if isPrevChar { - text += string(r) - continue - } - isPrevChar = false - case space: - if isPrevChar { - text += string(r) - continue - } - case tab: - hierarchy++ - default: // directry or file text char - text += string(r) - isPrevChar = true - } - } - if !isRoot && hierarchy == rootHierarchyNum { - hierarchy = 0 - } - - return newNode(text, hierarchy, idx) -} - -func generateFuncTwoSpaces(row string, idx uint) *Node { - var ( - text = "" - hierarchy = rootHierarchyNum - ) - var ( - spaceCnt = uint(0) - isPrevChar = false - ) - - for _, r := range row { - switch r { - case hyphen: - if isPrevChar { - text += string(r) - continue - } - if spaceCnt%2 == 0 { - hierarchy += spaceCnt / 2 - } - isPrevChar = false - case space: - if isPrevChar { - text += string(r) - continue - } - spaceCnt++ - default: // directry or file text char - text += string(r) - isPrevChar = true - } - } - - return newNode(text, hierarchy, idx) -} - -func generateFuncFourSpaces(row string, idx uint) *Node { - var ( - text = "" - hierarchy = rootHierarchyNum - ) - var ( - spaceCnt = uint(0) - isPrevChar = false - ) - - for _, r := range row { - switch r { - case hyphen: - if isPrevChar { - text += string(r) - continue - } - if spaceCnt%4 == 0 { - hierarchy += spaceCnt / 4 - } - isPrevChar = false - case space: - if isPrevChar { - text += string(r) - continue - } - spaceCnt++ - default: // directry or file text char - text += string(r) - isPrevChar = true - } - } - - return newNode(text, hierarchy, idx) -} diff --git a/node_generate_strategy.go b/node_generate_strategy.go new file mode 100644 index 0000000..5a5fa43 --- /dev/null +++ b/node_generate_strategy.go @@ -0,0 +1,153 @@ +package gtree + +type spaceType int + +const ( + spacesTab spaceType = iota + spacesTwo + spacesFour +) + +type nodeGenerateStrategy interface { + generate(row string, idx uint) *Node +} + +func newStrategy(st spaceType) nodeGenerateStrategy { + switch st { + case spacesTwo: + return &twoSpacesStrategy{} + case spacesFour: + return &fourSpacesStrategy{} + default: + return &tabStrategy{} + } +} + +// https://ja.wikipedia.org/wiki/ASCII +const ( + hyphen = 45 + space = 32 + tab = 9 +) + +const ( + rootHierarchyNum = uint(1) +) + +type tabStrategy struct{} + +func (*tabStrategy) generate(row string, idx uint) *Node { + var ( + text = "" + hierarchy = rootHierarchyNum + ) + var ( + isPrevChar = false + isRoot = false + ) + + for i, r := range row { + switch r { + case hyphen: + if i == 0 { + isRoot = true + } + if isPrevChar { + text += string(r) + continue + } + isPrevChar = false + case space: + if isPrevChar { + text += string(r) + continue + } + case tab: + hierarchy++ + default: // directry or file text char + text += string(r) + isPrevChar = true + } + } + if !isRoot && hierarchy == rootHierarchyNum { + hierarchy = 0 + } + + return newNode(text, hierarchy, idx) +} + +type twoSpacesStrategy struct{} + +func (*twoSpacesStrategy) generate(row string, idx uint) *Node { + var ( + text = "" + hierarchy = rootHierarchyNum + ) + var ( + spaceCnt = uint(0) + isPrevChar = false + ) + + for _, r := range row { + switch r { + case hyphen: + if isPrevChar { + text += string(r) + continue + } + if spaceCnt%2 == 0 { + hierarchy += spaceCnt / 2 + } + isPrevChar = false + case space: + if isPrevChar { + text += string(r) + continue + } + spaceCnt++ + default: // directry or file text char + text += string(r) + isPrevChar = true + } + } + + return newNode(text, hierarchy, idx) +} + +type fourSpacesStrategy struct{} + +func (*fourSpacesStrategy) generate(row string, idx uint) *Node { + var ( + text = "" + hierarchy = rootHierarchyNum + ) + var ( + spaceCnt = uint(0) + isPrevChar = false + ) + + for _, r := range row { + switch r { + case hyphen: + if isPrevChar { + text += string(r) + continue + } + if spaceCnt%4 == 0 { + hierarchy += spaceCnt / 4 + } + isPrevChar = false + case space: + if isPrevChar { + text += string(r) + continue + } + spaceCnt++ + default: // directry or file text char + text += string(r) + isPrevChar = true + } + } + + return newNode(text, hierarchy, idx) +}