github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/man/bigbytes.go (about)

     1  package man
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"strings"
     7  	"unicode"
     8  )
     9  
    10  var (
    11  	bigIECExp = big.NewInt(1024)
    12  
    13  	// BigByte is one byte in bit.Ints
    14  	BigByte = big.NewInt(1)
    15  	// BigKiByte is 1,024 bytes in bit.Ints
    16  	BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp)
    17  	// BigMiByte is 1,024 k bytes in bit.Ints
    18  	BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp)
    19  	// BigGiByte is 1,024 m bytes in bit.Ints
    20  	BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp)
    21  	// BigTiByte is 1,024 g bytes in bit.Ints
    22  	BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp)
    23  	// BigPiByte is 1,024 t bytes in bit.Ints
    24  	BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp)
    25  	// BigEiByte is 1,024 p bytes in bit.Ints
    26  	BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp)
    27  	// BigZiByte is 1,024 e bytes in bit.Ints
    28  	BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp)
    29  	// BigYiByte is 1,024 z bytes in bit.Ints
    30  	BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp)
    31  )
    32  
    33  var (
    34  	bigSIExp = big.NewInt(1000)
    35  
    36  	// BigSIByte is one SI byte in big.Ints
    37  	BigSIByte = big.NewInt(1)
    38  	// BigKByte is 1,000 SI bytes in big.Ints
    39  	BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp)
    40  	// BigMByte is 1,000 SI k bytes in big.Ints
    41  	BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp)
    42  	// BigGByte is 1,000 SI m bytes in big.Ints
    43  	BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp)
    44  	// BigTByte is 1,000 SI g bytes in big.Ints
    45  	BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp)
    46  	// BigPByte is 1,000 SI t bytes in big.Ints
    47  	BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp)
    48  	// BigEByte is 1,000 SI p bytes in big.Ints
    49  	BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp)
    50  	// BigZByte is 1,000 SI e bytes in big.Ints
    51  	BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp)
    52  	// BigYByte is 1,000 SI z bytes in big.Ints
    53  	BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp)
    54  )
    55  
    56  var bigBytesSizeTable = map[string]*big.Int{
    57  	"b": BigByte, "kib": BigKiByte, "kb": BigKByte, "mib": BigMiByte, "mb": BigMByte,
    58  	"gib": BigGiByte, "gb": BigGByte, "tib": BigTiByte, "tb": BigTByte, "pib": BigPiByte,
    59  	"pb": BigPByte, "eib": BigEiByte, "eb": BigEByte, "zib": BigZiByte, "zb": BigZByte,
    60  	"yib": BigYiByte, "yb": BigYByte,
    61  	// Without suffix
    62  	"": BigByte, "ki": BigKiByte, "k": BigKByte, "mi": BigMiByte, "m": BigMByte,
    63  	"gi": BigGiByte, "g": BigGByte, "ti": BigTiByte, "t": BigTByte, "pi": BigPiByte,
    64  	"p": BigPByte, "ei": BigEiByte, "e": BigEByte, "z": BigZByte, "zi": BigZiByte,
    65  	"y": BigYByte, "yi": BigYiByte,
    66  }
    67  
    68  var ten = big.NewInt(10)
    69  
    70  func humanateBigBytes(s, base *big.Int, sizes []string) string {
    71  	if s.Cmp(ten) < 0 {
    72  		return fmt.Sprintf("%dB", s)
    73  	}
    74  	c := (&big.Int{}).Set(s)
    75  	val, mag := oomm(c, base, len(sizes)-1)
    76  	suffix := sizes[mag]
    77  	f := strings.TrimSuffix(fmt.Sprintf("%.1f", val), ".0")
    78  	return f + suffix
    79  }
    80  
    81  // BigBytes produces a human readable representation of an SI size.
    82  //
    83  // See also: ParseBigBytes.
    84  //
    85  // BigBytes(82854982) -> 83MB
    86  func BigBytes(s *big.Int) string {
    87  	sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
    88  	return humanateBigBytes(s, bigSIExp, sizes)
    89  }
    90  
    91  // BigIBytes produces a human readable representation of an IEC size.
    92  //
    93  // See also: ParseBigBytes.
    94  //
    95  // BigIBytes(82854982) -> 79MiB
    96  func BigIBytes(s *big.Int) string {
    97  	sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
    98  	return humanateBigBytes(s, bigIECExp, sizes)
    99  }
   100  
   101  // ParseBigBytes parses a string representation of bytes into the number
   102  // of bytes it represents.
   103  //
   104  // See also: BigBytes, BigIBytes.
   105  //
   106  // ParseBigBytes("42 MB") -> 42000000, nil
   107  // ParseBigBytes("42 mib") -> 44040192, nil
   108  func ParseBigBytes(s string) (*big.Int, error) {
   109  	lastDigit := 0
   110  	hasComma := false
   111  	for _, r := range s {
   112  		if !(unicode.IsDigit(r) || r == '.' || r == ',') {
   113  			break
   114  		}
   115  		if r == ',' {
   116  			hasComma = true
   117  		}
   118  		lastDigit++
   119  	}
   120  
   121  	num := s[:lastDigit]
   122  	if hasComma {
   123  		num = strings.Replace(num, ",", "", -1)
   124  	}
   125  
   126  	val := &big.Rat{}
   127  	_, err := fmt.Sscanf(num, "%f", val)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
   133  	if m, ok := bigBytesSizeTable[extra]; ok {
   134  		mv := (&big.Rat{}).SetInt(m)
   135  		val.Mul(val, mv)
   136  		rv := &big.Int{}
   137  		rv.Div(val.Num(), val.Denom())
   138  		return rv, nil
   139  	}
   140  
   141  	return nil, fmt.Errorf("unhandled size name: %v", extra)
   142  }