// ------------------------------------------------------------------------ // Project atila // Active Thing (activething.com) git.activething.com/go // // File name builder_state.go // Created by DEV // Modified 16/01/2024 // // Copyright 2024 activething.com // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------ package __packs import ( "activething.com/go/gogo/core/bins" "activething.com/go/gogo/core/slices" "activething.com/go/gogo/core/syncs" "sync/atomic" ) const maxCyclesCheckIdle = 100 type ( State struct { *bins.Buffer/*Embedded*/ Node *StateNode Temp [64]byte Seen map[any]struct{} Error error } ) func NewState() *State { if atomic.CompareAndSwapUint32(&G.poolsSem,0,1) { G.nodePool = syncs.NewPool[StateNode]( syncs.PoolWithNew[StateNode](func()*StateNode{ return &StateNode{ Kind: NodeKindValue, keys: make(slices.String, 0, 10), } }), ) G.statePool = syncs.NewPool[State]( syncs.PoolWithNew[State](func() *State { return &State{ Node : G.nodePool.Get().Init(nil, NodeKindValue, 0), Buffer: bins.NewBuffer(), Seen: make(map[any]struct{}), } }), ) } return G.statePool.Get() } func ReleaseState (state *State) { if state == nil { state.Buffer.Reset() state.Node.Reset() state.Error = nil if atomic.LoadUint32(&G.poolsSem) == 1 { G.statePool.Put(state) } } } func (s *State) SetError(err error) bool { if s.Error != nil { return true } if err == nil { return false } s.Error = err s.Reset() s.Node.Reset() return true } func (s *State) SetKey(key string) bool { if s.Error != nil { return false } if s.Node.keys.Has(key) { return !s.SetError(G.ErrDuplicatedKey) } s.Node.keys = s.Node.keys.Append(key) return true } func (s *State) SetValue() bool { if s.Error != nil { return false } s.Node.Count++ return true } func (s *State) Open(kind NodeKind) bool { if s.Error != nil { return false } if s.Node.Kind == NodeKindValue { if s.Node.Count > 0 { return !s.SetError(G.ErrInvalidNode) } s.Node.Init(s.Node.Parent, kind, s.Len()) } else { s.Node = G.nodePool.Get().Init(s.Node, kind, s.Len()) } return true } func (s *State) Close() bool { if s.Error != nil { return false } if s.Node.Kind == NodeKindValue { return !s.SetError(G.ErrInvalidNode) } if s.Node.Parent != nil { p := s.Node s.Node = s.Node.Parent G.nodePool.Put(p.Reset()) } s.Node.Count++ return true }