github.com/tobgu/qframe@v0.4.0/internal/strings/serialize.go (about)

     1  package strings
     2  
     3  import (
     4  	"unicode/utf8"
     5  )
     6  
     7  const chars = "0123456789abcdef"
     8  
     9  func AppendQuotedString(buf []byte, str string) []byte {
    10  	// String escape code is highly inspired by the escape code in easyjson.
    11  	buf = append(buf, '"')
    12  	p := 0
    13  	// last non-escape symbol
    14  	for i := 0; i < len(str); {
    15  		c := str[i]
    16  
    17  		if c != '\\' && c != '"' && c >= 0x20 && c < utf8.RuneSelf {
    18  			// single-width character, no escaping is required
    19  			i++
    20  			continue
    21  		}
    22  
    23  		if c < utf8.RuneSelf {
    24  			// single-with character, need to escape
    25  			buf = append(buf, str[p:i]...)
    26  
    27  			switch c {
    28  			case '\t':
    29  				buf = append(buf, `\t`...)
    30  			case '\r':
    31  				buf = append(buf, `\r`...)
    32  			case '\n':
    33  				buf = append(buf, `\n`...)
    34  			case '\\':
    35  				buf = append(buf, `\\`...)
    36  			case '"':
    37  				buf = append(buf, `\"`...)
    38  			default:
    39  				buf = append(buf, `\u00`...)
    40  				buf = append(buf, chars[c>>4])
    41  				buf = append(buf, chars[c&0xf])
    42  			}
    43  
    44  			i++
    45  			p = i
    46  			continue
    47  		}
    48  
    49  		// broken utf
    50  		runeValue, runeWidth := utf8.DecodeRuneInString(str[i:])
    51  		if runeValue == utf8.RuneError && runeWidth == 1 {
    52  			buf = append(buf, str[p:i]...)
    53  			buf = append(buf, `\ufffd`...)
    54  			i++
    55  			p = i
    56  			continue
    57  		}
    58  
    59  		// jsonp stuff - tab separator and line separator
    60  		if runeValue == '\u2028' || runeValue == '\u2029' {
    61  			buf = append(buf, str[p:i]...)
    62  			buf = append(buf, `\u202`...)
    63  			buf = append(buf, chars[runeValue&0xf])
    64  			i += runeWidth
    65  			p = i
    66  			continue
    67  		}
    68  		i += runeWidth
    69  	}
    70  
    71  	buf = append(buf, str[p:]...)
    72  	buf = append(buf, '"')
    73  	return buf
    74  }