| package noder |
| |
| import ( |
| "bytes" |
| "strings" |
| |
| "golang.org/x/text/unicode/norm" |
| ) |
| |
| // Path values represent a noder and its ancestors. The root goes first |
| // and the actual final noder the path is referring to will be the last. |
| // |
| // A path implements the Noder interface, redirecting all the interface |
| // calls to its final noder. |
| // |
| // Paths build from an empty Noder slice are not valid paths and should |
| // not be used. |
| type Path []Noder |
| |
| // String returns the full path of the final noder as a string, using |
| // "/" as the separator. |
| func (p Path) String() string { |
| var buf bytes.Buffer |
| sep := "" |
| for _, e := range p { |
| _, _ = buf.WriteString(sep) |
| sep = "/" |
| _, _ = buf.WriteString(e.Name()) |
| } |
| |
| return buf.String() |
| } |
| |
| // Last returns the final noder in the path. |
| func (p Path) Last() Noder { |
| return p[len(p)-1] |
| } |
| |
| // Hash returns the hash of the final noder of the path. |
| func (p Path) Hash() []byte { |
| return p.Last().Hash() |
| } |
| |
| // Name returns the name of the final noder of the path. |
| func (p Path) Name() string { |
| return p.Last().Name() |
| } |
| |
| // IsDir returns if the final noder of the path is a directory-like |
| // noder. |
| func (p Path) IsDir() bool { |
| return p.Last().IsDir() |
| } |
| |
| // Children returns the children of the final noder in the path. |
| func (p Path) Children() ([]Noder, error) { |
| return p.Last().Children() |
| } |
| |
| // NumChildren returns the number of children the final noder of the |
| // path has. |
| func (p Path) NumChildren() (int, error) { |
| return p.Last().NumChildren() |
| } |
| |
| // Compare returns -1, 0 or 1 if the path p is smaller, equal or bigger |
| // than other, in "directory order"; for example: |
| // |
| // "a" < "b" |
| // "a/b/c/d/z" < "b" |
| // "a/b/a" > "a/b" |
| func (p Path) Compare(other Path) int { |
| i := 0 |
| for { |
| switch { |
| case len(other) == len(p) && i == len(p): |
| return 0 |
| case i == len(other): |
| return 1 |
| case i == len(p): |
| return -1 |
| default: |
| form := norm.Form(norm.NFC) |
| this := form.String(p[i].Name()) |
| that := form.String(other[i].Name()) |
| |
| cmp := strings.Compare(this, that) |
| if cmp != 0 { |
| return cmp |
| } |
| } |
| i++ |
| } |
| } |