github.com/mergetb/u-root@v4.0.1-0.20190719191109-b70b86b73e5b+incompatible/pkg/abi/flag.go (about) 1 // Copyright 2018 Google LLC. 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 abi 16 17 import ( 18 "fmt" 19 "math" 20 "strconv" 21 "strings" 22 ) 23 24 // The Flag interface has three functions: 25 // Match, to see if a given value is covered by the Flag. 26 // Mask, to return which bits in the flag are covered. 27 // String, to print a string determined by the flag and possibly the value. 28 type Flag interface { 29 Match(uint64) bool 30 Mask() uint64 31 String(uint64) string 32 } 33 34 // A FlagSet is a slice of Flags 35 type FlagSet []Flag 36 37 // A BitFlag is one or more bits and a name. 38 // The name is printed if all bits are matched 39 // (i.e. enabled) in a value. Typically, the Value 40 // is only one bit. 41 type BitFlag struct { 42 Name string 43 Value uint64 44 } 45 46 // Match returns true if the val and the BitFlag Value 47 // are the same, i.e. the flag is set. 48 func (f *BitFlag) Match(val uint64) bool { 49 return f.Value&val == f.Value 50 } 51 52 // String returns the string value of the BitFlag. 53 // The parameter is ignored. 54 func (f *BitFlag) String(_ uint64) string { 55 return f.Name 56 } 57 58 // Mask returns a mask for the BitFlag, namely, the value. 59 func (f *BitFlag) Mask() uint64 { 60 return f.Value 61 } 62 63 // Field is used to extract named fields, e.g. the 64 // Tries field in the ChromeOS GPT. The value 65 // is masked and shifted right. We may at some 66 // point want a format string. 67 type Field struct { 68 Name string 69 BitMask uint64 70 Shift uint64 71 } 72 73 // Match always matches in a Field, regardless of value. 74 func (f *Field) Match(val uint64) bool { 75 return true 76 } 77 78 // String returns the part or the val covered by this Field. 79 // The bits are extracted, shifted, and printed as hex. 80 func (f *Field) String(val uint64) string { 81 return fmt.Sprintf("%s=%#x", f.Name, (val&f.BitMask)>>f.Shift) 82 } 83 84 // Mask returns the bits covered by the Field. 85 func (f *Field) Mask() uint64 { 86 return f.BitMask 87 } 88 89 // Value is the simplest implementation for Flags. 90 // If an entire uint64 matches the Value, then Match 91 // will be true. Note that Value could be implemented 92 // by a Field with a Mask of MaxUint64, but Value 93 // is more convenient to use. 94 type Value struct { 95 Name string 96 Value uint64 97 } 98 99 // String returns the name of the value associated with `val`. 100 func (e *Value) String(_ uint64) string { 101 return e.Name 102 } 103 104 // Match determines if a Value matches the argument, meaning the 105 // Value and the arg are the same. 106 func (e *Value) Match(val uint64) bool { 107 return e.Value == val 108 } 109 110 // Mask returns the bits covered by a Value, in this case MaxUint64. 111 func (e *Value) Mask() uint64 { 112 return math.MaxUint64 113 } 114 115 // Parse returns a pretty version of a FlagSet, using the flag names for known flags. 116 // Unknown flags are printed as numeric if the Flagset did not cover all the bits 117 // in the argument. 118 func (s FlagSet) Parse(val uint64) string { 119 var flags []string 120 var clr uint64 121 122 for _, f := range s { 123 if f.Match(val) { 124 flags = append(flags, f.String(val)) 125 val &^= f.Mask() 126 clr |= f.Mask() 127 } 128 } 129 130 // If there are bits we did not check, then print out 131 // whatever is left, *if it is non-zero*. This is a bit 132 // hokey, but at the same time, it seems the most usable. 133 // We may, later, want to print out the bits not covered. 134 // It's possible to miss bits and have val be 0 if the bits 135 // we missed are 0, as in the earlier code. 136 if clr != math.MaxUint64 && val != 0 { 137 flags = append(flags, "0x"+strconv.FormatUint(val, 16)) 138 } 139 140 return strings.Join(flags, "|") 141 }