github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/util/camelcase/camelcase.go (about) 1 // Package camelcase is a micro package to split the words of a camelcase type 2 // string into a slice of words. 3 package camelcase 4 5 import ( 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: https://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 47 func Split(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 var lastClass int 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 90 return entries 91 }