Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / apimachinery / pkg / api / resource / suffix.go
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, 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 }