github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/android/util.go (about) 1 // Copyright 2015 Google Inc. All rights reserved. 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 android 16 17 import ( 18 "runtime" 19 "sort" 20 "strings" 21 ) 22 23 func JoinWithPrefix(strs []string, prefix string) string { 24 if len(strs) == 0 { 25 return "" 26 } 27 28 if len(strs) == 1 { 29 return prefix + strs[0] 30 } 31 32 n := len(" ") * (len(strs) - 1) 33 for _, s := range strs { 34 n += len(prefix) + len(s) 35 } 36 37 ret := make([]byte, 0, n) 38 for i, s := range strs { 39 if i != 0 { 40 ret = append(ret, ' ') 41 } 42 ret = append(ret, prefix...) 43 ret = append(ret, s...) 44 } 45 return string(ret) 46 } 47 48 func sortedKeys(m map[string][]string) []string { 49 s := make([]string, 0, len(m)) 50 for k := range m { 51 s = append(s, k) 52 } 53 sort.Strings(s) 54 return s 55 } 56 57 func IndexList(s string, list []string) int { 58 for i, l := range list { 59 if l == s { 60 return i 61 } 62 } 63 64 return -1 65 } 66 67 func InList(s string, list []string) bool { 68 return IndexList(s, list) != -1 69 } 70 71 func PrefixInList(s string, list []string) bool { 72 for _, prefix := range list { 73 if strings.HasPrefix(s, prefix) { 74 return true 75 } 76 } 77 return false 78 } 79 80 func FilterList(list []string, filter []string) (remainder []string, filtered []string) { 81 for _, l := range list { 82 if InList(l, filter) { 83 filtered = append(filtered, l) 84 } else { 85 remainder = append(remainder, l) 86 } 87 } 88 89 return 90 } 91 92 func RemoveListFromList(list []string, filter_out []string) (result []string) { 93 result = make([]string, 0, len(list)) 94 for _, l := range list { 95 if !InList(l, filter_out) { 96 result = append(result, l) 97 } 98 } 99 return 100 } 101 102 func RemoveFromList(s string, list []string) (bool, []string) { 103 i := IndexList(s, list) 104 if i == -1 { 105 return false, list 106 } 107 108 result := make([]string, 0, len(list)-1) 109 result = append(result, list[:i]...) 110 for _, l := range list[i+1:] { 111 if l != s { 112 result = append(result, l) 113 } 114 } 115 return true, result 116 } 117 118 // FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of 119 // each. It modifies the slice contents in place, and returns a subslice of the original slice. 120 func FirstUniqueStrings(list []string) []string { 121 k := 0 122 outer: 123 for i := 0; i < len(list); i++ { 124 for j := 0; j < k; j++ { 125 if list[i] == list[j] { 126 continue outer 127 } 128 } 129 list[k] = list[i] 130 k++ 131 } 132 return list[:k] 133 } 134 135 // LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of 136 // each. It modifies the slice contents in place, and returns a subslice of the original slice. 137 func LastUniqueStrings(list []string) []string { 138 totalSkip := 0 139 for i := len(list) - 1; i >= totalSkip; i-- { 140 skip := 0 141 for j := i - 1; j >= totalSkip; j-- { 142 if list[i] == list[j] { 143 skip++ 144 } else { 145 list[j+skip] = list[j] 146 } 147 } 148 totalSkip += skip 149 } 150 return list[totalSkip:] 151 } 152 153 // checkCalledFromInit panics if a Go package's init function is not on the 154 // call stack. 155 func checkCalledFromInit() { 156 for skip := 3; ; skip++ { 157 _, funcName, ok := callerName(skip) 158 if !ok { 159 panic("not called from an init func") 160 } 161 162 if funcName == "init" || strings.HasPrefix(funcName, "init·") { 163 return 164 } 165 } 166 } 167 168 // callerName returns the package path and function name of the calling 169 // function. The skip argument has the same meaning as the skip argument of 170 // runtime.Callers. 171 func callerName(skip int) (pkgPath, funcName string, ok bool) { 172 var pc [1]uintptr 173 n := runtime.Callers(skip+1, pc[:]) 174 if n != 1 { 175 return "", "", false 176 } 177 178 f := runtime.FuncForPC(pc[0]) 179 fullName := f.Name() 180 181 lastDotIndex := strings.LastIndex(fullName, ".") 182 if lastDotIndex == -1 { 183 panic("unable to distinguish function name from package") 184 } 185 186 if fullName[lastDotIndex-1] == ')' { 187 // The caller is a method on some type, so it's name looks like 188 // "pkg/path.(type).method". We need to go back one dot farther to get 189 // to the package name. 190 lastDotIndex = strings.LastIndex(fullName[:lastDotIndex], ".") 191 } 192 193 pkgPath = fullName[:lastDotIndex] 194 funcName = fullName[lastDotIndex+1:] 195 ok = true 196 return 197 } 198 199 func GetNumericSdkVersion(v string) string { 200 if strings.Contains(v, "system_") { 201 return strings.Replace(v, "system_", "", 1) 202 } 203 return v 204 }