Skip to content

Instantly share code, notes, and snippets.

@choonkeat
Forked from regeda/underscore.go
Created February 7, 2018 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save choonkeat/238220a67d67a416e249e69f4d70090f to your computer and use it in GitHub Desktop.
Save choonkeat/238220a67d67a416e249e69f4d70090f to your computer and use it in GitHub Desktop.
Convert CamelCase to underscore in golang with UTF-8 support.
package main
import (
"testing"
"unicode"
"unicode/utf8"
"github.com/stretchr/testify/assert"
)
type buffer struct {
r []byte
runeBytes [utf8.UTFMax]byte
}
func (b *buffer) write(r rune) {
if r < utf8.RuneSelf {
b.r = append(b.r, byte(r))
return
}
n := utf8.EncodeRune(b.runeBytes[0:], r)
b.r = append(b.r, b.runeBytes[0:n]...)
}
func (b *buffer) indent() {
if len(b.r) > 0 {
b.r = append(b.r, '_')
}
}
func underscore(s string) string {
b := buffer{
r: make([]byte, 0, len(s)),
}
var m rune
var w bool
for _, ch := range s {
if unicode.IsUpper(ch) {
if m != 0 {
if !w {
b.indent()
w = true
}
b.write(m)
}
m = unicode.ToLower(ch)
} else {
if m != 0 {
b.indent()
b.write(m)
m = 0
w = false
}
b.write(ch)
}
}
if m != 0 {
if !w {
b.indent()
}
b.write(m)
}
return string(b.r)
}
func TestUnderscore(t *testing.T) {
assert.Equal(t, "i_love_golang_and_json_so_much", underscore("ILoveGolangAndJSONSoMuch"))
assert.Equal(t, "i_love_json", underscore("ILoveJSON"))
assert.Equal(t, "json", underscore("json"))
assert.Equal(t, "json", underscore("JSON"))
assert.Equal(t, "привет_мир", underscore("ПриветМир"))
}
// BenchmarkUnderscore-4 10000000 209 ns/op
func BenchmarkUnderscore(b *testing.B) {
for n := 0; n < b.N; n++ {
underscore("TestTable")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment