github.com/searKing/golang/go@v1.2.74/util/spliterator/slice_spliterator.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package spliterator 6 7 import ( 8 "context" 9 10 "github.com/searKing/golang/go/error/exception" 11 "github.com/searKing/golang/go/util/function/consumer" 12 "github.com/searKing/golang/go/util/object" 13 ) 14 15 /** 16 * A slice Spliterator from a source Spliterator that reports 17 * {@code SUBSIZED}. 18 * 19 */ 20 type sliceSpliterator struct { 21 OfPrimitive 22 23 array []interface{} 24 25 index int // current index, modified on advance/split 26 fence int // one past last index 27 cs Characteristic 28 } 29 30 func NewSliceSpliterator2(acs Characteristic, arrays ...interface{}) Spliterator { 31 return NewSliceSpliterator4(0, len(arrays), acs, arrays...) 32 } 33 34 func NewSliceSpliterator4(origin int, fence int, acs Characteristic, arrays ...interface{}) Spliterator { 35 split := &sliceSpliterator{ 36 array: arrays, 37 index: origin, 38 fence: fence, 39 cs: acs | CharacteristicOrdered | CharacteristicSized | CharacteristicSubsized, 40 } 41 split.SetDerived(split) 42 return split 43 } 44 45 func (split *sliceSpliterator) TrySplit() Spliterator { 46 lo := split.index 47 mid := (lo + split.fence) >> 1 48 if lo >= mid { 49 return nil 50 } 51 split.index = mid 52 return NewSliceSpliterator4(lo, mid, split.cs, split.array...) 53 } 54 55 func (split *sliceSpliterator) ForEachRemaining(ctx context.Context, action consumer.Consumer) { 56 object.RequireNonNil(action) 57 58 var a []interface{} 59 var i, hi int // hoist accesses and checks from loop 60 a = split.array 61 62 hi = split.fence 63 i = split.index 64 split.index = hi 65 if len(a) >= hi && i >= 0 && i < hi { 66 for ; i < hi; i++ { 67 select { 68 case <-ctx.Done(): 69 return 70 default: 71 } 72 action.Accept(a[i]) 73 } 74 } 75 return 76 } 77 78 func (split *sliceSpliterator) TryAdvance(ctx context.Context, action consumer.Consumer) bool { 79 if action == nil { 80 panic(exception.NewNullPointerException()) 81 } 82 if split.index >= 0 && split.index < split.fence { 83 action.Accept(split.array[split.index]) 84 split.index++ 85 return true 86 } 87 return false 88 } 89 90 func (split *sliceSpliterator) EstimateSize() int { 91 return split.fence - split.index 92 } 93 94 func (split *sliceSpliterator) Characteristics() Characteristic { 95 return split.cs 96 } 97 98 func (split *sliceSpliterator) GetComparator() object.Comparator { 99 if split.GetDerivedElse(split).(Spliterator).HasCharacteristics(CharacteristicSorted) { 100 return nil 101 } 102 panic(exception.NewIllegalStateException()) 103 }