github.com/sandwich-go/boost@v1.3.29/xstrings/camel_case.go (about)

     1  package xstrings
     2  
     3  import "strings"
     4  
     5  // IsASCIILower Is c an ASCII lower-case letter?
     6  func IsASCIILower(c byte) bool {
     7  	return 'a' <= c && c <= 'z'
     8  }
     9  
    10  // IsASCIIDigit Is c an ASCII digit?
    11  func IsASCIIDigit(c byte) bool {
    12  	return '0' <= c && c <= '9'
    13  }
    14  
    15  // CamelCase returns the CamelCased name.
    16  // If there is an interior underscore followed by a lower case letter,
    17  // drop the underscore and convert the letter to upper case.
    18  // There is a remote possibility of this rewrite causing a name collision,
    19  // but it's so remote we're prepared to pretend it's nonexistent - since the
    20  // C++ generator lowercases names, it's extremely unlikely to have two fields
    21  // with different capitalizations.
    22  // In short, _my_field_name_2 becomes XMyFieldName_2.
    23  func CamelCase(s string) string {
    24  	if s == "" {
    25  		return ""
    26  	}
    27  	t := make([]byte, 0, 32)
    28  	i := 0
    29  	if s[0] == '_' {
    30  		// Need a capital letter; drop the '_'.
    31  		t = append(t, 'X')
    32  		i++
    33  	}
    34  	// Invariant: if the next letter is lower case, it must be converted
    35  	// to upper case.
    36  	// That is, we process a word at a time, where words are marked by _ or
    37  	// upper case letter. Digits are treated as words.
    38  	for ; i < len(s); i++ {
    39  		c := s[i]
    40  		if c == '_' && i+1 < len(s) && IsASCIILower(s[i+1]) {
    41  			continue // Skip the underscore in s.
    42  		}
    43  		if IsASCIIDigit(c) {
    44  			t = append(t, c)
    45  			continue
    46  		}
    47  		// Assume we have a letter now - if not, it's a bogus identifier.
    48  		// The next word is a sequence of characters that must start upper case.
    49  		if IsASCIILower(c) {
    50  			c ^= ' ' // Make it a capital letter.
    51  		}
    52  		t = append(t, c) // Guaranteed not lower case.
    53  		// Accept lower case sequence that follows.
    54  		for i+1 < len(s) && IsASCIILower(s[i+1]) {
    55  			i++
    56  			t = append(t, s[i])
    57  		}
    58  	}
    59  	return string(t)
    60  }
    61  
    62  // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
    63  // be joined with "_".
    64  func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }