Skip to content

Commit

Permalink
refs #24. camelCaseToUnderScore can handle more special cases.
Browse files Browse the repository at this point in the history
Includes:

* A_B => a_b
* _A  => _a
  • Loading branch information
huandu committed Jan 23, 2015
1 parent c390f96 commit a34d607
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 20 deletions.
5 changes: 3 additions & 2 deletions facebook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1286,8 +1286,9 @@ func TestCamelCaseToUnderScore(t *testing.T) {
"HTTPServer": "http_server",
"NoHTTPS": "no_https",
"Wi_thF": "wi_th_f",
"_AnotherTES_TCaseP": "__another_te_s__t_case_p",
"ALL": "all",
"_AnotherTES_TCaseP": "_another_tes_t_case_p",
"ALL": "all",
"UserID": "user_id",
}

for k, v := range cases {
Expand Down
55 changes: 37 additions & 18 deletions misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,39 @@ import (
"unicode/utf8"
)

func camelCaseToUnderScore(name string) string {
func camelCaseToUnderScore(str string) string {
if len(str) == 0 {
return ""
}

buf := &bytes.Buffer{}
var r0, r1 rune
var prev, r0, r1 rune
var size int

for len(name) > 0 {
r0, size = utf8.DecodeRuneInString(name)
name = name[size:]
r0 = '_'

for len(str) > 0 {
prev = r0
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]

switch {
case r0 == utf8.RuneError:
buf.WriteByte(byte(name[0]))
buf.WriteByte(byte(str[0]))

case unicode.IsUpper(r0):
if buf.Len() > 0 {
if prev != '_' {
buf.WriteRune('_')
}

buf.WriteRune(unicode.ToLower(r0))

if len(name) == 0 {
if len(str) == 0 {
break
}

r0, size = utf8.DecodeRuneInString(name)
name = name[size:]
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]

if !unicode.IsUpper(r0) {
buf.WriteRune(r0)
Expand All @@ -50,32 +57,44 @@ func camelCaseToUnderScore(name string) string {
// it's designed to convert `HTTPServer` to `http_server`.
// if there are more than 2 adjacent upper case characters in a word,
// treat them as an abbreviation plus a normal word.
for len(name) > 0 {
for len(str) > 0 {
r1 = r0
r0, size = utf8.DecodeRuneInString(name)
name = name[size:]
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]

if r0 == utf8.RuneError {
buf.WriteRune(unicode.ToLower(r1))
buf.WriteByte(byte(name[0]))
buf.WriteByte(byte(str[0]))
break
}

if !unicode.IsUpper(r0) {
buf.WriteRune('_')
buf.WriteRune(unicode.ToLower(r1))
buf.WriteRune(r0)
if r0 == '_' || r0 == ' ' || r0 == '-' {
r0 = '_'

buf.WriteRune(unicode.ToLower(r1))
} else {
buf.WriteRune('_')
buf.WriteRune(unicode.ToLower(r1))
buf.WriteRune(r0)
}

break
}

buf.WriteRune(unicode.ToLower(r1))
}

if len(name) == 0 {
if len(str) == 0 || r0 == '_' {
buf.WriteRune(unicode.ToLower(r0))
break
}

default:
if r0 == ' ' || r0 == '-' {
r0 = '_'
}

buf.WriteRune(r0)
}
}
Expand Down

0 comments on commit a34d607

Please sign in to comment.