-
Notifications
You must be signed in to change notification settings - Fork 54
/
parse.go
96 lines (85 loc) · 2.1 KB
/
parse.go
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
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package benchunit manipulates benchmark units and formats numbers
// in those units.
package benchunit
import (
"fmt"
"unicode"
)
// A Class specifies what class of unit prefixes are in use.
type Class int
const (
// Decimal indicates values of a given unit should be scaled
// by powers of 1000. Decimal units use the International
// System of Units SI prefixes, such as "k", and "M".
Decimal Class = iota
// Binary indicates values of a given unit should be scaled by
// powers of 1024. Binary units use the International
// Electrotechnical Commission (IEC) binary prefixes, such as
// "Ki" and "Mi".
Binary
)
func (c Class) String() string {
switch c {
case Decimal:
return "Decimal"
case Binary:
return "Binary"
}
return fmt.Sprintf("Class(%d)", int(c))
}
// ClassOf returns the Class of unit. If unit contains some measure of
// bytes in the numerator, this is Binary. Otherwise, it is Decimal.
func ClassOf(unit string) Class {
p := newParser(unit)
for p.next() {
if (p.tok == "B" || p.tok == "MB" || p.tok == "bytes") && !p.denom {
return Binary
}
}
return Decimal
}
type parser struct {
rest string // unparsed unit
rpos int // byte consumed from original unit
// Current token
tok string
pos int // byte offset of tok in original unit
denom bool // current token is in denominator
}
func newParser(unit string) *parser {
return &parser{rest: unit}
}
func (p *parser) next() bool {
// Consume separators.
for i, r := range p.rest {
if r == '*' {
p.denom = false
} else if r == '/' {
p.denom = true
} else if !(r == '-' || unicode.IsSpace(r)) {
p.rpos += i
p.rest = p.rest[i:]
goto tok
}
}
// End of string.
p.rest = ""
return false
tok:
// Consume until separator.
end := len(p.rest)
for i, r := range p.rest {
if r == '*' || r == '/' || r == '-' || unicode.IsSpace(r) {
end = i
break
}
}
p.tok = p.rest[:end]
p.pos = p.rpos
p.rpos += end
p.rest = p.rest[end:]
return true
}