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() }