summaryrefslogtreecommitdiff
path: root/android/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'android/util.go')
-rw-r--r--android/util.go124
1 files changed, 118 insertions, 6 deletions
diff --git a/android/util.go b/android/util.go
index b17422df3..ade851eff 100644
--- a/android/util.go
+++ b/android/util.go
@@ -16,6 +16,8 @@ package android
import (
"fmt"
+ "path/filepath"
+ "reflect"
"regexp"
"runtime"
"sort"
@@ -52,10 +54,54 @@ func JoinWithPrefix(strs []string, prefix string) string {
return string(ret)
}
-func sortedKeys(m map[string][]string) []string {
- s := make([]string, 0, len(m))
- for k := range m {
- s = append(s, k)
+func JoinWithSuffix(strs []string, suffix string, separator string) string {
+ if len(strs) == 0 {
+ return ""
+ }
+
+ if len(strs) == 1 {
+ return strs[0] + suffix
+ }
+
+ n := len(" ") * (len(strs) - 1)
+ for _, s := range strs {
+ n += len(suffix) + len(s)
+ }
+
+ ret := make([]byte, 0, n)
+ for i, s := range strs {
+ if i != 0 {
+ ret = append(ret, separator...)
+ }
+ ret = append(ret, s...)
+ ret = append(ret, suffix...)
+ }
+ return string(ret)
+}
+
+func SortedStringKeys(m interface{}) []string {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Map {
+ panic(fmt.Sprintf("%#v is not a map", m))
+ }
+ keys := v.MapKeys()
+ s := make([]string, 0, len(keys))
+ for _, key := range keys {
+ s = append(s, key.String())
+ }
+ sort.Strings(s)
+ return s
+}
+
+func SortedStringMapValues(m interface{}) []string {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Map {
+ panic(fmt.Sprintf("%#v is not a map", m))
+ }
+ keys := v.MapKeys()
+ s := make([]string, 0, len(keys))
+ for _, key := range keys {
+ s = append(s, v.MapIndex(key).String())
}
sort.Strings(s)
return s
@@ -75,8 +121,9 @@ func InList(s string, list []string) bool {
return IndexList(s, list) != -1
}
-func PrefixInList(s string, list []string) bool {
- for _, prefix := range list {
+// Returns true if the given string s is prefixed with any string in the given prefix list.
+func HasAnyPrefix(s string, prefixList []string) bool {
+ for _, prefix := range prefixList {
if strings.HasPrefix(s, prefix) {
return true
}
@@ -84,6 +131,27 @@ func PrefixInList(s string, list []string) bool {
return false
}
+// Returns true if any string in the given list has the given prefix.
+func PrefixInList(list []string, prefix string) bool {
+ for _, s := range list {
+ if strings.HasPrefix(s, prefix) {
+ return true
+ }
+ }
+ return false
+}
+
+// IndexListPred returns the index of the element which in the given `list` satisfying the predicate, or -1 if there is no such element.
+func IndexListPred(pred func(s string) bool, list []string) int {
+ for i, l := range list {
+ if pred(l) {
+ return i
+ }
+ }
+
+ return -1
+}
+
func FilterList(list []string, filter []string) (remainder []string, filtered []string) {
for _, l := range list {
if InList(l, filter) {
@@ -157,6 +225,13 @@ func LastUniqueStrings(list []string) []string {
return list[totalSkip:]
}
+// SortedUniqueStrings returns what the name says
+func SortedUniqueStrings(list []string) []string {
+ unique := FirstUniqueStrings(list)
+ sort.Strings(unique)
+ return unique
+}
+
// checkCalledFromInit panics if a Go package's init function is not on the
// call stack.
func checkCalledFromInit() {
@@ -244,6 +319,32 @@ func matchPattern(pat, str string) bool {
return strings.HasPrefix(str, pat[:i]) && strings.HasSuffix(str, pat[i+1:])
}
+var shlibVersionPattern = regexp.MustCompile("(?:\\.\\d+(?:svn)?)+")
+
+// splitFileExt splits a file name into root, suffix and ext. root stands for the file name without
+// the file extension and the version number (e.g. "libexample"). suffix stands for the
+// concatenation of the file extension and the version number (e.g. ".so.1.0"). ext stands for the
+// file extension after the version numbers are trimmed (e.g. ".so").
+func SplitFileExt(name string) (string, string, string) {
+ // Extract and trim the shared lib version number if the file name ends with dot digits.
+ suffix := ""
+ matches := shlibVersionPattern.FindAllStringIndex(name, -1)
+ if len(matches) > 0 {
+ lastMatch := matches[len(matches)-1]
+ if lastMatch[1] == len(name) {
+ suffix = name[lastMatch[0]:lastMatch[1]]
+ name = name[0:lastMatch[0]]
+ }
+ }
+
+ // Extract the file name root and the file extension.
+ ext := filepath.Ext(name)
+ root := strings.TrimSuffix(name, ext)
+ suffix = ext + suffix
+
+ return root, suffix, ext
+}
+
// ShardPaths takes a Paths, and returns a slice of Paths where each one has at most shardSize paths.
func ShardPaths(paths Paths, shardSize int) []Paths {
if len(paths) == 0 {
@@ -276,3 +377,14 @@ func ShardStrings(s []string, shardSize int) [][]string {
}
return ret
}
+
+func CheckDuplicate(values []string) (duplicate string, found bool) {
+ seen := make(map[string]string)
+ for _, v := range values {
+ if duplicate, found = seen[v]; found {
+ return
+ }
+ seen[v] = v
+ }
+ return
+}