github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/stack.go (about)

     1  package jzon
     2  
     3  import (
     4  	"sync"
     5  )
     6  
     7  var (
     8  	stackPool = sync.Pool{
     9  		New: func() interface{} {
    10  			return &stack{
    11  				stack: make([]uint64, 1),
    12  			}
    13  		},
    14  	}
    15  )
    16  
    17  type stackElement = int8
    18  
    19  const (
    20  	stackElementNone stackElement = -1
    21  
    22  	stackElementObjectBegin stackElement = 0 // 0b00
    23  	stackElementObject      stackElement = 2 // 0b10
    24  
    25  	stackElementArrayBegin stackElement = 1 // 0b01
    26  	stackElementArray      stackElement = 3 // 0b11
    27  )
    28  
    29  type stack struct {
    30  	stack []uint64
    31  	depth uint
    32  }
    33  
    34  func (s *stack) init() *stack {
    35  	s.depth = 0
    36  	return s
    37  }
    38  
    39  func (s *stack) initObject() *stack {
    40  	if len(s.stack) == 0 {
    41  		s.stack = make([]uint64, 1)
    42  	}
    43  	s.stack[0] = 0
    44  	s.depth = 1
    45  	return s
    46  }
    47  
    48  func (s *stack) initArray() *stack {
    49  	if len(s.stack) == 0 {
    50  		s.stack = make([]uint64, 1)
    51  	}
    52  	s.stack[0] = 1
    53  	s.depth = 1
    54  	return s
    55  }
    56  
    57  func (s *stack) top() stackElement {
    58  	if s.depth == 0 {
    59  		return stackElementNone
    60  	}
    61  	depth := s.depth - 1
    62  	div := depth >> 6
    63  	mod := depth & 63
    64  	return stackElement((s.stack[div] >> mod) & 1)
    65  }
    66  
    67  func (s *stack) pop() stackElement {
    68  	if s.depth == 0 {
    69  		return stackElementNone
    70  	}
    71  	depth := s.depth - 1
    72  	div := depth >> 6
    73  	mod := depth & 63
    74  	s.depth--
    75  	// stackElementObjectBegin -> stackElementObject
    76  	// stackElementArrayBegin -> stackElementArray
    77  	return stackElement((s.stack[div]>>mod)&1) | 2
    78  }
    79  
    80  func (s *stack) pushObject() *stack {
    81  	div := s.depth >> 6
    82  	if div == uint(len(s.stack)) {
    83  		s.stack = append(s.stack, 0)
    84  	} else {
    85  		s.stack[div] &= (1 << (s.depth & 63)) - 1
    86  	}
    87  	s.depth++
    88  	return s
    89  }
    90  
    91  func (s *stack) pushArray() *stack {
    92  	div := s.depth >> 6
    93  	if div == uint(len(s.stack)) {
    94  		s.stack = append(s.stack, 1)
    95  	} else {
    96  		s.stack[div] |= 1 << (s.depth & 63)
    97  	}
    98  	s.depth++
    99  	return s
   100  }