mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8265029: Preserve SIZED characteristics on slice operations (skip, limit)
Reviewed-by: psandoz
This commit is contained in:
parent
95b1fa7a88
commit
0c9daa7ed5
12 changed files with 704 additions and 89 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -50,7 +50,7 @@ final class SliceOps {
|
|||
* @return the sliced size
|
||||
*/
|
||||
private static long calcSize(long size, long skip, long limit) {
|
||||
return size >= 0 ? Math.max(-1, Math.min(size - skip, limit)) : -1;
|
||||
return size >= 0 ? Math.max(0, Math.min(size - skip, limit)) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,28 +72,23 @@ final class SliceOps {
|
|||
* spliterator type. Requires that the underlying Spliterator
|
||||
* be SUBSIZED.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <P_IN> Spliterator<P_IN> sliceSpliterator(StreamShape shape,
|
||||
Spliterator<P_IN> s,
|
||||
long skip, long limit) {
|
||||
assert s.hasCharacteristics(Spliterator.SUBSIZED);
|
||||
long sliceFence = calcSliceFence(skip, limit);
|
||||
switch (shape) {
|
||||
case REFERENCE:
|
||||
return new StreamSpliterators
|
||||
.SliceSpliterator.OfRef<>(s, skip, sliceFence);
|
||||
case INT_VALUE:
|
||||
return (Spliterator<P_IN>) new StreamSpliterators
|
||||
.SliceSpliterator.OfInt((Spliterator.OfInt) s, skip, sliceFence);
|
||||
case LONG_VALUE:
|
||||
return (Spliterator<P_IN>) new StreamSpliterators
|
||||
.SliceSpliterator.OfLong((Spliterator.OfLong) s, skip, sliceFence);
|
||||
case DOUBLE_VALUE:
|
||||
return (Spliterator<P_IN>) new StreamSpliterators
|
||||
.SliceSpliterator.OfDouble((Spliterator.OfDouble) s, skip, sliceFence);
|
||||
default:
|
||||
throw new IllegalStateException("Unknown shape " + shape);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Spliterator<P_IN> sliceSpliterator = (Spliterator<P_IN>) switch (shape) {
|
||||
case REFERENCE
|
||||
-> new StreamSpliterators.SliceSpliterator.OfRef<>(s, skip, sliceFence);
|
||||
case INT_VALUE
|
||||
-> new StreamSpliterators.SliceSpliterator.OfInt((Spliterator.OfInt) s, skip, sliceFence);
|
||||
case LONG_VALUE
|
||||
-> new StreamSpliterators.SliceSpliterator.OfLong((Spliterator.OfLong) s, skip, sliceFence);
|
||||
case DOUBLE_VALUE
|
||||
-> new StreamSpliterators.SliceSpliterator.OfDouble((Spliterator.OfDouble) s, skip, sliceFence);
|
||||
};
|
||||
return sliceSpliterator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,9 +105,15 @@ final class SliceOps {
|
|||
long skip, long limit) {
|
||||
if (skip < 0)
|
||||
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
|
||||
long normalizedLimit = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
|
||||
return new ReferencePipeline.StatefulOp<T, T>(upstream, StreamShape.REFERENCE,
|
||||
flags(limit)) {
|
||||
@Override
|
||||
long exactOutputSize(long previousSize) {
|
||||
return calcSize(previousSize, skip, normalizedLimit);
|
||||
}
|
||||
|
||||
Spliterator<T> unorderedSkipLimitSpliterator(Spliterator<T> s,
|
||||
long skip, long limit, long sizeIfKnown) {
|
||||
if (skip <= sizeIfKnown) {
|
||||
|
@ -182,9 +183,9 @@ final class SliceOps {
|
|||
|
||||
@Override
|
||||
Sink<T> opWrapSink(int flags, Sink<T> sink) {
|
||||
return new Sink.ChainedReference<T, T>(sink) {
|
||||
return new Sink.ChainedReference<>(sink) {
|
||||
long n = skip;
|
||||
long m = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
long m = normalizedLimit;
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
|
@ -226,9 +227,15 @@ final class SliceOps {
|
|||
long skip, long limit) {
|
||||
if (skip < 0)
|
||||
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
|
||||
long normalizedLimit = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
|
||||
return new IntPipeline.StatefulOp<Integer>(upstream, StreamShape.INT_VALUE,
|
||||
flags(limit)) {
|
||||
@Override
|
||||
long exactOutputSize(long previousSize) {
|
||||
return calcSize(previousSize, skip, normalizedLimit);
|
||||
}
|
||||
|
||||
Spliterator.OfInt unorderedSkipLimitSpliterator(
|
||||
Spliterator.OfInt s, long skip, long limit, long sizeIfKnown) {
|
||||
if (skip <= sizeIfKnown) {
|
||||
|
@ -291,9 +298,9 @@ final class SliceOps {
|
|||
|
||||
@Override
|
||||
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
|
||||
return new Sink.ChainedInt<Integer>(sink) {
|
||||
return new Sink.ChainedInt<>(sink) {
|
||||
long n = skip;
|
||||
long m = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
long m = normalizedLimit;
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
|
@ -335,9 +342,15 @@ final class SliceOps {
|
|||
long skip, long limit) {
|
||||
if (skip < 0)
|
||||
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
|
||||
long normalizedLimit = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
|
||||
return new LongPipeline.StatefulOp<Long>(upstream, StreamShape.LONG_VALUE,
|
||||
flags(limit)) {
|
||||
@Override
|
||||
long exactOutputSize(long previousSize) {
|
||||
return calcSize(previousSize, skip, normalizedLimit);
|
||||
}
|
||||
|
||||
Spliterator.OfLong unorderedSkipLimitSpliterator(
|
||||
Spliterator.OfLong s, long skip, long limit, long sizeIfKnown) {
|
||||
if (skip <= sizeIfKnown) {
|
||||
|
@ -400,9 +413,9 @@ final class SliceOps {
|
|||
|
||||
@Override
|
||||
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
|
||||
return new Sink.ChainedLong<Long>(sink) {
|
||||
return new Sink.ChainedLong<>(sink) {
|
||||
long n = skip;
|
||||
long m = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
long m = normalizedLimit;
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
|
@ -444,9 +457,15 @@ final class SliceOps {
|
|||
long skip, long limit) {
|
||||
if (skip < 0)
|
||||
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
|
||||
long normalizedLimit = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
|
||||
return new DoublePipeline.StatefulOp<Double>(upstream, StreamShape.DOUBLE_VALUE,
|
||||
flags(limit)) {
|
||||
@Override
|
||||
long exactOutputSize(long previousSize) {
|
||||
return calcSize(previousSize, skip, normalizedLimit);
|
||||
}
|
||||
|
||||
Spliterator.OfDouble unorderedSkipLimitSpliterator(
|
||||
Spliterator.OfDouble s, long skip, long limit, long sizeIfKnown) {
|
||||
if (skip <= sizeIfKnown) {
|
||||
|
@ -509,9 +528,9 @@ final class SliceOps {
|
|||
|
||||
@Override
|
||||
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
|
||||
return new Sink.ChainedDouble<Double>(sink) {
|
||||
return new Sink.ChainedDouble<>(sink) {
|
||||
long n = skip;
|
||||
long m = limit >= 0 ? limit : Long.MAX_VALUE;
|
||||
long m = normalizedLimit;
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
|
@ -541,7 +560,7 @@ final class SliceOps {
|
|||
}
|
||||
|
||||
private static int flags(long limit) {
|
||||
return StreamOpFlag.NOT_SIZED | ((limit != -1) ? StreamOpFlag.IS_SHORT_CIRCUIT : 0);
|
||||
return StreamOpFlag.IS_SIZE_ADJUSTING | ((limit != -1) ? StreamOpFlag.IS_SHORT_CIRCUIT : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue