1
0
mirror of https://github.com/golang/go synced 2024-11-24 19:10:15 -07:00

godoc: don't use quadratic algorithm to filter paths

R=rsc
CC=golang-dev
https://golang.org/cl/2212042
This commit is contained in:
Robert Griesemer 2010-09-16 10:40:07 -07:00
parent b610a78b6e
commit 599f758d42

View File

@ -107,21 +107,44 @@ func isRelated(p, q string) bool {
}
// binarySearch returns an index i such that (a[i] <= s < a[i+1]) || (s is not in a).
// The slice a must not be empty and sorted in increasing order.
// (See "A Method of Programming", E.W. Dijkstra).
//
func binarySearch(a []string, s string) int {
i, j := 0, len(a)
// i < j for non-empty a
for i+1 < j {
// 0 <= i < j <= len(a) && (a[i] <= s < a[j] || (s is not in a))
h := i + (j-i)/2 // i < h < j
if a[h] <= s {
i = h
} else { // s < a[h]
j = h
}
}
// i+1 == j for non-empty a
return i
}
func setPathFilter(list []string) {
if len(list) == 0 {
pathFilter.set(nil)
return
}
// TODO(gri) This leads to quadratic behavior.
// Need to find a better filter solution.
// len(list) > 0
pathFilter.set(func(path string) bool {
for _, p := range list {
if isRelated(path, p) {
return true
}
}
return false
// list is sorted in increasing order and for each path all its children are removed
i := binarySearch(list, path)
// At this point we have (list[i] <= path < list[i+1]) || (path is not in list),
// thus path must be either longer (a child) of list[i], or shorter (a parent)
// of list[i+1] - assuming an "infinitely extended" list. However, binarySearch
// will return a 0 if path < list[0], so we must be careful in that case.
return i == 0 && isParentOf(path, list[0]) ||
isParentOf(list[i], path) ||
i+1 < len(list) && isParentOf(path, list[i+1])
})
}
@ -142,12 +165,22 @@ func readDirList(filename string) ([]string, os.Error) {
if err != nil {
return nil, err
}
// create list of valid directory names
// create a sorted list of valid directory names
filter := func(path string) bool {
d, err := os.Lstat(path)
return err == nil && isPkgDir(d)
}
return canonicalizePaths(strings.Split(string(contents), "\n", -1), filter), nil
list := canonicalizePaths(strings.Split(string(contents), "\n", -1), filter)
// for each parent path, remove all it's children q
// (requirement for binary search to work when filtering)
i := 0
for _, q := range list {
if i == 0 || !isParentOf(list[i-1], q) {
list[i] = q
i++
}
}
return list[0:i], nil
}