]> Sergey Matveev's repositories - glocate.git/blob - names.go
Unify copyright comment format
[glocate.git] / names.go
1 // glocate -- ZFS-diff-friendly locate-like utility
2 // Copyright (C) 2022-2024 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 package main
17
18 import (
19         "log"
20         "path"
21         "strconv"
22         "strings"
23 )
24
25 func IsDir(s string) bool {
26         return s[len(s)-1] == '/'
27 }
28
29 type ByName [][]string
30
31 func (a ByName) Len() int {
32         return len(a)
33 }
34
35 func (a ByName) Swap(i, j int) {
36         a[i], a[j] = a[j], a[i]
37 }
38
39 func (a ByName) Less(i, j int) bool {
40         return namesCmp(a[i], a[j]) < 0
41 }
42
43 func nameSplit(name string) []string {
44         cols := strings.Split(name, "/")
45         if IsDir(name) {
46                 cols = cols[:len(cols)-1]
47                 cols[len(cols)-1] += "/"
48         }
49         return cols
50 }
51
52 func nameJoin(name []string) (s string) {
53         s = path.Join(name...)
54         if IsDir(name[len(name)-1]) {
55                 s += "/"
56         }
57         return
58 }
59
60 func namesCmp(n1, n2 []string) int {
61         min := len(n1)
62         if len(n2) < min {
63                 min = len(n2)
64         }
65         var t1, t2 string
66         for i := 0; i < min; i++ {
67                 t1 = strings.TrimSuffix(n1[i], "/")
68                 t2 = strings.TrimSuffix(n2[i], "/")
69                 if t1 < t2 {
70                         return -1
71                 }
72                 if t1 > t2 {
73                         return +1
74                 }
75         }
76         if len(n1) > len(n2) {
77                 return +1
78         }
79         if len(n1) < len(n2) {
80                 return -1
81         }
82         return 0
83 }
84
85 func hasPrefix(name, prefix []string) bool {
86         if len(name) < len(prefix) {
87                 return false
88         }
89         return namesCmp(name[:len(prefix)], prefix) == 0
90 }
91
92 func deoctalize(s string) string {
93         chars := make([]byte, 0, len(s))
94         for i := 0; i < len(s); i++ {
95                 if s[i] == '\\' {
96                         b, err := strconv.ParseUint(s[i+1:i+1+4], 0, 8)
97                         if err != nil {
98                                 log.Fatalln(err)
99                         }
100                         chars = append(chars, byte(b))
101                         i += 4
102                 } else {
103                         chars = append(chars, s[i])
104                 }
105         }
106         return string(chars)
107 }