| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- package casing
- // Camel returns the CamelCased name.
- //
- // This was moved from the now deprecated github.com/golang/protobuf/protoc-gen-go/generator package
- //
- // If there is an interior underscore followed by a lower case letter,
- // drop the underscore and convert the letter to upper case.
- // There is a remote possibility of this rewrite causing a name collision,
- // but it's so remote we're prepared to pretend it's nonexistent - since the
- // C++ generator lowercases names, it's extremely unlikely to have two fields
- // with different capitalizations.
- // In short, _my_field_name_2 becomes XMyFieldName_2.
- func Camel(s string) string {
- if s == "" {
- return ""
- }
- t := make([]byte, 0, 32)
- i := 0
- if s[0] == '_' {
- // Need a capital letter; drop the '_'.
- t = append(t, 'X')
- i++
- }
- // Invariant: if the next letter is lower case, it must be converted
- // to upper case.
- // That is, we process a word at a time, where words are marked by _ or
- // upper case letter. Digits are treated as words.
- for ; i < len(s); i++ {
- c := s[i]
- if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
- continue // Skip the underscore in s.
- }
- if isASCIIDigit(c) {
- t = append(t, c)
- continue
- }
- // Assume we have a letter now - if not, it's a bogus identifier.
- // The next word is a sequence of characters that must start upper case.
- if isASCIILower(c) {
- c ^= ' ' // Make it a capital letter.
- }
- t = append(t, c) // Guaranteed not lower case.
- // Accept lower case sequence that follows.
- for i+1 < len(s) && isASCIILower(s[i+1]) {
- i++
- t = append(t, s[i])
- }
- }
- return string(t)
- }
- // And now lots of helper functions.
- // Is c an ASCII lower-case letter?
- func isASCIILower(c byte) bool {
- return 'a' <= c && c <= 'z'
- }
- // Is c an ASCII digit?
- func isASCIIDigit(c byte) bool {
- return '0' <= c && c <= '9'
- }
|