github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/ast/api.go (about) 1 //go:build (amd64 && go1.16 && !go1.23) || (arm64 && go1.20 && !go1.23) 2 // +build amd64,go1.16,!go1.23 arm64,go1.20,!go1.23 3 4 /* 5 * Copyright 2022 ByteDance Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package ast 21 22 import ( 23 `runtime` 24 `unsafe` 25 26 `github.com/bytedance/sonic/encoder` 27 `github.com/bytedance/sonic/internal/native` 28 `github.com/bytedance/sonic/internal/native/types` 29 `github.com/bytedance/sonic/internal/rt` 30 uq `github.com/bytedance/sonic/unquote` 31 `github.com/bytedance/sonic/utf8` 32 ) 33 34 var typeByte = rt.UnpackEface(byte(0)).Type 35 36 //go:nocheckptr 37 func quote(buf *[]byte, val string) { 38 *buf = append(*buf, '"') 39 if len(val) == 0 { 40 *buf = append(*buf, '"') 41 return 42 } 43 44 sp := rt.IndexChar(val, 0) 45 nb := len(val) 46 b := (*rt.GoSlice)(unsafe.Pointer(buf)) 47 48 // input buffer 49 for nb > 0 { 50 // output buffer 51 dp := unsafe.Pointer(uintptr(b.Ptr) + uintptr(b.Len)) 52 dn := b.Cap - b.Len 53 // call native.Quote, dn is byte count it outputs 54 ret := native.Quote(sp, nb, dp, &dn, 0) 55 // update *buf length 56 b.Len += dn 57 58 // no need more output 59 if ret >= 0 { 60 break 61 } 62 63 // double buf size 64 *b = rt.GrowSlice(typeByte, *b, b.Cap*2) 65 // ret is the complement of consumed input 66 ret = ^ret 67 // update input buffer 68 nb -= ret 69 sp = unsafe.Pointer(uintptr(sp) + uintptr(ret)) 70 } 71 72 runtime.KeepAlive(buf) 73 runtime.KeepAlive(sp) 74 *buf = append(*buf, '"') 75 } 76 77 func unquote(src string) (string, types.ParsingError) { 78 return uq.String(src) 79 } 80 81 func (self *Parser) decodeValue() (val types.JsonState) { 82 sv := (*rt.GoString)(unsafe.Pointer(&self.s)) 83 flag := types.F_USE_NUMBER 84 if self.dbuf != nil { 85 flag = 0 86 val.Dbuf = self.dbuf 87 val.Dcap = types.MaxDigitNums 88 } 89 self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, uint64(flag)) 90 return 91 } 92 93 func (self *Parser) skip() (int, types.ParsingError) { 94 fsm := types.NewStateMachine() 95 start := native.SkipOne(&self.s, &self.p, fsm, 0) 96 types.FreeStateMachine(fsm) 97 98 if start < 0 { 99 return self.p, types.ParsingError(-start) 100 } 101 return start, 0 102 } 103 104 func (self *Node) encodeInterface(buf *[]byte) error { 105 //WARN: NOT compatible with json.Encoder 106 return encoder.EncodeInto(buf, self.packAny(), encoder.NoEncoderNewline) 107 } 108 109 func (self *Parser) skipFast() (int, types.ParsingError) { 110 start := native.SkipOneFast(&self.s, &self.p) 111 if start < 0 { 112 return self.p, types.ParsingError(-start) 113 } 114 return start, 0 115 } 116 117 func (self *Parser) getByPath(validate bool, path ...interface{}) (int, types.ParsingError) { 118 var fsm *types.StateMachine 119 if validate { 120 fsm = types.NewStateMachine() 121 } 122 start := native.GetByPath(&self.s, &self.p, &path, fsm) 123 if validate { 124 types.FreeStateMachine(fsm) 125 } 126 runtime.KeepAlive(path) 127 if start < 0 { 128 return self.p, types.ParsingError(-start) 129 } 130 return start, 0 131 } 132 133 func validate_utf8(str string) bool { 134 return utf8.ValidateString(str) 135 }