127 lines
2.4 KiB
Go
127 lines
2.4 KiB
Go
|
package gopher_utils
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"unicode"
|
||
|
"unicode/utf8"
|
||
|
)
|
||
|
|
||
|
// IsLetter returns true if the 'l' is an English letter.
|
||
|
func IsLetter(l uint8) bool {
|
||
|
n := (l | 0x20) - 'a'
|
||
|
if n >= 0 && n < 26 {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Reverse s string, support unicode
|
||
|
func Reverse(s string) string {
|
||
|
n := len(s)
|
||
|
runes := make([]rune, n)
|
||
|
for _, rune := range s {
|
||
|
n--
|
||
|
runes[n] = rune
|
||
|
}
|
||
|
return string(runes[n:])
|
||
|
}
|
||
|
|
||
|
// ToSnakeCase can convert all upper case characters in a string to
|
||
|
// underscore format.
|
||
|
//
|
||
|
// Some samples.
|
||
|
// "FirstName" => "first_name"
|
||
|
// "HTTPServer" => "http_server"
|
||
|
// "NoHTTPS" => "no_https"
|
||
|
// "GO_PATH" => "go_path"
|
||
|
// "GO PATH" => "go_path" // space is converted to underscore.
|
||
|
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
|
||
|
//
|
||
|
func ToSnakeCase(str string) string {
|
||
|
if len(str) == 0 {
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
buf := &bytes.Buffer{}
|
||
|
var prev, r0, r1 rune
|
||
|
var size int
|
||
|
|
||
|
r0 = '_'
|
||
|
|
||
|
for len(str) > 0 {
|
||
|
prev = r0
|
||
|
r0, size = utf8.DecodeRuneInString(str)
|
||
|
str = str[size:]
|
||
|
|
||
|
switch {
|
||
|
case r0 == utf8.RuneError:
|
||
|
buf.WriteByte(byte(str[0]))
|
||
|
|
||
|
case unicode.IsUpper(r0):
|
||
|
if prev != '_' {
|
||
|
buf.WriteRune('_')
|
||
|
}
|
||
|
|
||
|
buf.WriteRune(unicode.ToLower(r0))
|
||
|
|
||
|
if len(str) == 0 {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
r0, size = utf8.DecodeRuneInString(str)
|
||
|
str = str[size:]
|
||
|
|
||
|
if !unicode.IsUpper(r0) {
|
||
|
buf.WriteRune(r0)
|
||
|
break
|
||
|
}
|
||
|
|
||
|
// find next non-upper-case character and insert `_` properly.
|
||
|
// 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(str) > 0 {
|
||
|
r1 = r0
|
||
|
r0, size = utf8.DecodeRuneInString(str)
|
||
|
str = str[size:]
|
||
|
|
||
|
if r0 == utf8.RuneError {
|
||
|
buf.WriteRune(unicode.ToLower(r1))
|
||
|
buf.WriteByte(byte(str[0]))
|
||
|
break
|
||
|
}
|
||
|
|
||
|
if !unicode.IsUpper(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(str) == 0 || r0 == '_' {
|
||
|
buf.WriteRune(unicode.ToLower(r0))
|
||
|
break
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
if r0 == ' ' || r0 == '-' {
|
||
|
r0 = '_'
|
||
|
}
|
||
|
|
||
|
buf.WriteRune(r0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return buf.String()
|
||
|
}
|