package kmiputil import ( "regexp" "strings" "golang.org/x/text/cases" "golang.org/x/text/language" ) var ( nonWordAtWordBoundary = regexp.MustCompile(`(\W)([a-zA-Z][a-z])`) startingDigits = regexp.MustCompile(`^([\d]+)(.*)`) ) // NormalizeName converts a string into the CamelCase format required for the XML and JSON encoding // of KMIP values. It should be used for tag names, type names, and enumeration value names. // Implementation of 5.4.1.1 and 5.5.1.1 from the KMIP Profiles specification. func NormalizeName(s string) string { // 1. Replace round brackets ‘(‘, ‘)’ with spaces s = strings.Map(func(r rune) rune { switch r { case '(', ')': return ' ' } return r }, s) // 2. If a non-word char (not alpha, digit or underscore) is followed by a letter (either upper or lower case) then a lower case letter, replace the non-word char with space s = nonWordAtWordBoundary.ReplaceAllString(s, " $2") // 3. Replace remaining non-word chars (except whitespace) with underscore. s = strings.Map(func(r rune) rune { switch { case r >= 'a' && r <= 'z': case r >= 'A' && r <= 'Z': case r >= '0' && r <= '9': case r == '_': case r == ' ': default: return '_' } return r }, s) words := strings.Split(s, " ") for i, w := range words { if i == 0 { // 4. If the first word begins with a digit, move all digits at start of first word to end of first word w = startingDigits.ReplaceAllString(w, `$2$1`) } // 5. Capitalize the first letter of each word words[i] = cases.Title(language.AmericanEnglish, cases.NoLower).String(w) } // 6. Concatenate all words with spaces removed return strings.Join(words, "") }