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  }