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  }