2 Copyright 2014 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
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)
32 // quantitySuffixer handles suffixes for all three formats that quantity
34 var quantitySuffixer = newSuffixer()
40 type listSuffixer struct {
41 suffixToBE map[suffix]bePair
42 beToSuffix map[bePair]suffix
43 beToSuffixBytes map[bePair][]byte
46 func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
47 if ls.suffixToBE == nil {
48 ls.suffixToBE = map[suffix]bePair{}
50 if ls.beToSuffix == nil {
51 ls.beToSuffix = map[bePair]suffix{}
53 if ls.beToSuffixBytes == nil {
54 ls.beToSuffixBytes = map[bePair][]byte{}
56 ls.suffixToBE[s] = pair
57 ls.beToSuffix[pair] = s
58 ls.beToSuffixBytes[pair] = []byte(s)
61 func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) {
62 pair, ok := ls.suffixToBE[s]
66 return pair.base, pair.exponent, true
69 func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) {
70 s, ok = ls.beToSuffix[bePair{base, exponent}]
74 func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) {
75 s, ok = ls.beToSuffixBytes[bePair{base, exponent}]
79 type suffixHandler struct {
80 decSuffixes listSuffixer
81 binSuffixes listSuffixer
84 type fastLookup struct {
88 func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) {
91 return 10, 0, DecimalSI, true
93 return 10, -9, DecimalSI, true
95 return 10, -6, DecimalSI, true
97 return 10, -3, DecimalSI, true
99 return 10, 3, DecimalSI, true
101 return 10, 6, DecimalSI, true
103 return 10, 9, DecimalSI, true
105 return l.suffixHandler.interpret(s)
108 func newSuffixer() suffixer {
109 sh := &suffixHandler{}
111 // IMPORTANT: if you change this section you must change fastLookup
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
121 sh.decSuffixes.addSuffix("", bePair{2, 0})
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})
134 return fastLookup{sh}
137 func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) {
140 return sh.decSuffixes.construct(base, exponent)
142 return sh.binSuffixes.construct(base, exponent)
143 case DecimalExponent:
150 return suffix("e" + strconv.FormatInt(int64(exponent), 10)), true
155 func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) {
158 return sh.decSuffixes.constructBytes(base, exponent)
160 return sh.binSuffixes.constructBytes(base, exponent)
161 case DecimalExponent:
168 result := make([]byte, 8, 8)
170 number := strconv.AppendInt(result[1:1], int64(exponent), 10)
171 if &result[1] == &number[0] {
172 return result[:1+len(number)], true
174 result = append(result[:1], number...)
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
185 if b, e, ok := sh.binSuffixes.lookup(suffix); ok {
186 return b, e, BinarySI, true
189 if len(suffix) > 1 && (suffix[0] == 'E' || suffix[0] == 'e') {
190 parsed, err := strconv.ParseInt(string(suffix[1:]), 10, 64)
192 return 0, 0, DecimalExponent, false
194 return 10, int32(parsed), DecimalExponent, true
197 return 0, 0, DecimalExponent, false