1package kong 2 3// NOTE: This code is from https://github.com/fatih/camelcase. MIT license. 4 5import ( 6 "unicode" 7 "unicode/utf8" 8) 9 10// Split splits the camelcase word and returns a list of words. It also 11// supports digits. Both lower camel case and upper camel case are supported. 12// For more info please check: http://en.wikipedia.org/wiki/CamelCase 13// 14// Examples 15// 16// "" => [""] 17// "lowercase" => ["lowercase"] 18// "Class" => ["Class"] 19// "MyClass" => ["My", "Class"] 20// "MyC" => ["My", "C"] 21// "HTML" => ["HTML"] 22// "PDFLoader" => ["PDF", "Loader"] 23// "AString" => ["A", "String"] 24// "SimpleXMLParser" => ["Simple", "XML", "Parser"] 25// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] 26// "GL11Version" => ["GL", "11", "Version"] 27// "99Bottles" => ["99", "Bottles"] 28// "May5" => ["May", "5"] 29// "BFG9000" => ["BFG", "9000"] 30// "BöseÜberraschung" => ["Böse", "Überraschung"] 31// "Two spaces" => ["Two", " ", "spaces"] 32// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] 33// 34// Splitting rules 35// 36// 1) If string is not valid UTF-8, return it without splitting as 37// single item array. 38// 2) Assign all unicode characters into one of 4 sets: lower case 39// letters, upper case letters, numbers, and all other characters. 40// 3) Iterate through characters of string, introducing splits 41// between adjacent characters that belong to different sets. 42// 4) Iterate through array of split strings, and if a given string 43// is upper case: 44// if subsequent string is lower case: 45// move last character of upper case string to beginning of 46// lower case string 47func camelCase(src string) (entries []string) { 48 // don't split invalid utf8 49 if !utf8.ValidString(src) { 50 return []string{src} 51 } 52 entries = []string{} 53 var runes [][]rune 54 lastClass := 0 55 // split into fields based on class of unicode character 56 for _, r := range src { 57 var class int 58 switch { 59 case unicode.IsLower(r): 60 class = 1 61 case unicode.IsUpper(r): 62 class = 2 63 case unicode.IsDigit(r): 64 class = 3 65 default: 66 class = 4 67 } 68 if class == lastClass { 69 runes[len(runes)-1] = append(runes[len(runes)-1], r) 70 } else { 71 runes = append(runes, []rune{r}) 72 } 73 lastClass = class 74 } 75 // handle upper case -> lower case sequences, e.g. 76 // "PDFL", "oader" -> "PDF", "Loader" 77 for i := 0; i < len(runes)-1; i++ { 78 if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { 79 runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) 80 runes[i] = runes[i][:len(runes[i])-1] 81 } 82 } 83 // construct []string from results 84 for _, s := range runes { 85 if len(s) > 0 { 86 entries = append(entries, string(s)) 87 } 88 } 89 return entries 90} 91