github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/ast/encode.go (about)

     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  
    17  package ast
    18  
    19  import (
    20      `sync`
    21      `unicode/utf8`
    22  )
    23  
    24  const (
    25      _MaxBuffer = 1024    // 1KB buffer size
    26  )
    27  
    28  func quoteString(e *[]byte, s string) {
    29      *e = append(*e, '"')
    30      start := 0
    31      for i := 0; i < len(s); {
    32          if b := s[i]; b < utf8.RuneSelf {
    33              if safeSet[b] {
    34                  i++
    35                  continue
    36              }
    37              if start < i {
    38                  *e = append(*e, s[start:i]...)
    39              }
    40              *e = append(*e, '\\')
    41              switch b {
    42              case '\\', '"':
    43                  *e = append(*e, b)
    44              case '\n':
    45                  *e = append(*e, 'n')
    46              case '\r':
    47                  *e = append(*e, 'r')
    48              case '\t':
    49                  *e = append(*e, 't')
    50              default:
    51                  // This encodes bytes < 0x20 except for \t, \n and \r.
    52                  // If escapeHTML is set, it also escapes <, >, and &
    53                  // because they can lead to security holes when
    54                  // user-controlled strings are rendered into JSON
    55                  // and served to some browsers.
    56                  *e = append(*e, `u00`...)
    57                  *e = append(*e, hex[b>>4])
    58                  *e = append(*e, hex[b&0xF])
    59              }
    60              i++
    61              start = i
    62              continue
    63          }
    64          c, size := utf8.DecodeRuneInString(s[i:])
    65          // if c == utf8.RuneError && size == 1 {
    66          //     if start < i {
    67          //         e.Write(s[start:i])
    68          //     }
    69          //     e.WriteString(`\ufffd`)
    70          //     i += size
    71          //     start = i
    72          //     continue
    73          // }
    74          if c == '\u2028' || c == '\u2029' {
    75              if start < i {
    76                  *e = append(*e, s[start:i]...)
    77              }
    78              *e = append(*e, `\u202`...)
    79              *e = append(*e, hex[c&0xF])
    80              i += size
    81              start = i
    82              continue
    83          }
    84          i += size
    85      }
    86      if start < len(s) {
    87          *e = append(*e, s[start:]...)
    88      }
    89      *e = append(*e, '"')
    90  }
    91  
    92  var bytesPool   = sync.Pool{}
    93  
    94  func (self *Node) MarshalJSON() ([]byte, error) {
    95      buf := newBuffer()
    96      err := self.encode(buf)
    97      if err != nil {
    98          freeBuffer(buf)
    99          return nil, err
   100      }
   101  
   102      ret := make([]byte, len(*buf))
   103      copy(ret, *buf)
   104      freeBuffer(buf)
   105      return ret, err
   106  }
   107  
   108  func newBuffer() *[]byte {
   109      if ret := bytesPool.Get(); ret != nil {
   110          return ret.(*[]byte)
   111      } else {
   112          buf := make([]byte, 0, _MaxBuffer)
   113          return &buf
   114      }
   115  }
   116  
   117  func freeBuffer(buf *[]byte) {
   118      *buf = (*buf)[:0]
   119      bytesPool.Put(buf)
   120  }
   121  
   122  func (self *Node) encode(buf *[]byte) error {
   123      if self.IsRaw() {
   124          return self.encodeRaw(buf)
   125      }
   126      switch self.Type() {
   127          case V_NONE  : return ErrNotExist
   128          case V_ERROR : return self.Check()
   129          case V_NULL  : return self.encodeNull(buf)
   130          case V_TRUE  : return self.encodeTrue(buf)
   131          case V_FALSE : return self.encodeFalse(buf)
   132          case V_ARRAY : return self.encodeArray(buf)
   133          case V_OBJECT: return self.encodeObject(buf)
   134          case V_STRING: return self.encodeString(buf)
   135          case V_NUMBER: return self.encodeNumber(buf)
   136          case V_ANY   : return self.encodeInterface(buf)
   137          default      : return ErrUnsupportType 
   138      }
   139  }
   140  
   141  func (self *Node) encodeRaw(buf *[]byte) error {
   142      raw, err := self.Raw()
   143      if err != nil {
   144          return err
   145      }
   146      *buf = append(*buf, raw...)
   147      return nil
   148  }
   149  
   150  func (self *Node) encodeNull(buf *[]byte) error {
   151      *buf = append(*buf, bytesNull...)
   152      return nil
   153  }
   154  
   155  func (self *Node) encodeTrue(buf *[]byte) error {
   156      *buf = append(*buf, bytesTrue...)
   157      return nil
   158  }
   159  
   160  func (self *Node) encodeFalse(buf *[]byte) error {
   161      *buf = append(*buf, bytesFalse...)
   162      return nil
   163  }
   164  
   165  func (self *Node) encodeNumber(buf *[]byte) error {
   166      str := self.toString()
   167      *buf = append(*buf, str...)
   168      return nil
   169  }
   170  
   171  func (self *Node) encodeString(buf *[]byte) error {
   172      if self.l == 0 {
   173          *buf = append(*buf, '"', '"')
   174          return nil
   175      }
   176  
   177      quote(buf, self.toString())
   178      return nil
   179  }
   180  
   181  func (self *Node) encodeArray(buf *[]byte) error {
   182      if self.isLazy() {
   183          if err := self.skipAllIndex(); err != nil {
   184              return err
   185          }
   186      }
   187  
   188      nb := self.len()
   189      if nb == 0 {
   190          *buf = append(*buf, bytesArray...)
   191          return nil
   192      }
   193      
   194      *buf = append(*buf, '[')
   195  
   196      var started bool
   197      for i := 0; i < nb; i++ {
   198          n := self.nodeAt(i)
   199          if !n.Exists() {
   200              continue
   201          }
   202          if started {
   203              *buf = append(*buf, ',')
   204          }
   205          started = true
   206          if err := n.encode(buf); err != nil {
   207              return err
   208          }
   209      }
   210  
   211      *buf = append(*buf, ']')
   212      return nil
   213  }
   214  
   215  func (self *Pair) encode(buf *[]byte) error {
   216      if len(*buf) == 0 {
   217          *buf = append(*buf, '"', '"', ':')
   218          return self.Value.encode(buf)
   219      }
   220  
   221      quote(buf, self.Key)
   222      *buf = append(*buf, ':')
   223  
   224      return self.Value.encode(buf)
   225  }
   226  
   227  func (self *Node) encodeObject(buf *[]byte) error {
   228      if self.isLazy() {
   229          if err := self.skipAllKey(); err != nil {
   230              return err
   231          }
   232      }
   233      
   234      nb := self.len()
   235      if nb == 0 {
   236          *buf = append(*buf, bytesObject...)
   237          return nil
   238      }
   239      
   240      *buf = append(*buf, '{')
   241  
   242      var started bool
   243      for i := 0; i < nb; i++ {
   244          n := self.pairAt(i)
   245          if n == nil || !n.Value.Exists() {
   246              continue
   247          }
   248          if started {
   249              *buf = append(*buf, ',')
   250          }
   251          started = true
   252          if err := n.encode(buf); err != nil {
   253              return err
   254          }
   255      }
   256  
   257      *buf = append(*buf, '}')
   258      return nil
   259  }