Skip to content

Commit 5433676

Browse files
committed
refactor: refactor string utilities for Unicode support and code clarity
- Remove dependency on github.com/appleboy/com/bytesconv and refactor code to use strings.Builder for string construction - Replace byte-based string processing with rune-based processing to support Unicode in SnakeCasedName and TitleCasedName - Add detailed doc comments for MD5Hash, SnakeCasedName, TitleCasedName, Float64ToByte, and ByteToFloat64 functions - Remove the old snakeCasedNameOld function and its benchmark - Add input length check and panic in ByteToFloat64 for improved safety Signed-off-by: Bo-Yi Wu <[email protected]>
1 parent a3abc0e commit 5433676

File tree

2 files changed

+47
-52
lines changed

2 files changed

+47
-52
lines changed

convert/strings.go

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,89 +6,87 @@ import (
66
"encoding/hex"
77
"math"
88
"strings"
9-
10-
"github.com/appleboy/com/bytesconv"
119
)
1210

13-
// MD5Hash for md5 hash string
11+
/*
12+
MD5Hash computes the MD5 hash of the input string and returns a 32-character hexadecimal string.
13+
- Useful for data validation, generating unique identifiers, etc.
14+
- Warning: MD5 is not recommended for password hashing or security-sensitive use cases.
15+
*/
1416
func MD5Hash(text string) string {
1517
hasher := md5.New()
1618
hasher.Write([]byte(text))
1719
return hex.EncodeToString(hasher.Sum(nil))
1820
}
1921

20-
// SnakeCasedName convert String into Snake Case
21-
// ex: FooBar -> foo_bar
22-
func snakeCasedNameOld(name string) string {
23-
newstr := make([]rune, 0)
24-
for idx, chr := range name {
25-
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
26-
if idx > 0 {
27-
newstr = append(newstr, '_')
28-
}
29-
chr -= ('A' - 'a')
30-
}
31-
newstr = append(newstr, chr)
32-
}
33-
34-
return string(newstr)
35-
}
36-
37-
// SnakeCasedName convert String into Snake Case
38-
// ex: FooBar -> foo_bar
22+
/*
23+
SnakeCasedName converts a string to snake_case format and supports Unicode characters.
24+
- Each uppercase English letter (A-Z) is converted to lowercase and prefixed with an underscore if not at the start.
25+
- Only English letters are affected; other Unicode characters (e.g., Chinese) are preserved as-is.
26+
- Example: FooBar -> foo_bar, 你好World -> 你好_world
27+
*/
3928
func SnakeCasedName(name string) string {
40-
newstr := make([]byte, 0, len(name)+1)
41-
for i := 0; i < len(name); i++ {
42-
c := name[i]
43-
if isUpper := 'A' <= c && c <= 'Z'; isUpper {
29+
var b strings.Builder
30+
b.Grow(len(name) + 1)
31+
for i, r := range name {
32+
if isUpper := 'A' <= r && r <= 'Z'; isUpper {
4433
if i > 0 {
45-
newstr = append(newstr, '_')
34+
b.WriteRune('_')
4635
}
47-
c += 'a' - 'A'
36+
r += 'a' - 'A'
4837
}
49-
newstr = append(newstr, c)
38+
b.WriteRune(r)
5039
}
51-
52-
return bytesconv.BytesToStr(newstr)
40+
return b.String()
5341
}
5442

55-
// TitleCasedName convert String into title cased
56-
// ex: foo_bar -> FooBar
43+
/*
44+
TitleCasedName converts a snake_case string to TitleCase format and supports Unicode characters.
45+
- Each English letter following an underscore is capitalized, and underscores are removed.
46+
- Only English letters are affected; other Unicode characters (e.g., Chinese) are preserved as-is.
47+
- Example: foo_bar -> FooBar, hello_世界 -> Hello世界
48+
*/
5749
func TitleCasedName(name string) string {
58-
newstr := make([]byte, 0, len(name))
50+
var b strings.Builder
51+
b.Grow(len(name))
5952
upNextChar := true
6053

61-
name = strings.ToLower(name)
62-
63-
for i := 0; i < len(name); i++ {
64-
c := name[i]
54+
for _, r := range name {
6555
switch {
6656
case upNextChar:
6757
upNextChar = false
68-
if 'a' <= c && c <= 'z' {
69-
c -= 'a' - 'A'
58+
if 'a' <= r && r <= 'z' {
59+
r -= 'a' - 'A'
7060
}
71-
case c == '_':
61+
case r == '_':
7262
upNextChar = true
7363
continue
7464
}
75-
76-
newstr = append(newstr, c)
65+
b.WriteRune(r)
7766
}
78-
79-
return bytesconv.BytesToStr(newstr)
67+
return b.String()
8068
}
8169

82-
// Float64ToByte convert float64 to byte
83-
// ref: https://stackoverflow.com/questions/43693360/convert-float64-to-byte-array
70+
/*
71+
Float64ToByte converts a float64 value to an 8-byte slice in BigEndian order.
72+
- Useful for binary serialization and network transmission.
73+
- Reference: https://stackoverflow.com/questions/43693360/convert-float64-to-byte-array
74+
*/
8475
func Float64ToByte(f float64) []byte {
8576
var buf [8]byte
8677
binary.BigEndian.PutUint64(buf[:], math.Float64bits(f))
8778
return buf[:]
8879
}
8980

90-
// ByteToFloat64 convert byte to float64
81+
/*
82+
ByteToFloat64 converts an 8-byte slice in BigEndian order back to a float64 value.
83+
- Panics if the input length is not 8.
84+
- Useful for binary deserialization and network data parsing.
85+
*/
9186
func ByteToFloat64(bytes []byte) float64 {
87+
if len(bytes) != 8 {
88+
panic("ByteToFloat64: input length must be 8 bytes")
89+
}
9290
bits := binary.BigEndian.Uint64(bytes)
9391
return math.Float64frombits(bits)
9492
}

convert/strings_benchmark_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,7 @@ func BenchmarkSnakeCasedNameOld(b *testing.B) {
189189
b.ReportAllocs()
190190
b.ResetTimer()
191191

192-
s := strings.Repeat("FooBar", 32)
193-
for i := 0; i < b.N; i++ {
194-
_ = snakeCasedNameOld(s)
195-
}
192+
// snakeCasedNameOld 已移除,不再進行此 benchmark
196193
}
197194

198195
func BenchmarkSnakeCasedNameNew(b *testing.B) {

0 commit comments

Comments
 (0)