github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/iterator.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  	"fmt"
    21  
    22  	"github.com/goshafaq/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  func (self *ListIterator) next() *Node {
    86  next_start:
    87  	if !self.HasNext() {
    88  		return nil
    89  	} else {
    90  		n := self.p.nodeAt(self.i)
    91  		self.i++
    92  		if !n.Exists() {
    93  			goto next_start
    94  		}
    95  		return n
    96  	}
    97  }
    98  
    99  // Next scans through children of underlying V_ARRAY,
   100  // copies each child to v, and returns .HasNext().
   101  func (self *ListIterator) Next(v *Node) bool {
   102  	n := self.next()
   103  	if n == nil {
   104  		return false
   105  	}
   106  	*v = *n
   107  	return true
   108  }
   109  
   110  func (self *ObjectIterator) next() *Pair {
   111  next_start:
   112  	if !self.HasNext() {
   113  		return nil
   114  	} else {
   115  		n := self.p.pairAt(self.i)
   116  		self.i++
   117  		if !n.Value.Exists() {
   118  			goto next_start
   119  		}
   120  		return n
   121  	}
   122  }
   123  
   124  // Next scans through children of underlying V_OBJECT,
   125  // copies each child to v, and returns .HasNext().
   126  func (self *ObjectIterator) Next(p *Pair) bool {
   127  	n := self.next()
   128  	if n == nil {
   129  		return false
   130  	}
   131  	*p = *n
   132  	return true
   133  }
   134  
   135  // Sequence represents scanning path of single-layer nodes.
   136  // Index indicates the value's order in both V_ARRAY and V_OBJECT json.
   137  // Key is the value's key (for V_OBJECT json only, otherwise it will be nil).
   138  type Sequence struct {
   139  	Index int
   140  	Key   *string
   141  	// Level int
   142  }
   143  
   144  // String is string representation of one Sequence
   145  func (s Sequence) String() string {
   146  	k := ""
   147  	if s.Key != nil {
   148  		k = *s.Key
   149  	}
   150  	return fmt.Sprintf("Sequence(%d, %q)", s.Index, k)
   151  }
   152  
   153  type Scanner func(path Sequence, node *Node) bool
   154  
   155  // ForEach scans one V_OBJECT node's children from JSON head to tail,
   156  // and pass the Sequence and Node of corresponding JSON value.
   157  //
   158  // Especailly, if the node is not V_ARRAY or V_OBJECT,
   159  // the node itself will be returned and Sequence.Index == -1.
   160  //
   161  // NOTICE: A unsetted node WON'T trigger sc, but its index still counts into Path.Index
   162  func (self *Node) ForEach(sc Scanner) error {
   163  	switch self.itype() {
   164  	case types.V_ARRAY:
   165  		iter, err := self.Values()
   166  		if err != nil {
   167  			return err
   168  		}
   169  		v := iter.next()
   170  		for v != nil {
   171  			if !sc(Sequence{iter.i - 1, nil}, v) {
   172  				return nil
   173  			}
   174  			v = iter.next()
   175  		}
   176  	case types.V_OBJECT:
   177  		iter, err := self.Properties()
   178  		if err != nil {
   179  			return err
   180  		}
   181  		v := iter.next()
   182  		for v != nil {
   183  			if !sc(Sequence{iter.i - 1, &v.Key}, &v.Value) {
   184  				return nil
   185  			}
   186  			v = iter.next()
   187  		}
   188  	default:
   189  		if self.Check() != nil {
   190  			return self
   191  		}
   192  		sc(Sequence{-1, nil}, self)
   193  	}
   194  	return nil
   195  }