github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/internal/util.go (about) 1 package internal 2 3 import ( 4 "bytes" 5 "unicode" 6 "unicode/utf8" 7 ) 8 9 // JsonName returns the default JSON name for a field with the given name. 10 func JsonName(name string) string { 11 var js []rune 12 nextUpper := false 13 for i, r := range name { 14 if r == '_' { 15 nextUpper = true 16 continue 17 } 18 if i == 0 { 19 js = append(js, r) 20 } else if nextUpper { 21 nextUpper = false 22 js = append(js, unicode.ToUpper(r)) 23 } else { 24 js = append(js, r) 25 } 26 } 27 return string(js) 28 } 29 30 // InitCap returns the given field name, but with the first letter capitalized. 31 func InitCap(name string) string { 32 r, sz := utf8.DecodeRuneInString(name) 33 return string(unicode.ToUpper(r)) + name[sz:] 34 } 35 36 // CreatePrefixList returns a list of package prefixes to search when resolving 37 // a symbol name. If the given package is blank, it returns only the empty 38 // string. If the given package contains only one token, e.g. "foo", it returns 39 // that token and the empty string, e.g. ["foo", ""]. Otherwise, it returns 40 // successively shorter prefixes of the package and then the empty string. For 41 // example, for a package named "foo.bar.baz" it will return the following list: 42 // ["foo.bar.baz", "foo.bar", "foo", ""] 43 func CreatePrefixList(pkg string) []string { 44 if pkg == "" { 45 return []string{""} 46 } 47 48 numDots := 0 49 // one pass to pre-allocate the returned slice 50 for i := 0; i < len(pkg); i++ { 51 if pkg[i] == '.' { 52 numDots++ 53 } 54 } 55 if numDots == 0 { 56 return []string{pkg, ""} 57 } 58 59 prefixes := make([]string, numDots+2) 60 // second pass to fill in returned slice 61 for i := 0; i < len(pkg); i++ { 62 if pkg[i] == '.' { 63 prefixes[numDots] = pkg[:i] 64 numDots-- 65 } 66 } 67 prefixes[0] = pkg 68 69 return prefixes 70 } 71 72 func WriteEscapedBytes(buf *bytes.Buffer, b []byte) { 73 for _, c := range b { 74 switch c { 75 case '\n': 76 buf.WriteString("\\n") 77 case '\r': 78 buf.WriteString("\\r") 79 case '\t': 80 buf.WriteString("\\t") 81 case '"': 82 buf.WriteString("\\\"") 83 case '\'': 84 buf.WriteString("\\'") 85 case '\\': 86 buf.WriteString("\\\\") 87 default: 88 if c >= 0x20 && c <= 0x7f && c != '"' && c != '\\' { 89 // simple printable characters 90 buf.WriteByte(c) 91 } else { 92 // use octal escape for all other values 93 buf.WriteRune('\\') 94 buf.WriteByte('0' + ((c >> 6) & 0x7)) 95 buf.WriteByte('0' + ((c >> 3) & 0x7)) 96 buf.WriteByte('0' + (c & 0x7)) 97 } 98 } 99 } 100 }