api_amd64.go 4.2 KB

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