github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/api/resource/suffix.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package resource 18 19 import ( 20 "strconv" 21 ) 22 23 type suffix string 24 25 // suffixer can interpret and construct suffixes. 26 type suffixer interface { 27 interpret(suffix) (base, exponent int32, fmt Format, ok bool) 28 construct(base, exponent int32, fmt Format) (s suffix, ok bool) 29 constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool) 30 } 31 32 // quantitySuffixer handles suffixes for all three formats that quantity 33 // can handle. 34 var quantitySuffixer = newSuffixer() 35 36 type bePair struct { 37 base, exponent int32 38 } 39 40 type listSuffixer struct { 41 suffixToBE map[suffix]bePair 42 beToSuffix map[bePair]suffix 43 beToSuffixBytes map[bePair][]byte 44 } 45 46 func (ls *listSuffixer) addSuffix(s suffix, pair bePair) { 47 if ls.suffixToBE == nil { 48 ls.suffixToBE = map[suffix]bePair{} 49 } 50 if ls.beToSuffix == nil { 51 ls.beToSuffix = map[bePair]suffix{} 52 } 53 if ls.beToSuffixBytes == nil { 54 ls.beToSuffixBytes = map[bePair][]byte{} 55 } 56 ls.suffixToBE[s] = pair 57 ls.beToSuffix[pair] = s 58 ls.beToSuffixBytes[pair] = []byte(s) 59 } 60 61 func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) { 62 pair, ok := ls.suffixToBE[s] 63 if !ok { 64 return 0, 0, false 65 } 66 return pair.base, pair.exponent, true 67 } 68 69 func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) { 70 s, ok = ls.beToSuffix[bePair{base, exponent}] 71 return 72 } 73 74 func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) { 75 s, ok = ls.beToSuffixBytes[bePair{base, exponent}] 76 return 77 } 78 79 type suffixHandler struct { 80 decSuffixes listSuffixer 81 binSuffixes listSuffixer 82 } 83 84 type fastLookup struct { 85 *suffixHandler 86 } 87 88 func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) { 89 switch s { 90 case "": 91 return 10, 0, DecimalSI, true 92 case "n": 93 return 10, -9, DecimalSI, true 94 case "u": 95 return 10, -6, DecimalSI, true 96 case "m": 97 return 10, -3, DecimalSI, true 98 case "k": 99 return 10, 3, DecimalSI, true 100 case "M": 101 return 10, 6, DecimalSI, true 102 case "G": 103 return 10, 9, DecimalSI, true 104 } 105 return l.suffixHandler.interpret(s) 106 } 107 108 func newSuffixer() suffixer { 109 sh := &suffixHandler{} 110 111 // IMPORTANT: if you change this section you must change fastLookup 112 113 sh.binSuffixes.addSuffix("Ki", bePair{2, 10}) 114 sh.binSuffixes.addSuffix("Mi", bePair{2, 20}) 115 sh.binSuffixes.addSuffix("Gi", bePair{2, 30}) 116 sh.binSuffixes.addSuffix("Ti", bePair{2, 40}) 117 sh.binSuffixes.addSuffix("Pi", bePair{2, 50}) 118 sh.binSuffixes.addSuffix("Ei", bePair{2, 60}) 119 // Don't emit an error when trying to produce 120 // a suffix for 2^0. 121 sh.decSuffixes.addSuffix("", bePair{2, 0}) 122 123 sh.decSuffixes.addSuffix("n", bePair{10, -9}) 124 sh.decSuffixes.addSuffix("u", bePair{10, -6}) 125 sh.decSuffixes.addSuffix("m", bePair{10, -3}) 126 sh.decSuffixes.addSuffix("", bePair{10, 0}) 127 sh.decSuffixes.addSuffix("k", bePair{10, 3}) 128 sh.decSuffixes.addSuffix("M", bePair{10, 6}) 129 sh.decSuffixes.addSuffix("G", bePair{10, 9}) 130 sh.decSuffixes.addSuffix("T", bePair{10, 12}) 131 sh.decSuffixes.addSuffix("P", bePair{10, 15}) 132 sh.decSuffixes.addSuffix("E", bePair{10, 18}) 133 134 return fastLookup{sh} 135 } 136 137 func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) { 138 switch fmt { 139 case DecimalSI: 140 return sh.decSuffixes.construct(base, exponent) 141 case BinarySI: 142 return sh.binSuffixes.construct(base, exponent) 143 case DecimalExponent: 144 if base != 10 { 145 return "", false 146 } 147 if exponent == 0 { 148 return "", true 149 } 150 return suffix("e" + strconv.FormatInt(int64(exponent), 10)), true 151 } 152 return "", false 153 } 154 155 func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) { 156 switch format { 157 case DecimalSI: 158 return sh.decSuffixes.constructBytes(base, exponent) 159 case BinarySI: 160 return sh.binSuffixes.constructBytes(base, exponent) 161 case DecimalExponent: 162 if base != 10 { 163 return nil, false 164 } 165 if exponent == 0 { 166 return nil, true 167 } 168 result := make([]byte, 8) 169 result[0] = 'e' 170 number := strconv.AppendInt(result[1:1], int64(exponent), 10) 171 if &result[1] == &number[0] { 172 return result[:1+len(number)], true 173 } 174 result = append(result[:1], number...) 175 return result, true 176 } 177 return nil, false 178 } 179 180 func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) { 181 // Try lookup tables first 182 if b, e, ok := sh.decSuffixes.lookup(suffix); ok { 183 return b, e, DecimalSI, true 184 } 185 if b, e, ok := sh.binSuffixes.lookup(suffix); ok { 186 return b, e, BinarySI, true 187 } 188 189 if len(suffix) > 1 && (suffix[0] == 'E' || suffix[0] == 'e') { 190 parsed, err := strconv.ParseInt(string(suffix[1:]), 10, 64) 191 if err != nil { 192 return 0, 0, DecimalExponent, false 193 } 194 return 10, int32(parsed), DecimalExponent, true 195 } 196 197 return 0, 0, DecimalExponent, false 198 }