Move first/last unique elements utility functions to android package
Move firstUniqueElements to android.FirstUniqueStrings,
lastUniqueElements to android.LastUniqueStrings, and lastUniquePaths
to android.LastUniquePaths.
Test: m checkbuild
Change-Id: Ieac840405126c7f8f98afb4a4ef35c01a18fe7fb
diff --git a/Android.bp b/Android.bp
index 1f6ebe2..3badfcd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -67,6 +67,7 @@
"android/expand_test.go",
"android/paths_test.go",
"android/prebuilt_test.go",
+ "android/util_test.go",
"android/variable_test.go",
],
}
diff --git a/android/paths.go b/android/paths.go
index 7443547..d6a1c66 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -286,8 +286,8 @@
return ret
}
-// FirstUniqueElements returns all unique elements of a slice, keeping the first copy of each
-// modifies the slice contents in place, and returns a subslice of the original slice
+// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each. It
+// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func FirstUniquePaths(list Paths) Paths {
k := 0
outer:
@@ -303,6 +303,24 @@
return list[:k]
}
+// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each. It
+// modifies the Paths slice contents in place, and returns a subslice of the original slice.
+func LastUniquePaths(list Paths) Paths {
+ totalSkip := 0
+ for i := len(list) - 1; i >= totalSkip; i-- {
+ skip := 0
+ for j := i - 1; j >= totalSkip; j-- {
+ if list[i] == list[j] {
+ skip++
+ } else {
+ list[j+skip] = list[j]
+ }
+ }
+ totalSkip += skip
+ }
+ return list[totalSkip:]
+}
+
func indexPathList(s Path, list []Path) int {
for i, l := range list {
if l == s {
diff --git a/android/util.go b/android/util.go
index 80c7870..4d30a74 100644
--- a/android/util.go
+++ b/android/util.go
@@ -77,6 +77,41 @@
return false
}
+// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
+// each. It modifies the slice contents in place, and returns a subslice of the original slice.
+func FirstUniqueStrings(list []string) []string {
+ k := 0
+outer:
+ for i := 0; i < len(list); i++ {
+ for j := 0; j < k; j++ {
+ if list[i] == list[j] {
+ continue outer
+ }
+ }
+ list[k] = list[i]
+ k++
+ }
+ return list[:k]
+}
+
+// LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of
+// each. It modifies the slice contents in place, and returns a subslice of the original slice.
+func LastUniqueStrings(list []string) []string {
+ totalSkip := 0
+ for i := len(list) - 1; i >= totalSkip; i-- {
+ skip := 0
+ for j := i - 1; j >= totalSkip; j-- {
+ if list[i] == list[j] {
+ skip++
+ } else {
+ list[j+skip] = list[j]
+ }
+ }
+ totalSkip += skip
+ }
+ return list[totalSkip:]
+}
+
// checkCalledFromInit panics if a Go package's init function is not on the
// call stack.
func checkCalledFromInit() {
diff --git a/android/util_test.go b/android/util_test.go
new file mode 100644
index 0000000..32f92b4
--- /dev/null
+++ b/android/util_test.go
@@ -0,0 +1,120 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "reflect"
+ "testing"
+)
+
+var firstUniqueStringsTestCases = []struct {
+ in []string
+ out []string
+}{
+ {
+ in: []string{"a"},
+ out: []string{"a"},
+ },
+ {
+ in: []string{"a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"a", "a"},
+ out: []string{"a"},
+ },
+ {
+ in: []string{"a", "b", "a"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"b", "a", "a"},
+ out: []string{"b", "a"},
+ },
+ {
+ in: []string{"a", "a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"a", "b", "a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
+ out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
+ },
+}
+
+func TestFirstUniqueStrings(t *testing.T) {
+ for _, testCase := range firstUniqueStringsTestCases {
+ out := FirstUniqueStrings(testCase.in)
+ if !reflect.DeepEqual(out, testCase.out) {
+ t.Errorf("incorrect output:")
+ t.Errorf(" input: %#v", testCase.in)
+ t.Errorf(" expected: %#v", testCase.out)
+ t.Errorf(" got: %#v", out)
+ }
+ }
+}
+
+var lastUniqueStringsTestCases = []struct {
+ in []string
+ out []string
+}{
+ {
+ in: []string{"a"},
+ out: []string{"a"},
+ },
+ {
+ in: []string{"a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"a", "a"},
+ out: []string{"a"},
+ },
+ {
+ in: []string{"a", "b", "a"},
+ out: []string{"b", "a"},
+ },
+ {
+ in: []string{"b", "a", "a"},
+ out: []string{"b", "a"},
+ },
+ {
+ in: []string{"a", "a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"a", "b", "a", "b"},
+ out: []string{"a", "b"},
+ },
+ {
+ in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
+ out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
+ },
+}
+
+func TestLastUniqueStrings(t *testing.T) {
+ for _, testCase := range lastUniqueStringsTestCases {
+ out := LastUniqueStrings(testCase.in)
+ if !reflect.DeepEqual(out, testCase.out) {
+ t.Errorf("incorrect output:")
+ t.Errorf(" input: %#v", testCase.in)
+ t.Errorf(" expected: %#v", testCase.out)
+ t.Errorf(" got: %#v", out)
+ }
+ }
+}
diff --git a/cc/cc.go b/cc/cc.go
index 7163696..36b97e1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -561,7 +561,7 @@
orderedAllDeps = append(orderedAllDeps, transitiveDeps[dep]...)
}
- orderedAllDeps = lastUniquePaths(orderedAllDeps)
+ orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
// We don't want to add any new dependencies into directDeps (to allow the caller to
// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
@@ -763,12 +763,12 @@
deps = feature.deps(ctx, deps)
}
- deps.WholeStaticLibs = lastUniqueElements(deps.WholeStaticLibs)
- deps.StaticLibs = lastUniqueElements(deps.StaticLibs)
- deps.LateStaticLibs = lastUniqueElements(deps.LateStaticLibs)
- deps.SharedLibs = lastUniqueElements(deps.SharedLibs)
- deps.LateSharedLibs = lastUniqueElements(deps.LateSharedLibs)
- deps.HeaderLibs = lastUniqueElements(deps.HeaderLibs)
+ deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
+ deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
+ deps.LateStaticLibs = android.LastUniqueStrings(deps.LateStaticLibs)
+ deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
+ deps.LateSharedLibs = android.LastUniqueStrings(deps.LateSharedLibs)
+ deps.HeaderLibs = android.LastUniqueStrings(deps.HeaderLibs)
for _, lib := range deps.ReexportSharedLibHeaders {
if !inList(lib, deps.SharedLibs) {
@@ -1249,13 +1249,13 @@
depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps)...)
// Dedup exported flags from dependencies
- depPaths.Flags = firstUniqueElements(depPaths.Flags)
+ depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
- depPaths.ReexportedFlags = firstUniqueElements(depPaths.ReexportedFlags)
+ depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
depPaths.ReexportedFlagsDeps = android.FirstUniquePaths(depPaths.ReexportedFlagsDeps)
if c.sabi != nil {
- c.sabi.Properties.ReexportedIncludeFlags = firstUniqueElements(c.sabi.Properties.ReexportedIncludeFlags)
+ c.sabi.Properties.ReexportedIncludeFlags = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludeFlags)
}
return depPaths
@@ -1438,58 +1438,6 @@
}
}
-// firstUniqueElements returns all unique elements of a slice, keeping the first copy of each
-// modifies the slice contents in place, and returns a subslice of the original slice
-func firstUniqueElements(list []string) []string {
- k := 0
-outer:
- for i := 0; i < len(list); i++ {
- for j := 0; j < k; j++ {
- if list[i] == list[j] {
- continue outer
- }
- }
- list[k] = list[i]
- k++
- }
- return list[:k]
-}
-
-// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each.
-// It modifies the slice contents in place, and returns a subslice of the original slice
-func lastUniqueElements(list []string) []string {
- totalSkip := 0
- for i := len(list) - 1; i >= totalSkip; i-- {
- skip := 0
- for j := i - 1; j >= totalSkip; j-- {
- if list[i] == list[j] {
- skip++
- } else {
- list[j+skip] = list[j]
- }
- }
- totalSkip += skip
- }
- return list[totalSkip:]
-}
-
-// lastUniquePaths is the same as lastUniqueElements but uses Path structs
-func lastUniquePaths(list []android.Path) []android.Path {
- totalSkip := 0
- for i := len(list) - 1; i >= totalSkip; i-- {
- skip := 0
- for j := i - 1; j >= totalSkip; j-- {
- if list[i] == list[j] {
- skip++
- } else {
- list[j+skip] = list[j]
- }
- }
- totalSkip += skip
- }
- return list[totalSkip:]
-}
-
func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
if ctx.AConfig().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index dc04a4e..35274f0 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -156,106 +156,6 @@
}
}
-var firstUniqueElementsTestCases = []struct {
- in []string
- out []string
-}{
- {
- in: []string{"a"},
- out: []string{"a"},
- },
- {
- in: []string{"a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"a", "a"},
- out: []string{"a"},
- },
- {
- in: []string{"a", "b", "a"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"b", "a", "a"},
- out: []string{"b", "a"},
- },
- {
- in: []string{"a", "a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"a", "b", "a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
- out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
- },
-}
-
-func TestFirstUniqueElements(t *testing.T) {
- for _, testCase := range firstUniqueElementsTestCases {
- out := firstUniqueElements(testCase.in)
- if !reflect.DeepEqual(out, testCase.out) {
- t.Errorf("incorrect output:")
- t.Errorf(" input: %#v", testCase.in)
- t.Errorf(" expected: %#v", testCase.out)
- t.Errorf(" got: %#v", out)
- }
- }
-}
-
-var lastUniqueElementsTestCases = []struct {
- in []string
- out []string
-}{
- {
- in: []string{"a"},
- out: []string{"a"},
- },
- {
- in: []string{"a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"a", "a"},
- out: []string{"a"},
- },
- {
- in: []string{"a", "b", "a"},
- out: []string{"b", "a"},
- },
- {
- in: []string{"b", "a", "a"},
- out: []string{"b", "a"},
- },
- {
- in: []string{"a", "a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"a", "b", "a", "b"},
- out: []string{"a", "b"},
- },
- {
- in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
- out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
- },
-}
-
-func TestLastUniqueElements(t *testing.T) {
- for _, testCase := range lastUniqueElementsTestCases {
- out := lastUniqueElements(testCase.in)
- if !reflect.DeepEqual(out, testCase.out) {
- t.Errorf("incorrect output:")
- t.Errorf(" input: %#v", testCase.in)
- t.Errorf(" expected: %#v", testCase.out)
- t.Errorf(" got: %#v", out)
- }
- }
-}
-
var (
str11 = "01234567891"
str10 = str11[:10]