@@ -6,49 +6,43 @@ import (
6
6
"unicode"
7
7
)
8
8
9
+ type CaseStrategy int
10
+
11
+ const (
12
+ CaseStrategyAlways CaseStrategy = 0
13
+ CaseStrategySkipFirstPart CaseStrategy = 1
14
+ CaseStrategyNever CaseStrategy = math .MaxInt64
15
+
16
+ NoSeparator rune = 0
17
+ )
18
+
9
19
// ToPascalCase transforms a string in any form to PascalCase.
10
20
func ToPascalCase (input string ) string {
11
- return splitJoin (input , 0 , 0 , false )
21
+ return SplitJoin (input , CaseStrategyAlways , NoSeparator , false )
12
22
}
13
23
14
24
// ToPascalGoCase transforms a string in any form to PascalCase, but with recognized initialisms in uppercase, matching the Go style.
15
25
func ToPascalGoCase (input string ) string {
16
- return splitJoin (input , 0 , 0 , true )
26
+ return SplitJoin (input , CaseStrategyAlways , NoSeparator , true )
17
27
}
18
28
19
29
// ToCamelCase transforms a string in any form to camelCase.
20
30
func ToCamelCase (input string ) string {
21
- return splitJoin (input , 1 , 0 , false )
31
+ return SplitJoin (input , CaseStrategySkipFirstPart , NoSeparator , false )
22
32
}
23
33
24
34
// ToCamelGoCase transforms a string in any form to camelCase, but with recognized initialisms in uppercase, matching the Go style.
25
35
func ToCamelGoCase (input string ) string {
26
- return splitJoin (input , 1 , 0 , true )
36
+ return SplitJoin (input , CaseStrategySkipFirstPart , NoSeparator , true )
27
37
}
28
38
29
39
// ToSnakeCase transforms a string in any form to snake_case.
30
40
func ToSnakeCase (input string ) string {
31
- return splitJoin (input , math . MaxInt64 , '_' , false )
41
+ return SplitJoin (input , CaseStrategyNever , '_' , false )
32
42
}
33
43
34
- func allocateBuilder (input string , separator rune ) * strings.Builder {
35
- var b strings.Builder
36
- length := len (input )
37
- if separator != 0 {
38
- // Heuristic to add about 25% buffer for separators
39
- // Not having perfect match isn't terrible, it will only result in a few more memory allocations.
40
- // Ex:
41
- // foo_bar_baz: 9 original chars, 11 final. 9 * 5 / 4 = 11
42
- // foo_id: 5 original chars, 6 final. 5 * 5 / 4 = 6
43
- // a_b_c_d: 4 original chars, 7 final. 4 * 5 / 4 = 5, which will result in an extra allocation.
44
- length = length * 5 / 4
45
- }
46
-
47
- b .Grow (length )
48
- return & b
49
- }
50
-
51
- func splitJoin (input string , firstUpper int , separator rune , initialism bool ) string {
44
+ func SplitJoin (input string , caseStrategy CaseStrategy , separator rune , initialism bool ) string {
45
+ firstUpper := int (caseStrategy )
52
46
b := allocateBuilder (input , separator )
53
47
var buf []rune
54
48
var currentPartIndex int
@@ -60,7 +54,7 @@ func splitJoin(input string, firstUpper int, separator rune, initialism bool) st
60
54
// Nothing was added since last flush
61
55
return
62
56
}
63
- if separator != 0 && currentPartIndex > 0 {
57
+ if separator != NoSeparator && currentPartIndex > 0 {
64
58
b .WriteRune (separator )
65
59
}
66
60
if currentPartIndex >= firstUpper {
@@ -98,6 +92,23 @@ func splitJoin(input string, firstUpper int, separator rune, initialism bool) st
98
92
return b .String ()
99
93
}
100
94
95
+ func allocateBuilder (input string , separator rune ) * strings.Builder {
96
+ var b strings.Builder
97
+ length := len (input )
98
+ if separator != NoSeparator {
99
+ // Heuristic to add about 25% buffer for separators
100
+ // Not having perfect match isn't terrible, it will only result in a few more memory allocations.
101
+ // Ex:
102
+ // foo_bar_baz: 9 original chars, 11 final. 9 * 5 / 4 = 11
103
+ // foo_id: 5 original chars, 6 final. 5 * 5 / 4 = 6
104
+ // a_b_c_d: 4 original chars, 7 final. 4 * 5 / 4 = 5, which will result in an extra allocation.
105
+ length = length * 5 / 4
106
+ }
107
+
108
+ b .Grow (length )
109
+ return & b
110
+ }
111
+
101
112
// Convert to uppercase if initialism and `initialism` is true.
102
113
// Convert first rune to uppercase otherwise.
103
114
func pascalPart (part []rune , initialism bool ) {
0 commit comments