github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/internal/json/api_compat.go (about) 1 //go:build !amd64 || !go1.16 2 // +build !amd64 !go1.16 3 4 // Copyright 2023 CloudWeGo Authors. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package json 19 20 import ( 21 "encoding/base64" 22 "strconv" 23 "unicode/utf8" 24 _ "unsafe" 25 ) 26 27 func NoQuote(buf *[]byte, val string) { 28 quoteString(buf, val) 29 } 30 31 var ( 32 //go:linkname safeSet encoding/json.safeSet 33 safeSet [utf8.RuneSelf]bool 34 35 //go:linkname hex encoding/json.hex 36 hex string 37 ) 38 39 func quoteString(e *[]byte, s string) { 40 start := 0 41 for i := 0; i < len(s); { 42 if b := s[i]; b < utf8.RuneSelf { 43 if safeSet[b] { 44 i++ 45 continue 46 } 47 if start < i { 48 *e = append(*e, s[start:i]...) 49 } 50 *e = append(*e, '\\') 51 switch b { 52 case '\\', '"': 53 *e = append(*e, b) 54 case '\n': 55 *e = append(*e, 'n') 56 case '\r': 57 *e = append(*e, 'r') 58 case '\t': 59 *e = append(*e, 't') 60 default: 61 // This encodes bytes < 0x20 except for \t, \n and \r. 62 // If escapeHTML is set, it also escapes <, >, and & 63 // because they can lead to security holes when 64 // user-controlled strings are rendered into JSON 65 // and served to some browsers. 66 *e = append(*e, `u00`...) 67 *e = append(*e, hex[b>>4]) 68 *e = append(*e, hex[b&0xF]) 69 } 70 i++ 71 start = i 72 continue 73 } 74 c, size := utf8.DecodeRuneInString(s[i:]) 75 // if c == utf8.RuneError && size == 1 { 76 // if start < i { 77 // e.Write(s[start:i]) 78 // } 79 // e.WriteString(`\ufffd`) 80 // i += size 81 // start = i 82 // continue 83 // } 84 if c == '\u2028' || c == '\u2029' { 85 if start < i { 86 *e = append(*e, s[start:i]...) 87 } 88 *e = append(*e, `\u202`...) 89 *e = append(*e, hex[c&0xF]) 90 i += size 91 start = i 92 continue 93 } 94 i += size 95 } 96 if start < len(s) { 97 *e = append(*e, s[start:]...) 98 } 99 } 100 101 func encodeBase64(src []byte) string { 102 return base64.StdEncoding.EncodeToString(src) 103 } 104 105 func i64toa(buf *[]byte, v int64) { 106 *buf = strconv.AppendInt(*buf, v, 10) 107 } 108 109 func f64toa(buf *[]byte, v float64) { 110 *buf = strconv.AppendFloat(*buf, v, 'g', -1, 64) 111 }