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
|
// SPDX-License-Identifier: GPL-3.0-or-later
package config
import (
"errors"
"fmt"
"math"
"strconv"
"time"
)
// ParseSize reads a size: a whole number with an optional K, M, G or T
// suffix, in powers of 1024.
func ParseSize(s string) (int64, error) {
num, mult := s, int64(1)
if n := len(s); n > 0 {
switch s[n-1] {
case 'K':
mult = 1 << 10
case 'M':
mult = 1 << 20
case 'G':
mult = 1 << 30
case 'T':
mult = 1 << 40
}
if mult > 1 {
num = s[:n-1]
}
}
v, err := parseCount(num)
if err != nil || v > math.MaxInt64/mult {
return 0, fmt.Errorf("bad size %q: want a whole number with an optional K, M, G or T, like 50M", s)
}
return v * mult, nil
}
var durationUnits = map[byte]time.Duration{
's': time.Second, 'm': time.Minute, 'h': time.Hour, 'd': 24 * time.Hour, 'w': 7 * 24 * time.Hour,
}
// ParseDuration reads a duration: a whole number followed by s, m, h, d or w.
func ParseDuration(s string) (time.Duration, error) {
bad := fmt.Errorf("bad duration %q: want a whole number followed by s, m, h, d or w, like 30d", s)
if len(s) < 2 {
return 0, bad
}
unit, ok := durationUnits[s[len(s)-1]]
if !ok {
return 0, bad
}
v, err := parseCount(s[:len(s)-1])
if err != nil || v > int64(math.MaxInt64/unit) {
return 0, bad
}
return time.Duration(v) * unit, nil
}
// parseCount reads a non-empty run of ASCII digits.
func parseCount(s string) (int64, error) {
if s == "" {
return 0, errors.New("empty number")
}
for _, c := range s {
if c < '0' || c > '9' {
return 0, errors.New("not a whole number")
}
}
return strconv.ParseInt(s, 10, 64)
}
|