visitor.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright 2021 ByteDance Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package ast
  17. import (
  18. `encoding/json`
  19. `github.com/bytedance/sonic/internal/native/types`
  20. )
  21. // Visitor handles the callbacks during preorder traversal of a JSON AST.
  22. //
  23. // According to the JSON RFC8259, a JSON AST can be defined by
  24. // the following rules without seperator / whitespace tokens.
  25. //
  26. // JSON-AST = value
  27. // value = false / null / true / object / array / number / string
  28. // object = begin-object [ member *( member ) ] end-object
  29. // member = string value
  30. // array = begin-array [ value *( value ) ] end-array
  31. //
  32. type Visitor interface {
  33. // OnNull handles a JSON null value.
  34. OnNull() error
  35. // OnBool handles a JSON true / false value.
  36. OnBool(v bool) error
  37. // OnString handles a JSON string value.
  38. OnString(v string) error
  39. // OnInt64 handles a JSON number value with int64 type.
  40. OnInt64(v int64, n json.Number) error
  41. // OnFloat64 handles a JSON number value with float64 type.
  42. OnFloat64(v float64, n json.Number) error
  43. // OnObjectBegin handles the beginning of a JSON object value with a
  44. // suggested capacity that can be used to make your custom object container.
  45. //
  46. // After this point the visitor will receive a sequence of callbacks like
  47. // [string, value, string, value, ......, ObjectEnd].
  48. //
  49. // Note:
  50. // 1. This is a recursive definition which means the value can
  51. // also be a JSON object / array described by a sequence of callbacks.
  52. // 2. The suggested capacity will be 0 if current object is empty.
  53. // 3. Currently sonic use a fixed capacity for non-empty object (keep in
  54. // sync with ast.Node) which might not be very suitable. This may be
  55. // improved in future version.
  56. OnObjectBegin(capacity int) error
  57. // OnObjectKey handles a JSON object key string in member.
  58. OnObjectKey(key string) error
  59. // OnObjectEnd handles the ending of a JSON object value.
  60. OnObjectEnd() error
  61. // OnArrayBegin handles the beginning of a JSON array value with a
  62. // suggested capacity that can be used to make your custom array container.
  63. //
  64. // After this point the visitor will receive a sequence of callbacks like
  65. // [value, value, value, ......, ArrayEnd].
  66. //
  67. // Note:
  68. // 1. This is a recursive definition which means the value can
  69. // also be a JSON object / array described by a sequence of callbacks.
  70. // 2. The suggested capacity will be 0 if current array is empty.
  71. // 3. Currently sonic use a fixed capacity for non-empty array (keep in
  72. // sync with ast.Node) which might not be very suitable. This may be
  73. // improved in future version.
  74. OnArrayBegin(capacity int) error
  75. // OnArrayEnd handles the ending of a JSON array value.
  76. OnArrayEnd() error
  77. }
  78. // VisitorOptions contains all Visitor's options. The default value is an
  79. // empty VisitorOptions{}.
  80. type VisitorOptions struct {
  81. // OnlyNumber indicates parser to directly return number value without
  82. // conversion, then the first argument of OnInt64 / OnFloat64 will always
  83. // be zero.
  84. OnlyNumber bool
  85. }
  86. var defaultVisitorOptions = &VisitorOptions{}
  87. // Preorder decodes the whole JSON string and callbacks each AST node to visitor
  88. // during preorder traversal. Any visitor method with an error returned will
  89. // break the traversal and the given error will be directly returned. The opts
  90. // argument can be reused after every call.
  91. func Preorder(str string, visitor Visitor, opts *VisitorOptions) error {
  92. if opts == nil {
  93. opts = defaultVisitorOptions
  94. }
  95. // process VisitorOptions first to guarantee that all options will be
  96. // constant during decoding and make options more readable.
  97. var (
  98. optDecodeNumber = !opts.OnlyNumber
  99. )
  100. tv := &traverser{
  101. parser: Parser{
  102. s: str,
  103. noLazy: true,
  104. skipValue: false,
  105. },
  106. visitor: visitor,
  107. }
  108. if optDecodeNumber {
  109. tv.parser.decodeNumber(true)
  110. }
  111. err := tv.decodeValue()
  112. if optDecodeNumber {
  113. tv.parser.decodeNumber(false)
  114. }
  115. return err
  116. }
  117. type traverser struct {
  118. parser Parser
  119. visitor Visitor
  120. }
  121. // NOTE: keep in sync with (*Parser).Parse method.
  122. func (self *traverser) decodeValue() error {
  123. switch val := self.parser.decodeValue(); val.Vt {
  124. case types.V_EOF:
  125. return types.ERR_EOF
  126. case types.V_NULL:
  127. return self.visitor.OnNull()
  128. case types.V_TRUE:
  129. return self.visitor.OnBool(true)
  130. case types.V_FALSE:
  131. return self.visitor.OnBool(false)
  132. case types.V_STRING:
  133. return self.decodeString(val.Iv, val.Ep)
  134. case types.V_DOUBLE:
  135. return self.visitor.OnFloat64(val.Dv,
  136. json.Number(self.parser.s[val.Ep:self.parser.p]))
  137. case types.V_INTEGER:
  138. return self.visitor.OnInt64(val.Iv,
  139. json.Number(self.parser.s[val.Ep:self.parser.p]))
  140. case types.V_ARRAY:
  141. return self.decodeArray()
  142. case types.V_OBJECT:
  143. return self.decodeObject()
  144. default:
  145. return types.ParsingError(-val.Vt)
  146. }
  147. }
  148. // NOTE: keep in sync with (*Parser).decodeArray method.
  149. func (self *traverser) decodeArray() error {
  150. sp := self.parser.p
  151. ns := len(self.parser.s)
  152. /* check for EOF */
  153. self.parser.p = self.parser.lspace(sp)
  154. if self.parser.p >= ns {
  155. return types.ERR_EOF
  156. }
  157. /* check for empty array */
  158. if self.parser.s[self.parser.p] == ']' {
  159. self.parser.p++
  160. if err := self.visitor.OnArrayBegin(0); err != nil {
  161. return err
  162. }
  163. return self.visitor.OnArrayEnd()
  164. }
  165. /* allocate array space and parse every element */
  166. if err := self.visitor.OnArrayBegin(_DEFAULT_NODE_CAP); err != nil {
  167. return err
  168. }
  169. for {
  170. /* decode the value */
  171. if err := self.decodeValue(); err != nil {
  172. return err
  173. }
  174. self.parser.p = self.parser.lspace(self.parser.p)
  175. /* check for EOF */
  176. if self.parser.p >= ns {
  177. return types.ERR_EOF
  178. }
  179. /* check for the next character */
  180. switch self.parser.s[self.parser.p] {
  181. case ',':
  182. self.parser.p++
  183. case ']':
  184. self.parser.p++
  185. return self.visitor.OnArrayEnd()
  186. default:
  187. return types.ERR_INVALID_CHAR
  188. }
  189. }
  190. }
  191. // NOTE: keep in sync with (*Parser).decodeObject method.
  192. func (self *traverser) decodeObject() error {
  193. sp := self.parser.p
  194. ns := len(self.parser.s)
  195. /* check for EOF */
  196. self.parser.p = self.parser.lspace(sp)
  197. if self.parser.p >= ns {
  198. return types.ERR_EOF
  199. }
  200. /* check for empty object */
  201. if self.parser.s[self.parser.p] == '}' {
  202. self.parser.p++
  203. if err := self.visitor.OnObjectBegin(0); err != nil {
  204. return err
  205. }
  206. return self.visitor.OnObjectEnd()
  207. }
  208. /* allocate object space and decode each pair */
  209. if err := self.visitor.OnObjectBegin(_DEFAULT_NODE_CAP); err != nil {
  210. return err
  211. }
  212. for {
  213. var njs types.JsonState
  214. var err types.ParsingError
  215. /* decode the key */
  216. if njs = self.parser.decodeValue(); njs.Vt != types.V_STRING {
  217. return types.ERR_INVALID_CHAR
  218. }
  219. /* extract the key */
  220. idx := self.parser.p - 1
  221. key := self.parser.s[njs.Iv:idx]
  222. /* check for escape sequence */
  223. if njs.Ep != -1 {
  224. if key, err = unquote(key); err != 0 {
  225. return err
  226. }
  227. }
  228. if err := self.visitor.OnObjectKey(key); err != nil {
  229. return err
  230. }
  231. /* expect a ':' delimiter */
  232. if err = self.parser.delim(); err != 0 {
  233. return err
  234. }
  235. /* decode the value */
  236. if err := self.decodeValue(); err != nil {
  237. return err
  238. }
  239. self.parser.p = self.parser.lspace(self.parser.p)
  240. /* check for EOF */
  241. if self.parser.p >= ns {
  242. return types.ERR_EOF
  243. }
  244. /* check for the next character */
  245. switch self.parser.s[self.parser.p] {
  246. case ',':
  247. self.parser.p++
  248. case '}':
  249. self.parser.p++
  250. return self.visitor.OnObjectEnd()
  251. default:
  252. return types.ERR_INVALID_CHAR
  253. }
  254. }
  255. }
  256. // NOTE: keep in sync with (*Parser).decodeString method.
  257. func (self *traverser) decodeString(iv int64, ep int) error {
  258. p := self.parser.p - 1
  259. s := self.parser.s[iv:p]
  260. /* fast path: no escape sequence */
  261. if ep == -1 {
  262. return self.visitor.OnString(s)
  263. }
  264. /* unquote the string */
  265. out, err := unquote(s)
  266. if err != 0 {
  267. return err
  268. }
  269. return self.visitor.OnString(out)
  270. }