util.go (2740B)
1 package format 2 3 import ( 4 "strings" 5 "unsafe" 6 ) 7 8 const ( 9 // SingleTermLine: beyond a certain length of string, all of the 10 // extra checks to handle quoting/not-quoting add a significant 11 // amount of extra processing time. Quoting in this manner only really 12 // effects readability on a single line, so a max string length that 13 // encompasses the maximum number of columns on *most* terminals was 14 // selected. This was chosen using the metric that 1080p is one of the 15 // most common display resolutions, and that a relatively small font size 16 // of 7 requires 223 columns. So 256 should be >= $COLUMNS (fullscreen) 17 // in 99% of usecases (these figures all pulled out of my ass). 18 SingleTermLine = 256 19 ) 20 21 // IsSafeASCII checks whether string is printable (i.e. non-control char) ASCII text. 22 func IsSafeASCII(str string) bool { 23 for _, r := range str { 24 if (r < ' ' && r != '\t') || 25 r >= 0x7f { 26 return false 27 } 28 } 29 return true 30 } 31 32 // ContainsSpaceOrTab checks if "s" contains space or tabs. 33 func ContainsSpaceOrTab(s string) bool { 34 if i := strings.IndexByte(s, ' '); i >= 0 { 35 return true // note using indexbyte as it is ASM. 36 } else if i := strings.IndexByte(s, '\t'); i >= 0 { 37 return true 38 } 39 return false 40 } 41 42 // ContainsDoubleQuote checks if "s" contains a double quote. 43 func ContainsDoubleQuote(s string) bool { 44 return (strings.IndexByte(s, '"') >= 0) 45 } 46 47 // AppendEscape will append 's' to 'dst' and escape any double quotes. 48 func AppendEscape(dst []byte, str string) []byte { 49 var delim bool 50 for i := range str { 51 if str[i] == '\\' && !delim { 52 // Set delim flag 53 delim = true 54 continue 55 } else if str[i] == '"' && !delim { 56 // Append escaped double quote 57 dst = append(dst, `\"`...) 58 continue 59 } else if delim { 60 // Append skipped slash 61 dst = append(dst, `\`...) 62 delim = false 63 } 64 65 // Append char as-is 66 dst = append(dst, str[i]) 67 } 68 return dst 69 } 70 71 // Byte2Str returns 'c' as a string, escaping if necessary. 72 func Byte2Str(c byte) string { 73 switch c { 74 case '\a': 75 return `\a` 76 case '\b': 77 return `\b` 78 case '\f': 79 return `\f` 80 case '\n': 81 return `\n` 82 case '\r': 83 return `\r` 84 case '\t': 85 return `\t` 86 case '\v': 87 return `\v` 88 case '\'': 89 return `\\` 90 default: 91 if c < ' ' { 92 const hex = "0123456789abcdef" 93 return `\x` + 94 string(hex[c>>4]) + 95 string(hex[c&0xF]) 96 } 97 return string(c) 98 } 99 } 100 101 // isNil will safely check if 'v' is nil without dealing with weird Go interface nil bullshit. 102 func isNil(i interface{}) bool { 103 type eface struct{ _type, data unsafe.Pointer } //nolint 104 return (*(*eface)(unsafe.Pointer(&i))).data == nil //nolint 105 } 106 107 // b2s converts a byteslice to string without allocation. 108 func b2s(b []byte) string { 109 return *(*string)(unsafe.Pointer(&b)) 110 }