gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

iterator.go (4273B)


      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     `fmt`
     21 
     22     `github.com/bytedance/sonic/internal/native/types`
     23 )
     24 
     25 type Pair struct {
     26     Key   string
     27     Value Node
     28 }
     29 
     30 // Values returns iterator for array's children traversal
     31 func (self *Node) Values() (ListIterator, error) {
     32     if err := self.should(types.V_ARRAY, "an array"); err != nil {
     33         return ListIterator{}, err
     34     }
     35     return ListIterator{Iterator{p: self}}, nil
     36 }
     37 
     38 // Properties returns iterator for object's children traversal
     39 func (self *Node) Properties() (ObjectIterator, error) {
     40     if err := self.should(types.V_OBJECT, "an object"); err != nil {
     41         return ObjectIterator{}, err
     42     }
     43     return ObjectIterator{Iterator{p: self}}, nil
     44 }
     45 
     46 type Iterator struct {
     47     i int
     48     p *Node
     49 }
     50 
     51 func (self *Iterator) Pos() int {
     52     return self.i
     53 }
     54 
     55 func (self *Iterator) Len() int {
     56     return self.p.len()
     57 }
     58 
     59 // HasNext reports if it is the end of iteration or has error.
     60 func (self *Iterator) HasNext() bool {
     61     if !self.p.isLazy() {
     62         return self.p.Valid() && self.i < self.p.len()
     63     } else if self.p.t == _V_ARRAY_LAZY {
     64         return self.p.skipNextNode().Valid()
     65     } else if self.p.t == _V_OBJECT_LAZY {
     66         pair := self.p.skipNextPair()
     67         if pair == nil {
     68             return false
     69         }
     70         return pair.Value.Valid()
     71     }
     72     return false
     73 }
     74 
     75 // ListIterator is specialized iterator for V_ARRAY
     76 type ListIterator struct {
     77     Iterator
     78 }
     79 
     80 // ObjectIterator is specialized iterator for V_ARRAY
     81 type ObjectIterator struct {
     82     Iterator
     83 }
     84 
     85 // Next scans through children of underlying V_ARRAY, 
     86 // copies each child to v, and returns .HasNext().
     87 func (self *ListIterator) Next(v *Node) bool {
     88     if !self.HasNext() {
     89         return false
     90     } else {
     91         *v, self.i = *self.p.nodeAt(self.i), self.i + 1
     92         return true
     93     }
     94 }
     95 
     96 // Next scans through children of underlying V_OBJECT, 
     97 // copies each child to v, and returns .HasNext().
     98 func (self *ObjectIterator) Next(p *Pair) bool {
     99     if !self.HasNext() {
    100         return false
    101     } else {
    102         *p, self.i = *self.p.pairAt(self.i), self.i + 1
    103         return true
    104     }
    105 }
    106 
    107 // Sequence represents scanning path of single-layer nodes.
    108 // Index indicates the value's order in both V_ARRAY and V_OBJECT json.
    109 // Key is the value's key (for V_OBJECT json only, otherwise it will be nil).
    110 type Sequence struct {
    111     Index int 
    112     Key *string
    113     // Level int
    114 }
    115 
    116 // String is string representation of one Sequence
    117 func (s Sequence) String() string {
    118     k := ""
    119     if s.Key != nil {
    120         k = *s.Key
    121     }
    122     return fmt.Sprintf("Sequence(%d, %q)", s.Index, k)
    123 }
    124 
    125 type Scanner func(path Sequence, node *Node) bool
    126 
    127 // ForEach scans one V_OBJECT node's children from JSON head to tail, 
    128 // and pass the Sequence and Node of corresponding JSON value.
    129 //
    130 // Especailly, if the node is not V_ARRAY or V_OBJECT, 
    131 // the node itself will be returned and Sequence.Index == -1.
    132 func (self *Node) ForEach(sc Scanner) error {
    133     switch self.itype() {
    134     case types.V_ARRAY:
    135         ns, err := self.UnsafeArray()
    136         if err != nil {
    137             return err
    138         }
    139         for i := range ns {
    140             if !sc(Sequence{i, nil}, &ns[i]) {
    141                 return err
    142             }
    143         }
    144     case types.V_OBJECT:
    145         ns, err := self.UnsafeMap()
    146         if err != nil {
    147             return err
    148         }
    149         for i := range ns {
    150             if !sc(Sequence{i, &ns[i].Key}, &ns[i].Value) {
    151                 return err
    152             }
    153         }
    154     default:
    155         sc(Sequence{-1, nil}, self)
    156     }
    157     return self.Check()
    158 }
    159 
    160 type PairSlice []Pair
    161 
    162 func (self PairSlice) Sort() {
    163     radixQsort(self, 0, maxDepth(len(self)))
    164 }