File: fmtx.go

package info (click to toggle)
golang-github-icza-gox 0.0~git20210726.cd40a3f-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 332 kB
  • sloc: makefile: 2
file content (131 lines) | stat: -rw-r--r-- 3,518 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// This file contains general formatting utilities.

package fmtx

import (
	"fmt"
	"strconv"
)

// FormatInt formats an integer with grouping decimals, in decimal radix.
// Grouping signs are inserted after every groupSize digits, starting from the right.
// A groupingSize less than 1 will default to 3.
// Only ASCII grouping decimal signs are supported which may be provided with
// grouping.
//
// For details, see https://stackoverflow.com/a/31046325/1705598
func FormatInt(n int64, groupSize int, grouping byte) string {
	if groupSize < 1 {
		groupSize = 3
	}

	in := strconv.FormatInt(n, 10)
	numOfDigits := len(in)
	if n < 0 {
		numOfDigits-- // First character is the - sign (not a digit)
	}
	numOfCommas := (numOfDigits - 1) / groupSize

	out := make([]byte, len(in)+numOfCommas)
	if n < 0 {
		in, out[0] = in[1:], '-'
	}

	for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
		out[j] = in[i]
		if i == 0 {
			return string(out)
		}
		if k++; k == groupSize {
			j, k = j-1, 0
			out[j] = grouping
		}
	}
}

// SizeUnit is the type of the unit sizes
type SizeUnit string

const (
	// SizeUnitAuto indicates that another unit is to be chosen automatically
	// based on the size value
	SizeUnitAuto SizeUnit = "(auto)"
	// SizeUnitByte is the byte unit size
	SizeUnitByte SizeUnit = "bytes"
	// SizeUnitKB is the kilobyte (2^10 bytes) unit size
	SizeUnitKB SizeUnit = "KB"
	// SizeUnitMB is the megabyte (2^20 bytes) unit size
	SizeUnitMB SizeUnit = "MB"
	// SizeUnitGB is the gigabyte (2^30 bytes) unit size
	SizeUnitGB SizeUnit = "GB"
	// SizeUnitTB is the terabyte (2^40 bytes) unit size
	SizeUnitTB SizeUnit = "TB"
	// SizeUnitPB is the petabyte (2^50 bytes) unit size
	SizeUnitPB SizeUnit = "PB"
	// SizeUnitEB is the exabyte (2^60 bytes) unit size
	SizeUnitEB SizeUnit = "EB"
)

// FormatSize formats the given size value using the given size unit, rounding to
// the given number of fraction digits. Fraction digits are omitted when the
// (resulting) unit is SizeUnitByte.
//
// If SizeUnitAuto is specified, the unit will be automatically selected based
// on the size value.
//
// Behavior for negative size values is undefined.
func FormatSize(size int64, unit SizeUnit, fractionDigits int) string {
	if unit == SizeUnitAuto {
		switch {
		case size < 1000:
			unit = SizeUnitByte
		case size < 1000<<10:
			unit = SizeUnitKB
		case size < 1024<<20:
			unit = SizeUnitMB
		case size < 1024<<30:
			unit = SizeUnitGB
		case size < 1024<<40:
			unit = SizeUnitTB
		case size < 1024<<50:
			unit = SizeUnitPB
		default:
			unit = SizeUnitEB
		}
	}

	if unit == SizeUnitByte {
		return fmt.Sprint(size, " "+SizeUnitByte)
	}

	var divisor float64
	switch unit {
	case SizeUnitKB:
		divisor = 1 << 10
	case SizeUnitMB:
		divisor = 1 << 20
	case SizeUnitGB:
		divisor = 1 << 30
	case SizeUnitTB:
		divisor = 1 << 40
	case SizeUnitPB:
		divisor = 1 << 50
	default:
		divisor = 1 << 60
	}

	return fmt.Sprintf("%.[1]*f %s", fractionDigits, float64(size)/divisor, unit)
}

// CondSprintf is like fmt.Sprintf(), but extra arguments (that have no verb
// in the format string) are ignored (not treated as an error).
//
// Usually mismatching format string and arguments is an indication of a bug
// in your code (in how you call fmt.Sprintf()), so you should not overuse this.
//
// For details, see https://stackoverflow.com/a/59696492/1705598
func CondSprintf(format string, v ...interface{}) string {
	v = append(v, "")
	format += fmt.Sprint("%[", len(v), "]s")
	return fmt.Sprintf(format, v...)
}