xref: /aosp_15_r20/build/blueprint/proptools/proptools.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage proptools
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
19*1fa6dee9SAndroid Build Coastguard Worker	"strings"
20*1fa6dee9SAndroid Build Coastguard Worker	"unicode"
21*1fa6dee9SAndroid Build Coastguard Worker	"unicode/utf8"
22*1fa6dee9SAndroid Build Coastguard Worker)
23*1fa6dee9SAndroid Build Coastguard Worker
24*1fa6dee9SAndroid Build Coastguard Worker// PropertyNameForField converts the name of a field in property struct to the property name that
25*1fa6dee9SAndroid Build Coastguard Worker// might appear in a Blueprints file.  Since the property struct fields must always be exported
26*1fa6dee9SAndroid Build Coastguard Worker// to be accessed with reflection and the canonical Blueprints style is lowercased names, it
27*1fa6dee9SAndroid Build Coastguard Worker// lower cases the first rune in the field name unless the field name contains an uppercase rune
28*1fa6dee9SAndroid Build Coastguard Worker// after the first rune (which is always uppercase), and no lowercase runes.
29*1fa6dee9SAndroid Build Coastguard Workerfunc PropertyNameForField(fieldName string) string {
30*1fa6dee9SAndroid Build Coastguard Worker	r, size := utf8.DecodeRuneInString(fieldName)
31*1fa6dee9SAndroid Build Coastguard Worker	propertyName := string(unicode.ToLower(r))
32*1fa6dee9SAndroid Build Coastguard Worker	if size == len(fieldName) {
33*1fa6dee9SAndroid Build Coastguard Worker		return propertyName
34*1fa6dee9SAndroid Build Coastguard Worker	}
35*1fa6dee9SAndroid Build Coastguard Worker	if strings.IndexFunc(fieldName[size:], unicode.IsLower) == -1 &&
36*1fa6dee9SAndroid Build Coastguard Worker		strings.IndexFunc(fieldName[size:], unicode.IsUpper) != -1 {
37*1fa6dee9SAndroid Build Coastguard Worker		return fieldName
38*1fa6dee9SAndroid Build Coastguard Worker	}
39*1fa6dee9SAndroid Build Coastguard Worker	if len(fieldName) > size {
40*1fa6dee9SAndroid Build Coastguard Worker		propertyName += fieldName[size:]
41*1fa6dee9SAndroid Build Coastguard Worker	}
42*1fa6dee9SAndroid Build Coastguard Worker	return propertyName
43*1fa6dee9SAndroid Build Coastguard Worker}
44*1fa6dee9SAndroid Build Coastguard Worker
45*1fa6dee9SAndroid Build Coastguard Worker// FieldNameForProperty converts the name of a property that might appear in a Blueprints file to
46*1fa6dee9SAndroid Build Coastguard Worker// the name of a field in property struct by uppercasing the first rune.
47*1fa6dee9SAndroid Build Coastguard Workerfunc FieldNameForProperty(propertyName string) string {
48*1fa6dee9SAndroid Build Coastguard Worker	r, size := utf8.DecodeRuneInString(propertyName)
49*1fa6dee9SAndroid Build Coastguard Worker	fieldName := string(unicode.ToUpper(r))
50*1fa6dee9SAndroid Build Coastguard Worker	if len(propertyName) > size {
51*1fa6dee9SAndroid Build Coastguard Worker		fieldName += propertyName[size:]
52*1fa6dee9SAndroid Build Coastguard Worker	}
53*1fa6dee9SAndroid Build Coastguard Worker	return fieldName
54*1fa6dee9SAndroid Build Coastguard Worker}
55*1fa6dee9SAndroid Build Coastguard Worker
56*1fa6dee9SAndroid Build Coastguard Worker// Clear takes a pointer to a field and clears the value pointed to by the pointer with zero value.
57*1fa6dee9SAndroid Build Coastguard Workerfunc Clear[T any](ptr *T) {
58*1fa6dee9SAndroid Build Coastguard Worker	var zeroValue T
59*1fa6dee9SAndroid Build Coastguard Worker	*ptr = zeroValue
60*1fa6dee9SAndroid Build Coastguard Worker}
61*1fa6dee9SAndroid Build Coastguard Worker
62*1fa6dee9SAndroid Build Coastguard Worker// BoolPtr returns a pointer to a new bool containing the given value.
63*1fa6dee9SAndroid Build Coastguard Workerfunc BoolPtr(b bool) *bool {
64*1fa6dee9SAndroid Build Coastguard Worker	return &b
65*1fa6dee9SAndroid Build Coastguard Worker}
66*1fa6dee9SAndroid Build Coastguard Worker
67*1fa6dee9SAndroid Build Coastguard Worker// Int64Ptr returns a pointer to a new int64 containing the given value.
68*1fa6dee9SAndroid Build Coastguard Workerfunc Int64Ptr(i int64) *int64 {
69*1fa6dee9SAndroid Build Coastguard Worker	b := int64(i)
70*1fa6dee9SAndroid Build Coastguard Worker	return &(b)
71*1fa6dee9SAndroid Build Coastguard Worker}
72*1fa6dee9SAndroid Build Coastguard Worker
73*1fa6dee9SAndroid Build Coastguard Worker// StringPtr returns a pointer to a new string containing the given value.
74*1fa6dee9SAndroid Build Coastguard Workerfunc StringPtr(s string) *string {
75*1fa6dee9SAndroid Build Coastguard Worker	return &s
76*1fa6dee9SAndroid Build Coastguard Worker}
77*1fa6dee9SAndroid Build Coastguard Worker
78*1fa6dee9SAndroid Build Coastguard Worker// BoolDefault takes a pointer to a bool and returns the value pointed to by the pointer if it is non-nil,
79*1fa6dee9SAndroid Build Coastguard Worker// or def if the pointer is nil.
80*1fa6dee9SAndroid Build Coastguard Workerfunc BoolDefault(b *bool, def bool) bool {
81*1fa6dee9SAndroid Build Coastguard Worker	if b != nil {
82*1fa6dee9SAndroid Build Coastguard Worker		return *b
83*1fa6dee9SAndroid Build Coastguard Worker	}
84*1fa6dee9SAndroid Build Coastguard Worker	return def
85*1fa6dee9SAndroid Build Coastguard Worker}
86*1fa6dee9SAndroid Build Coastguard Worker
87*1fa6dee9SAndroid Build Coastguard Worker// Bool takes a pointer to a bool and returns true iff the pointer is non-nil and points to a true
88*1fa6dee9SAndroid Build Coastguard Worker// value.
89*1fa6dee9SAndroid Build Coastguard Workerfunc Bool(b *bool) bool {
90*1fa6dee9SAndroid Build Coastguard Worker	return BoolDefault(b, false)
91*1fa6dee9SAndroid Build Coastguard Worker}
92*1fa6dee9SAndroid Build Coastguard Worker
93*1fa6dee9SAndroid Build Coastguard Worker// String takes a pointer to a string and returns the value of the string if the pointer is non-nil,
94*1fa6dee9SAndroid Build Coastguard Worker// or def if the pointer is nil.
95*1fa6dee9SAndroid Build Coastguard Workerfunc StringDefault(s *string, def string) string {
96*1fa6dee9SAndroid Build Coastguard Worker	if s != nil {
97*1fa6dee9SAndroid Build Coastguard Worker		return *s
98*1fa6dee9SAndroid Build Coastguard Worker	}
99*1fa6dee9SAndroid Build Coastguard Worker	return def
100*1fa6dee9SAndroid Build Coastguard Worker}
101*1fa6dee9SAndroid Build Coastguard Worker
102*1fa6dee9SAndroid Build Coastguard Worker// String takes a pointer to a string and returns the value of the string if the pointer is non-nil,
103*1fa6dee9SAndroid Build Coastguard Worker// or an empty string.
104*1fa6dee9SAndroid Build Coastguard Workerfunc String(s *string) string {
105*1fa6dee9SAndroid Build Coastguard Worker	return StringDefault(s, "")
106*1fa6dee9SAndroid Build Coastguard Worker}
107*1fa6dee9SAndroid Build Coastguard Worker
108*1fa6dee9SAndroid Build Coastguard Worker// Slice takes a pointer to a slice and returns the value of the slice if the pointer is non-nil,
109*1fa6dee9SAndroid Build Coastguard Worker// or a nil slice.
110*1fa6dee9SAndroid Build Coastguard Workerfunc Slice[T any](s *[]T) []T {
111*1fa6dee9SAndroid Build Coastguard Worker	if s != nil {
112*1fa6dee9SAndroid Build Coastguard Worker		return *s
113*1fa6dee9SAndroid Build Coastguard Worker	}
114*1fa6dee9SAndroid Build Coastguard Worker	return nil
115*1fa6dee9SAndroid Build Coastguard Worker}
116*1fa6dee9SAndroid Build Coastguard Worker
117*1fa6dee9SAndroid Build Coastguard Worker// IntDefault takes a pointer to an int64 and returns the value pointed to by the pointer cast to int
118*1fa6dee9SAndroid Build Coastguard Worker// if it is non-nil, or def if the pointer is nil.
119*1fa6dee9SAndroid Build Coastguard Workerfunc IntDefault(i *int64, def int) int {
120*1fa6dee9SAndroid Build Coastguard Worker	if i != nil {
121*1fa6dee9SAndroid Build Coastguard Worker		return int(*i)
122*1fa6dee9SAndroid Build Coastguard Worker	}
123*1fa6dee9SAndroid Build Coastguard Worker	return def
124*1fa6dee9SAndroid Build Coastguard Worker}
125*1fa6dee9SAndroid Build Coastguard Worker
126*1fa6dee9SAndroid Build Coastguard Worker// Int takes a pointer to an int64 and returns the value pointed to by the pointer cast to int
127*1fa6dee9SAndroid Build Coastguard Worker// if it is non-nil, or 0 if the pointer is nil.
128*1fa6dee9SAndroid Build Coastguard Workerfunc Int(i *int64) int {
129*1fa6dee9SAndroid Build Coastguard Worker	return IntDefault(i, 0)
130*1fa6dee9SAndroid Build Coastguard Worker}
131*1fa6dee9SAndroid Build Coastguard Worker
132*1fa6dee9SAndroid Build Coastguard Workerfunc isStruct(t reflect.Type) bool {
133*1fa6dee9SAndroid Build Coastguard Worker	return t.Kind() == reflect.Struct
134*1fa6dee9SAndroid Build Coastguard Worker}
135*1fa6dee9SAndroid Build Coastguard Worker
136*1fa6dee9SAndroid Build Coastguard Workerfunc isStructPtr(t reflect.Type) bool {
137*1fa6dee9SAndroid Build Coastguard Worker	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
138*1fa6dee9SAndroid Build Coastguard Worker}
139*1fa6dee9SAndroid Build Coastguard Worker
140*1fa6dee9SAndroid Build Coastguard Workerfunc isSlice(t reflect.Type) bool {
141*1fa6dee9SAndroid Build Coastguard Worker	return t.Kind() == reflect.Slice
142*1fa6dee9SAndroid Build Coastguard Worker}
143*1fa6dee9SAndroid Build Coastguard Worker
144*1fa6dee9SAndroid Build Coastguard Workerfunc isSliceOfStruct(t reflect.Type) bool {
145*1fa6dee9SAndroid Build Coastguard Worker	return isSlice(t) && isStruct(t.Elem())
146*1fa6dee9SAndroid Build Coastguard Worker}
147*1fa6dee9SAndroid Build Coastguard Worker
148*1fa6dee9SAndroid Build Coastguard Workerfunc isStringOrStringPtr(t reflect.Type) bool {
149*1fa6dee9SAndroid Build Coastguard Worker	return t.Kind() == reflect.String || (t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.String)
150*1fa6dee9SAndroid Build Coastguard Worker}
151*1fa6dee9SAndroid Build Coastguard Worker
152*1fa6dee9SAndroid Build Coastguard Workerfunc isMapOfStruct(t reflect.Type) bool {
153*1fa6dee9SAndroid Build Coastguard Worker	return t.Kind() == reflect.Map && isStruct(t.Elem())
154*1fa6dee9SAndroid Build Coastguard Worker}
155*1fa6dee9SAndroid Build Coastguard Worker
156*1fa6dee9SAndroid Build Coastguard Workerfunc isConfigurable(t reflect.Type) bool {
157*1fa6dee9SAndroid Build Coastguard Worker	return isStruct(t) && t.NumField() > 0 && typeFields(t)[0].Type == configurableMarkerType
158*1fa6dee9SAndroid Build Coastguard Worker}
159*1fa6dee9SAndroid Build Coastguard Worker
160*1fa6dee9SAndroid Build Coastguard Workerfunc IsConfigurable(t reflect.Type) bool {
161*1fa6dee9SAndroid Build Coastguard Worker	return isConfigurable(t)
162*1fa6dee9SAndroid Build Coastguard Worker}
163