diff --git a/ident.go b/ident.go index 78b51d4..da3560b 100644 --- a/ident.go +++ b/ident.go @@ -38,9 +38,9 @@ func toParts(s string) []string { return []string{strings.ToUpper(s)} } var prev rune - var x string + var x strings.Builder + x.Grow(len(s)) for _, c := range s { - cs := string(c) // fmt.Println("### cs ->", cs) // fmt.Println("### unicode.IsControl(c) ->", unicode.IsControl(c)) // fmt.Println("### unicode.IsDigit(c) ->", unicode.IsDigit(c)) @@ -58,35 +58,38 @@ func toParts(s string) []string { } if isSpace(c) { - parts = xappend(parts, x) - x = cs + parts = xappend(parts, x.String()) + x.Reset() + x.WriteRune(c) prev = c continue } if unicode.IsUpper(c) && !unicode.IsUpper(prev) { - parts = xappend(parts, x) - x = cs + parts = xappend(parts, x.String()) + x.Reset() + x.WriteRune(c) prev = c continue } - if unicode.IsUpper(c) && baseAcronyms[strings.ToUpper(x)] { - parts = xappend(parts, x) - x = cs + if unicode.IsUpper(c) && baseAcronyms[strings.ToUpper(x.String())] { + parts = xappend(parts, x.String()) + x.Reset() + x.WriteRune(c) prev = c continue } if unicode.IsLetter(c) || unicode.IsDigit(c) || unicode.IsPunct(c) || c == '`' { prev = c - x += cs + x.WriteRune(c) continue } - parts = xappend(parts, x) - x = "" + parts = xappend(parts, x.String()) + x.Reset() prev = c } - parts = xappend(parts, x) + parts = xappend(parts, x.String()) return parts } diff --git a/ident_test.go b/ident_test.go index 034acb0..3994d29 100644 --- a/ident_test.go +++ b/ident_test.go @@ -64,3 +64,49 @@ func Test_MarshalText(t *testing.T) { r.NoError((&n).UnmarshalText([]byte("bates"))) r.Equal("bates", n.String()) } + +func Benchmark_New(b *testing.B) { + + table := []string{ + "", + "widget", + "widget_id", + "WidgetID", + "Widget_ID", + "widget_ID", + "widget/ID", + "widgetID", + "widgetName", + "JWTName", + "JWTname", + "jwtname", + "sql", + "sQl", + "id", + "Id", + "iD", + "html", + "Html", + "HTML", + "with `code` inside", + "Donald E. Knuth", + "Random text with *(bad)* characters", + "Allow_Under_Scores", + "Trailing bad characters!@#", + "!@#Leading bad characters", + "Squeeze separators", + "Test with + sign", + "Malmö", + "Garçons", + "Opsů", + "Ærøskøbing", + "Aßlar", + "Japanese: 日本語", + } + + for n := 0; n < b.N; n++ { + for i := range table { + New(table[i]) + } + } +} diff --git a/underscore.go b/underscore.go index b92488a..e1466d9 100644 --- a/underscore.go +++ b/underscore.go @@ -18,16 +18,17 @@ func Underscore(s string) string { // Nice to see you! = nice_to_see_you // widgetID = widget_id func (i Ident) Underscore() Ident { - var out []string + out := make([]string, 0, len(i.Parts)) for _, part := range i.Parts { - var x string + var x strings.Builder + x.Grow(len(part)) for _, c := range part { if unicode.IsLetter(c) || unicode.IsDigit(c) { - x += string(c) + x.WriteRune(c) } } - if x != "" { - out = append(out, x) + if x.Len() > 0 { + out = append(out, x.String()) } } return New(strings.ToLower(strings.Join(out, "_"))) diff --git a/underscore_test.go b/underscore_test.go index 2425738..7122e9d 100644 --- a/underscore_test.go +++ b/underscore_test.go @@ -27,3 +27,22 @@ func Test_Underscore(t *testing.T) { }) } } + +func Benchmark_Underscore(b *testing.B) { + + table := []string{ + "", + "bob dylan", + "Nice to see you!", + "*hello*", + "i've read a book! have you?", + "This is `code` ok", + "TLCForm", + } + + for n := 0; n < b.N; n++ { + for i := range table { + Underscore(table[i]) + } + } +}