this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/str: add package

Change-Id: Icb5ec1385be4d200f19613eebcd4d290b3b01642

+212
+61
internal/str/path.go
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package str 16 + 17 + import ( 18 + "path/filepath" 19 + "strings" 20 + ) 21 + 22 + // HasPath reports whether the slash-separated path s 23 + // begins with the elements in prefix. 24 + func HasPathPrefix(s, prefix string) bool { 25 + if len(s) == len(prefix) { 26 + return s == prefix 27 + } 28 + if prefix == "" { 29 + return true 30 + } 31 + if len(s) > len(prefix) { 32 + if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' { 33 + return s[:len(prefix)] == prefix 34 + } 35 + } 36 + return false 37 + } 38 + 39 + // HasFilePathPrefix reports whether the filesystem path s 40 + // begins with the elements in prefix. 41 + func HasFilePathPrefix(s, prefix string) bool { 42 + sv := strings.ToUpper(filepath.VolumeName(s)) 43 + pv := strings.ToUpper(filepath.VolumeName(prefix)) 44 + s = s[len(sv):] 45 + prefix = prefix[len(pv):] 46 + switch { 47 + default: 48 + return false 49 + case sv != pv: 50 + return false 51 + case len(s) == len(prefix): 52 + return s == prefix 53 + case prefix == "": 54 + return true 55 + case len(s) > len(prefix): 56 + if prefix[len(prefix)-1] == filepath.Separator { 57 + return strings.HasPrefix(s, prefix) 58 + } 59 + return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix 60 + } 61 + }
+151
internal/str/str.go
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + // Package str provides string manipulation utilities. 16 + package str // import "cuelang.org/go/internal/str" 17 + 18 + import ( 19 + "bytes" 20 + "fmt" 21 + "unicode" 22 + "unicode/utf8" 23 + ) 24 + 25 + // StringList flattens its arguments into a single []string. 26 + // Each argument in args must have type string or []string. 27 + func StringList(args ...interface{}) []string { 28 + var x []string 29 + for _, arg := range args { 30 + switch arg := arg.(type) { 31 + case []string: 32 + x = append(x, arg...) 33 + case string: 34 + x = append(x, arg) 35 + default: 36 + panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg)) 37 + } 38 + } 39 + return x 40 + } 41 + 42 + // ToFold returns a string with the property that 43 + // strings.EqualFold(s, t) iff ToFold(s) == ToFold(t) 44 + // This lets us test a large set of strings for fold-equivalent 45 + // duplicates without making a quadratic number of calls 46 + // to EqualFold. Note that strings.ToUpper and strings.ToLower 47 + // do not have the desired property in some corner cases. 48 + func ToFold(s string) string { 49 + // Fast path: all ASCII, no upper case. 50 + // Most paths look like this already. 51 + for i := 0; i < len(s); i++ { 52 + c := s[i] 53 + if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { 54 + goto Slow 55 + } 56 + } 57 + return s 58 + 59 + Slow: 60 + var buf bytes.Buffer 61 + for _, r := range s { 62 + // SimpleFold(x) cycles to the next equivalent rune > x 63 + // or wraps around to smaller values. Iterate until it wraps, 64 + // and we've found the minimum value. 65 + for { 66 + r0 := r 67 + r = unicode.SimpleFold(r0) 68 + if r <= r0 { 69 + break 70 + } 71 + } 72 + // Exception to allow fast path above: A-Z => a-z 73 + if 'A' <= r && r <= 'Z' { 74 + r += 'a' - 'A' 75 + } 76 + buf.WriteRune(r) 77 + } 78 + return buf.String() 79 + } 80 + 81 + // FoldDup reports a pair of strings from the list that are 82 + // equal according to strings.EqualFold. 83 + // It returns "", "" if there are no such strings. 84 + func FoldDup(list []string) (string, string) { 85 + clash := map[string]string{} 86 + for _, s := range list { 87 + fold := ToFold(s) 88 + if t := clash[fold]; t != "" { 89 + if s > t { 90 + s, t = t, s 91 + } 92 + return s, t 93 + } 94 + clash[fold] = s 95 + } 96 + return "", "" 97 + } 98 + 99 + // Contains reports whether x contains s. 100 + func Contains(x []string, s string) bool { 101 + for _, t := range x { 102 + if t == s { 103 + return true 104 + } 105 + } 106 + return false 107 + } 108 + 109 + func isSpaceByte(c byte) bool { 110 + return c == ' ' || c == '\t' || c == '\n' || c == '\r' 111 + } 112 + 113 + // SplitQuotedFields splits s into a list of fields, 114 + // allowing single or double quotes around elements. 115 + // There is no unescaping or other processing within 116 + // quoted fields. 117 + func SplitQuotedFields(s string) ([]string, error) { 118 + // Split fields allowing '' or "" around elements. 119 + // Quotes further inside the string do not count. 120 + var f []string 121 + for len(s) > 0 { 122 + for len(s) > 0 && isSpaceByte(s[0]) { 123 + s = s[1:] 124 + } 125 + if len(s) == 0 { 126 + break 127 + } 128 + // Accepted quoted string. No unescaping inside. 129 + if s[0] == '"' || s[0] == '\'' { 130 + quote := s[0] 131 + s = s[1:] 132 + i := 0 133 + for i < len(s) && s[i] != quote { 134 + i++ 135 + } 136 + if i >= len(s) { 137 + return nil, fmt.Errorf("unterminated %c string", quote) 138 + } 139 + f = append(f, s[:i]) 140 + s = s[i+1:] 141 + continue 142 + } 143 + i := 0 144 + for i < len(s) && !isSpaceByte(s[i]) { 145 + i++ 146 + } 147 + f = append(f, s[:i]) 148 + s = s[i:] 149 + } 150 + return f, nil 151 + }