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  }