bytes.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package humanize
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. "strings"
  7. "golang.org/x/exp/constraints"
  8. )
  9. // IEC Sizes.
  10. // kibis of bits
  11. const (
  12. Byte = 1 << (iota * 10)
  13. KiByte
  14. MiByte
  15. GiByte
  16. TiByte
  17. PiByte
  18. EiByte
  19. )
  20. // SI Sizes.
  21. const (
  22. IByte = 1
  23. KByte = IByte * 1000
  24. MByte = KByte * 1000
  25. GByte = MByte * 1000
  26. TByte = GByte * 1000
  27. PByte = TByte * 1000
  28. EByte = PByte * 1000
  29. )
  30. func logn(n, b float64) float64 {
  31. return math.Log(n) / math.Log(b)
  32. }
  33. func humanize_bytes(s uint64, base float64, sizes []string, sep string) string {
  34. if s < 10 {
  35. return fmt.Sprintf("%d%sB", s, sep)
  36. }
  37. e := math.Floor(logn(float64(s), base))
  38. suffix := sizes[int(e)]
  39. val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10
  40. f := "%.0f%s%s"
  41. if val < 10 {
  42. f = "%.1f%s%s"
  43. }
  44. return fmt.Sprintf(f, val, sep, suffix)
  45. }
  46. // Bytes produces a human readable representation of an SI size.
  47. // Bytes(82854982) -> 83 MB
  48. func Bytes(s uint64) string {
  49. return Size(s, SizeOptions{})
  50. }
  51. // IBytes produces a human readable representation of an IEC size.
  52. // IBytes(82854982) -> 79 MiB
  53. func IBytes(s uint64) string {
  54. return Size(s, SizeOptions{Base: 1024})
  55. }
  56. type SizeOptions struct {
  57. Separator string
  58. Base int
  59. }
  60. func Size[T constraints.Integer | constraints.Float](s T, opts ...SizeOptions) string {
  61. var o SizeOptions
  62. prefix := ""
  63. if len(opts) == 0 {
  64. o = SizeOptions{}
  65. } else {
  66. o = opts[0]
  67. }
  68. if s < 0 {
  69. prefix = "-"
  70. }
  71. if o.Separator == "" {
  72. o.Separator = " "
  73. }
  74. if o.Base == 0 {
  75. o.Base = 1000
  76. }
  77. var sizes []string
  78. switch o.Base {
  79. default:
  80. sizes = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"}
  81. case 1024:
  82. sizes = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
  83. }
  84. return prefix + humanize_bytes(uint64(s), float64(o.Base), sizes, o.Separator)
  85. }
  86. func FormatNumber[T constraints.Float](n T, max_num_of_decimals ...int) string {
  87. prec := 2
  88. if len(max_num_of_decimals) > 0 {
  89. prec = max_num_of_decimals[0]
  90. }
  91. ans := strconv.FormatFloat(float64(n), 'f', prec, 64)
  92. return strings.TrimRight(strings.TrimRight(ans, "0"), ".")
  93. }