Using struct{}{} as the payload for set maps reduces memory use for large sets. Bug: 68860345 Bug: 151177513 Bug: 151953481 Test: m all Test: m systemlicense Test: m listshare; out/soong/host/linux-x86/bin/listshare ... Test: m checkshare; out/soong/host/linux-x86/bin/checkshare ... Test: m dumpgraph; out/soong/host/linux-x86/dumpgraph ... Test: m dumpresolutions; out/soong/host/linux-x86/dumpresolutions ... where ... is the path to the .meta_lic file for the system image. In my case if $ export PRODUCT=$(realpath $ANDROID_PRODUCT_OUT --relative-to=$PWD) ... can be expressed as: ${PRODUCT}/gen/META/lic_intermediates/${PRODUCT}/system.img.meta_lic Change-Id: Ibc831ae80fc50f35e1000348fb28fc0167d0ebed
279 lines
8.2 KiB
Go
279 lines
8.2 KiB
Go
// Copyright 2021 Google LLC
|
|
//
|
|
// 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 compliance
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// NewLicenseConditionSet creates a new instance or variable of *LicenseConditionSet.
|
|
func NewLicenseConditionSet(conditions ...LicenseCondition) *LicenseConditionSet {
|
|
cs := newLicenseConditionSet()
|
|
cs.Add(conditions...)
|
|
return cs
|
|
}
|
|
|
|
// LicenseConditionSet describes a mutable set of immutable license conditions.
|
|
type LicenseConditionSet struct {
|
|
// conditions describes the set of license conditions i.e. (condition name, origin target) pairs
|
|
// by mapping condition name -> origin target -> struct{}{}.
|
|
conditions map[string]map[*TargetNode]struct{}
|
|
}
|
|
|
|
// Add makes all `conditions` members of the set if they were not previously.
|
|
func (cs *LicenseConditionSet) Add(conditions ...LicenseCondition) {
|
|
if len(conditions) == 0 {
|
|
return
|
|
}
|
|
for _, lc := range conditions {
|
|
if _, ok := cs.conditions[lc.name]; !ok {
|
|
cs.conditions[lc.name] = make(map[*TargetNode]struct{})
|
|
}
|
|
cs.conditions[lc.name][lc.origin] = struct{}{}
|
|
}
|
|
}
|
|
|
|
// AddSet makes all elements of `conditions` members of the set if they were not previously.
|
|
func (cs *LicenseConditionSet) AddSet(other *LicenseConditionSet) {
|
|
if len(other.conditions) == 0 {
|
|
return
|
|
}
|
|
for name, origins := range other.conditions {
|
|
if len(origins) == 0 {
|
|
continue
|
|
}
|
|
if _, ok := cs.conditions[name]; !ok {
|
|
cs.conditions[name] = make(map[*TargetNode]struct{})
|
|
}
|
|
for origin := range origins {
|
|
cs.conditions[name][origin] = other.conditions[name][origin]
|
|
}
|
|
}
|
|
}
|
|
|
|
// ByName returns a list of the conditions in the set matching `names`.
|
|
func (cs *LicenseConditionSet) ByName(names ...ConditionNames) *LicenseConditionSet {
|
|
other := newLicenseConditionSet()
|
|
for _, cn := range names {
|
|
for _, name := range cn {
|
|
if origins, ok := cs.conditions[name]; ok {
|
|
other.conditions[name] = make(map[*TargetNode]struct{})
|
|
for origin := range origins {
|
|
other.conditions[name][origin] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// HasAnyByName returns true if the set contains any conditions matching `names` originating at any target.
|
|
func (cs *LicenseConditionSet) HasAnyByName(names ...ConditionNames) bool {
|
|
for _, cn := range names {
|
|
for _, name := range cn {
|
|
if origins, ok := cs.conditions[name]; ok {
|
|
if len(origins) > 0 {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CountByName returns the number of conditions matching `names` originating at any target.
|
|
func (cs *LicenseConditionSet) CountByName(names ...ConditionNames) int {
|
|
size := 0
|
|
for _, cn := range names {
|
|
for _, name := range cn {
|
|
if origins, ok := cs.conditions[name]; ok {
|
|
size += len(origins)
|
|
}
|
|
}
|
|
}
|
|
return size
|
|
}
|
|
|
|
// ByOrigin returns all of the conditions that originate at `origin` regardless of name.
|
|
func (cs *LicenseConditionSet) ByOrigin(origin *TargetNode) *LicenseConditionSet {
|
|
other := newLicenseConditionSet()
|
|
for name, origins := range cs.conditions {
|
|
if _, ok := origins[origin]; ok {
|
|
other.conditions[name] = make(map[*TargetNode]struct{})
|
|
other.conditions[name][origin] = struct{}{}
|
|
}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// HasAnyByOrigin returns true if the set contains any conditions originating at `origin` regardless of condition name.
|
|
func (cs *LicenseConditionSet) HasAnyByOrigin(origin *TargetNode) bool {
|
|
for _, origins := range cs.conditions {
|
|
if _, ok := origins[origin]; ok {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CountByOrigin returns the number of conditions originating at `origin` regardless of condition name.
|
|
func (cs *LicenseConditionSet) CountByOrigin(origin *TargetNode) int {
|
|
size := 0
|
|
for _, origins := range cs.conditions {
|
|
if _, ok := origins[origin]; ok {
|
|
size++
|
|
}
|
|
}
|
|
return size
|
|
}
|
|
|
|
// AsList returns a list of all the conditions in the set.
|
|
func (cs *LicenseConditionSet) AsList() ConditionList {
|
|
result := make(ConditionList, 0, cs.Count())
|
|
for name, origins := range cs.conditions {
|
|
for origin := range origins {
|
|
result = append(result, LicenseCondition{name, origin})
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Names returns a list of the names of the conditions in the set.
|
|
func (cs *LicenseConditionSet) Names() []string {
|
|
result := make([]string, 0, len(cs.conditions))
|
|
for name := range cs.conditions {
|
|
result = append(result, name)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Count returns the number of conditions in the set.
|
|
func (cs *LicenseConditionSet) Count() int {
|
|
size := 0
|
|
for _, origins := range cs.conditions {
|
|
size += len(origins)
|
|
}
|
|
return size
|
|
}
|
|
|
|
// Copy creates a new LicenseCondition variable with the same value.
|
|
func (cs *LicenseConditionSet) Copy() *LicenseConditionSet {
|
|
other := newLicenseConditionSet()
|
|
for name := range cs.conditions {
|
|
other.conditions[name] = make(map[*TargetNode]struct{})
|
|
for origin := range cs.conditions[name] {
|
|
other.conditions[name][origin] = cs.conditions[name][origin]
|
|
}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// HasCondition returns true if the set contains any condition matching both `names` and `origin`.
|
|
func (cs *LicenseConditionSet) HasCondition(names ConditionNames, origin *TargetNode) bool {
|
|
for _, name := range names {
|
|
if origins, ok := cs.conditions[name]; ok {
|
|
_, isPresent := origins[origin]
|
|
if isPresent {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsEmpty returns true when the set of conditions contains zero elements.
|
|
func (cs *LicenseConditionSet) IsEmpty() bool {
|
|
for _, origins := range cs.conditions {
|
|
if 0 < len(origins) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// RemoveAllByName changes the set to delete all conditions matching `names`.
|
|
func (cs *LicenseConditionSet) RemoveAllByName(names ...ConditionNames) {
|
|
for _, cn := range names {
|
|
for _, name := range cn {
|
|
delete(cs.conditions, name)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove changes the set to delete `conditions`.
|
|
func (cs *LicenseConditionSet) Remove(conditions ...LicenseCondition) {
|
|
for _, lc := range conditions {
|
|
if _, isPresent := cs.conditions[lc.name]; !isPresent {
|
|
panic(fmt.Errorf("attempt to remove non-existent condition: %q", lc.asString(":")))
|
|
}
|
|
if _, isPresent := cs.conditions[lc.name][lc.origin]; !isPresent {
|
|
panic(fmt.Errorf("attempt to remove non-existent origin: %q", lc.asString(":")))
|
|
}
|
|
delete(cs.conditions[lc.name], lc.origin)
|
|
}
|
|
}
|
|
|
|
// removeSet changes the set to delete all conditions also present in `other`.
|
|
func (cs *LicenseConditionSet) RemoveSet(other *LicenseConditionSet) {
|
|
for name, origins := range other.conditions {
|
|
if _, isPresent := cs.conditions[name]; !isPresent {
|
|
continue
|
|
}
|
|
for origin := range origins {
|
|
delete(cs.conditions[name], origin)
|
|
}
|
|
}
|
|
}
|
|
|
|
// compliance-only LicenseConditionSet methods
|
|
|
|
// newLicenseConditionSet constructs a set of `conditions`.
|
|
func newLicenseConditionSet() *LicenseConditionSet {
|
|
return &LicenseConditionSet{make(map[string]map[*TargetNode]struct{})}
|
|
}
|
|
|
|
// add changes the set to include each element of `conditions` originating at `origin`.
|
|
func (cs *LicenseConditionSet) add(origin *TargetNode, conditions ...string) {
|
|
for _, name := range conditions {
|
|
if _, ok := cs.conditions[name]; !ok {
|
|
cs.conditions[name] = make(map[*TargetNode]struct{})
|
|
}
|
|
cs.conditions[name][origin] = struct{}{}
|
|
}
|
|
}
|
|
|
|
// asStringList returns the conditions in the set as `separator`-separated (origin, condition-name) pair strings.
|
|
func (cs *LicenseConditionSet) asStringList(separator string) []string {
|
|
result := make([]string, 0, cs.Count())
|
|
for name, origins := range cs.conditions {
|
|
for origin := range origins {
|
|
result = append(result, origin.name+separator+name)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// conditionNamesArray implements a `contains` predicate for arrays of ConditionNames
|
|
type conditionNamesArray []ConditionNames
|
|
|
|
func (cn conditionNamesArray) contains(name string) bool {
|
|
for _, names := range cn {
|
|
if names.Contains(name) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|