github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/internal/json/api_amd64.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  	"runtime"
    22  	"unsafe"
    23  
    24  	"github.com/cloudwego/base64x"
    25  	"github.com/cloudwego/dynamicgo/internal/native"
    26  	"github.com/cloudwego/dynamicgo/internal/native/types"
    27  	"github.com/cloudwego/dynamicgo/internal/rt"
    28  )
    29  
    30  
    31  var typeByte = rt.UnpackEface(byte(0)).Type
    32  
    33  //go:nocheckptr
    34  // NoQuote only escape inner '\' and '"' of one string, but it does add quotes besides string.
    35  func NoQuote(buf *[]byte, val string) {
    36  	sp := rt.IndexChar(val, 0)
    37  	nb := len(val)
    38  	b := (*rt.GoSlice)(unsafe.Pointer(buf))
    39  
    40  	// input buffer
    41  	for nb > 0 {
    42  		// output buffer
    43  		dp := unsafe.Pointer(uintptr(b.Ptr) + uintptr(b.Len))
    44  		dn := b.Cap - b.Len
    45  		// call native.Quote, dn is byte count it outputs
    46  		ret := native.Quote(sp, nb, dp, &dn, 0)
    47  		// update *buf length
    48  		b.Len += dn
    49  
    50  		// no need more output
    51  		if ret >= 0 {
    52  			break
    53  		}
    54  
    55  		// double buf size
    56  		*b = rt.Growslice(typeByte, *b, b.Cap*2)
    57  		// ret is the complement of consumed input
    58  		ret = ^ret
    59  		// update input buffer
    60  		nb -= ret
    61  		sp = unsafe.Pointer(uintptr(sp) + uintptr(ret))
    62  	}
    63  
    64  	runtime.KeepAlive(buf)
    65  	runtime.KeepAlive(sp)
    66  }
    67  
    68  func i64toa(buf *[]byte, val int64) int {
    69  	rt.GuardSlice(buf, types.MaxInt64StringLen)
    70  	s := len(*buf)
    71  	ret := native.I64toa((*byte)(rt.IndexPtr((*rt.GoSlice)(unsafe.Pointer(buf)).Ptr, typeByte.Size, s)), val)
    72  	if ret < 0 {
    73  		*buf = append((*buf)[s:], '0')
    74  		return 1
    75  	}
    76  	*buf = (*buf)[:s+ret]
    77  	return ret
    78  }
    79  
    80  func f64toa(buf *[]byte, val float64) int {
    81  	rt.GuardSlice(buf, types.MaxFloat64StringLen)
    82  	s := len(*buf)
    83  	ret := native.F64toa((*byte)(rt.IndexPtr((*rt.GoSlice)(unsafe.Pointer(buf)).Ptr, typeByte.Size, s)), val)
    84  	if ret < 0 {
    85  		*buf = append((*buf)[s:], '0')
    86  		return 1
    87  	}
    88  	*buf = (*buf)[:s+ret]
    89  	return ret
    90  }
    91  
    92  func encodeBase64(src []byte) string {
    93  	return base64x.StdEncoding.EncodeToString(src)
    94  }