Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit 817870e

Browse files
committed
Adding number helper
1 parent 69ec501 commit 817870e

File tree

9 files changed

+200
-133
lines changed

9 files changed

+200
-133
lines changed

aws/session/internal/ini/literal_tokens.go

Lines changed: 18 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -26,62 +26,45 @@ func isBoolValue(b []byte) bool {
2626
return false
2727
}
2828

29+
// isNumberValue will return whether not the leading characters in
30+
// a byte slice is a number. A number is delimited by whitespace or
31+
// the newline token.
32+
//
33+
// A number is defined to be in a binary, octal, decimal (int | float), hex format,
34+
// or in scientific notation.
2935
func isNumberValue(b []byte) bool {
30-
foundDecimal := false
31-
foundBinary := false
32-
foundOctal := false
33-
foundHex := false
34-
foundExponent := false
35-
foundNegative := false
3636
negativeIndex := 0
37+
helper := numberHelper{}
3738

3839
for i := 0; i < len(b); i++ {
3940
negativeIndex++
4041

4142
switch b[i] {
4243
case '-':
43-
if foundNegative || negativeIndex != 1 {
44+
if helper.IsNegative() || negativeIndex != 1 {
4445
return false
4546
}
46-
foundNegative = true
47-
continue
48-
case '.':
49-
if foundDecimal ||
50-
foundBinary ||
51-
foundOctal ||
52-
foundHex ||
53-
foundExponent {
54-
return false
55-
}
56-
foundDecimal = true
47+
helper.Determine(b[i])
5748
continue
5849
case 'e', 'E':
59-
if foundDecimal ||
60-
foundBinary ||
61-
foundOctal ||
62-
foundHex ||
63-
foundExponent {
50+
if helper.Exists() {
6451
return false
6552
}
6653

67-
foundExponent = true
68-
foundNegative = false
6954
negativeIndex = 0
55+
helper.Determine(b[i])
7056
continue
7157
case 'b', 'o', 'x':
7258
if i == 0 {
7359
return false
7460
}
75-
if foundDecimal ||
76-
foundBinary ||
77-
foundOctal ||
78-
foundHex ||
79-
foundExponent {
61+
62+
fallthrough
63+
case '.':
64+
if helper.Exists() {
8065
return false
8166
}
82-
foundBinary = foundBinary || b[i] == 'b'
83-
foundOctal = foundOctal || b[i] == 'o'
84-
foundHex = foundHex || b[i] == 'x'
67+
helper.Determine(b[i])
8568
continue
8669
}
8770

@@ -90,49 +73,14 @@ func isNumberValue(b []byte) bool {
9073
return true
9174
}
9275

93-
switch {
94-
case foundBinary:
95-
if b[i] != '0' && b[i] != '1' {
96-
return false
97-
}
98-
case foundOctal:
99-
switch b[i] {
100-
case '0', '1', '2', '3', '4', '5', '6', '7':
101-
default:
102-
return false
103-
}
104-
case foundHex:
105-
if !isHexByte(b[i]) {
106-
return false
107-
}
108-
case foundDecimal:
109-
if !isDigit(b[i]) {
110-
return false
111-
}
112-
case foundExponent:
113-
if !isDigit(b[i]) {
114-
return false
115-
}
116-
case foundNegative:
117-
if !isDigit(b[i]) {
118-
return false
119-
}
120-
default:
121-
if !isDigit(b[i]) {
122-
return false
123-
}
76+
if !helper.CorrectByte(b[i]) {
77+
return false
12478
}
125-
12679
}
12780

12881
return true
12982
}
13083

131-
// isDigit will return whether or not something is an integer
132-
func isDigit(b byte) bool {
133-
return b >= '0' && b <= '9'
134-
}
135-
13684
func isValid(b byte) bool {
13785
return utf8.ValidRune(rune(b)) && b != '=' && b != '[' && b != ']' && b != ' ' && b != '\n'
13886
}
@@ -286,7 +234,3 @@ func (token literalToken) String() string {
286234

287235
return "invalid token"
288236
}
289-
290-
func hasExponent(v string) bool {
291-
return strings.Contains(v, "e") || strings.Contains(v, "E")
292-
}

aws/session/internal/ini/newline_token.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package ini
22

3+
// newlineToken acts as a delimeter in ini is will be used
4+
// primarily to handle nesting expressions.
35
type newlineToken struct {
46
emptyToken
57
raw string
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package ini
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/aws/aws-sdk-go/aws/awserr"
7+
)
8+
9+
// numberHelper is used to dictate what format a number is in
10+
// and what to do for negative values. Since -1e-4 is a valid
11+
// number, we cannot just simply check for duplicate negatives.
12+
type numberHelper struct {
13+
binary bool
14+
octal bool
15+
decimal bool
16+
hex bool
17+
18+
exponent bool
19+
negative bool
20+
}
21+
22+
func (b numberHelper) Exists() bool {
23+
return b.decimal || b.binary || b.octal || b.hex || b.exponent
24+
}
25+
26+
func (b numberHelper) IsNegative() bool {
27+
return b.negative
28+
}
29+
30+
func (b *numberHelper) Determine(c byte) error {
31+
switch c {
32+
case 'b':
33+
b.binary = true
34+
case 'o':
35+
b.octal = true
36+
case 'x':
37+
b.hex = true
38+
case 'e', 'E':
39+
b.exponent = true
40+
b.negative = false
41+
case '-':
42+
b.negative = true
43+
case '.':
44+
b.decimal = true
45+
default:
46+
return awserr.New(ErrCodeParseError, fmt.Sprintf("invalid number character: %v", string(c)), nil)
47+
}
48+
49+
return nil
50+
}
51+
52+
func (b numberHelper) CorrectByte(c byte) bool {
53+
switch {
54+
case b.binary:
55+
if !isBinaryByte(c) {
56+
return false
57+
}
58+
case b.octal:
59+
if !isOctalByte(c) {
60+
return false
61+
}
62+
case b.hex:
63+
if !isHexByte(c) {
64+
return false
65+
}
66+
case b.decimal:
67+
if !isDigit(c) {
68+
return false
69+
}
70+
case b.exponent:
71+
if !isDigit(c) {
72+
return false
73+
}
74+
case b.negative:
75+
if !isDigit(c) {
76+
return false
77+
}
78+
default:
79+
if !isDigit(c) {
80+
return false
81+
}
82+
}
83+
84+
return true
85+
}
86+
87+
func (b numberHelper) Base() int {
88+
switch {
89+
case b.binary:
90+
return 2
91+
case b.octal:
92+
return 8
93+
case b.hex:
94+
return 16
95+
default:
96+
return 10
97+
}
98+
}

aws/session/internal/ini/op_tokens.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
opTypeEqual
2525
)
2626

27+
// opToken is an operation token that signifies an expression.
2728
type opToken struct {
2829
emptyToken
2930

aws/session/internal/ini/parse_stack.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,34 @@ import (
55
"fmt"
66
)
77

8+
// ParseStack is a stack that contains a container, the stack portion,
9+
// and the list which is the list of ASTs that have been successfully
10+
// parsed.
811
type ParseStack struct {
912
container []AST
1013
list []AST
1114
}
1215

16+
// Pop will return and truncate the last container element.
1317
func (s *ParseStack) Pop() AST {
1418
temp := s.container[0]
1519
s.container = s.container[1:]
1620
return temp
1721
}
1822

23+
// Push will add the new AST to the container
1924
func (s *ParseStack) Push(ast AST) {
2025
s.container = append(s.container, ast)
2126
}
2227

28+
// Epsilon will push Start{} back to the stack and append the
29+
// AST to the list of completed statements
2330
func (s *ParseStack) Epsilon(ast AST) {
2431
s.Push(Start{})
2532
s.list = append(s.list, ast)
2633
}
2734

35+
// Len will return the length of the container
2836
func (s *ParseStack) Len() int {
2937
return len(s.container)
3038
}

aws/session/internal/ini/sep_tokens.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const (
2525
sepTypeCloseBrace
2626
)
2727

28+
// sepToken is a separator token which represents the concept of
29+
// scoping in ini files.
2830
type sepToken struct {
2931
emptyToken
3032

0 commit comments

Comments
 (0)