1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-08-08 14:54:40 +00:00

fix an error that occured when one subhypha's name was the prefix of another

figureOutChildren("root/a") would detect "root/ab" as a descendant
then figureOutChildren("root/ab") would detect "root/ab" as a descendant and panic trying to find the subpath
This commit is contained in:
Elias Bomberger 2021-10-16 22:48:35 -04:00 committed by handlerug
parent 0354945502
commit 835529947b

View File

@ -11,7 +11,7 @@ import (
"github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/util"
) )
func findSiblingsAndDescendants(hyphaName string) ([]*sibling, map[string]bool) { func findSiblings(hyphaName string) []*sibling {
hyphaDir := "" hyphaDir := ""
if hyphaRawDir := path.Dir(hyphaName); hyphaRawDir != "." { if hyphaRawDir := path.Dir(hyphaName); hyphaRawDir != "." {
hyphaDir = hyphaRawDir hyphaDir = hyphaRawDir
@ -37,20 +37,11 @@ func findSiblingsAndDescendants(hyphaName string) ([]*sibling, map[string]bool)
return hyphae.CheckContinue return hyphae.CheckContinue
} }
descendantsPool = make(map[string]bool, 0)
descendantCheck = func(h *hyphae.Hypha) hyphae.CheckResult {
if strings.HasPrefix(h.Name, hyphaName+"/") {
descendantsPool[h.Name] = true
}
return hyphae.CheckContinue
}
i7n = hyphae.NewIteration() i7n = hyphae.NewIteration()
) )
siblingsMap[hyphaName] = true siblingsMap[hyphaName] = true
i7n.AddCheck(siblingCheck) i7n.AddCheck(siblingCheck)
i7n.AddCheck(descendantCheck)
i7n.Ignite() i7n.Ignite()
siblings := make([]*sibling, len(siblingsMap)) siblings := make([]*sibling, len(siblingsMap))
@ -62,7 +53,7 @@ func findSiblingsAndDescendants(hyphaName string) ([]*sibling, map[string]bool)
sort.Slice(siblings, func(i, j int) bool { sort.Slice(siblings, func(i, j int) bool {
return siblings[i].name < siblings[j].name return siblings[i].name < siblings[j].name
}) })
return siblings, descendantsPool return siblings
} }
func countSubhyphae(siblings []*sibling) { func countSubhyphae(siblings []*sibling) {
@ -90,21 +81,22 @@ func Tree(hyphaName string) (siblingsHTML, childrenHTML, prev, next string) {
children := make([]child, 0) children := make([]child, 0)
I := 0 I := 0
// The tree is generated in two iterations of hyphae storage: // The tree is generated in two iterations of hyphae storage:
// 1. Find all siblings (sorted) and descendants' names // 1. Find all siblings (sorted)
// 2. Count how many subhyphae siblings have // 2. Count how many subhyphae siblings have
// //
// We also have to figure out what is going on with the descendants: who is a child of whom. We do that in parallel with (2) because we can. // We also have to figure out what is going on with the descendants: who is a child of whom. We do that in parallel with (2) because we can.
// One of the siblings is the hypha with name `hyphaName` // One of the siblings is the hypha with name `hyphaName`
siblings, descendantsPool := findSiblingsAndDescendants(hyphaName) var siblings []*sibling
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(2) wg.Add(2)
go func() { go func() {
siblings = findSiblings(hyphaName)
countSubhyphae(siblings) countSubhyphae(siblings)
wg.Done() wg.Done()
}() }()
go func() { go func() {
children = figureOutChildren(hyphaName, descendantsPool, true).children children = figureOutChildren(hyphaName, true).children
wg.Done() wg.Done()
}() }()
wg.Wait() wg.Wait()
@ -132,32 +124,55 @@ type child struct {
children []child children []child
} }
func figureOutChildren(hyphaName string, subhyphaePool map[string]bool, exists bool) child { func figureOutChildren(hyphaName string, exists bool) child {
var ( var (
nestLevel = strings.Count(hyphaName, "/") descPrefix = hyphaName + "/"
adopted = make([]child, 0) child = child{hyphaName, true, make([]child, 0)}
) )
for subhyphaName := range subhyphaePool {
subnestLevel := strings.Count(subhyphaName, "/") for desc := range hyphae.YieldExistingHyphae() {
if subnestLevel-1 == nestLevel && path.Dir(subhyphaName) == hyphaName { var descName = desc.Name
delete(subhyphaePool, subhyphaName) if strings.HasPrefix(descName, descPrefix) {
adopted = append(adopted, figureOutChildren(subhyphaName, subhyphaePool, true)) var subPath = strings.TrimPrefix(descName, descPrefix)
} addHyphaToChild(descName, subPath, &child)
}
for descName := range subhyphaePool {
if strings.HasPrefix(descName, hyphaName) {
var (
rawSubPath = strings.TrimPrefix(descName, hyphaName)[1:]
slashIdx = strings.IndexRune(rawSubPath, '/')
)
if slashIdx > -1 {
var sibPath = descName[:slashIdx+len(hyphaName)+1]
adopted = append(adopted, figureOutChildren(sibPath, subhyphaePool, false))
} // `else` never happens?
} }
} }
return child{hyphaName, exists, adopted} return child
}
func addHyphaToChild(hyphaName, subPath string, child *child) {
// when hyphaName = "root/a/b", subPath = "a/b", and child.name = "root"
// addHyphaToChild("root/a/b", "b", child{"root/a"})
// when hyphaName = "root/a/b", subPath = "b", and child.name = "root/a"
// set .exists=true for "root/a/b", and create it if it isn't there already
var exists = !strings.Contains(subPath, "/")
if exists {
var subchild = findOrCreateSubchild(subPath, child)
subchild.exists = true
} else {
var (
firstSlash = strings.IndexRune(subPath, '/')
firstDir = subPath[:firstSlash]
restOfPath = subPath[firstSlash + 1:]
subchild = findOrCreateSubchild(firstDir, child)
)
addHyphaToChild(hyphaName, restOfPath, subchild)
}
}
func findOrCreateSubchild(name string, baseChild *child) *child {
// when name = "a", and baseChild.name = "root"
// if baseChild.children contains "root/a", return it
// else create it and return that
var fullName = baseChild.name + "/" + name
for i := range baseChild.children {
if baseChild.children[i].name == fullName {
return &baseChild.children[i]
}
}
baseChild.children = append(baseChild.children, child{fullName, false, make([]child, 0)})
return &baseChild.children[len(baseChild.children) - 1]
} }
type sibling struct { type sibling struct {