Skip to content

Commit 9f4ede6

Browse files
BradBot1dmulloy2
authored andcommitted
Custom Spliterator for Structure Modifier
1 parent f768ea0 commit 9f4ede6

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

src/main/java/com/comphenix/protocol/reflect/StructureModifier.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
import java.util.List;
4343
import java.util.Map;
4444
import java.util.Optional;
45+
import java.util.Spliterator;
4546
import java.util.function.UnaryOperator;
4647
import java.util.stream.Collectors;
48+
import java.util.stream.Stream;
4749

4850
/**
4951
* Provides list-oriented access to the fields of a Minecraft packet.
@@ -676,4 +678,12 @@ public String toString() {
676678
public Iterator<StructureModifierIntermediate<T>> iterator() {
677679
return new StructureModifierIterator<T>(this);
678680
}
681+
682+
/**
683+
* {@inheritDoc}
684+
*/
685+
@Override
686+
public Spliterator<StructureModifierIntermediate<T>> spliterator() {
687+
return new StructureModifierSpliterator<T>(this);
688+
}
679689
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
3+
* Copyright (C) 2012 Kristian S. Stangeland
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the
6+
* GNU General Public License as published by the Free Software Foundation; either version 2 of
7+
* the License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11+
* See the GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with this program;
14+
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
15+
* 02111-1307 USA
16+
*/
17+
package com.comphenix.protocol.reflect;
18+
19+
import java.util.Spliterator;
20+
import java.util.function.Consumer;
21+
22+
/**
23+
* Provides {@link Spliterator} access to a {@link StructureModifier}
24+
*
25+
* @param <T> Type of the fields in the {@link StructureModifier}
26+
* @author BradBot_1
27+
*/
28+
class StructureModifierSpliterator<T> implements Spliterator<StructureModifierIntermediate<T>> {
29+
30+
private final StructureModifier<T> structure;
31+
private int index;
32+
private int bounds;
33+
34+
/**
35+
* @param structure - {@link StructureModifier} to operate on.
36+
*/
37+
StructureModifierSpliterator(final StructureModifier<T> structure) {
38+
this(structure, 0, structure.size());
39+
}
40+
41+
/**
42+
* @param structure - {@link StructureModifier} to operate on.
43+
* @param offset - The offset to start at
44+
* @param bounds - The max bound for reading.
45+
*/
46+
StructureModifierSpliterator(final StructureModifier<T> structure, final int offset, final int bounds) {
47+
this.structure = structure;
48+
this.index = offset;
49+
this.bounds = bounds;
50+
}
51+
52+
53+
/**
54+
* {@inheritDoc}
55+
*/
56+
@Override
57+
public StructureModifierSpliterator<T> trySplit() {
58+
final int remainingElements = this.bounds - this.index;
59+
if (remainingElements <= 1) return null; // as spec
60+
final int newSplitBounds = bounds;
61+
this.bounds -= (remainingElements - (remainingElements % 2)) / 2;
62+
return new StructureModifierSpliterator<T>(this.structure, this.bounds, newSplitBounds);
63+
}
64+
65+
66+
/**
67+
* {@inheritDoc}
68+
*/
69+
@Override
70+
public boolean tryAdvance(final Consumer<? super StructureModifierIntermediate<T>> action) throws NullPointerException {
71+
// as demanded by the spec
72+
if (action == null) throw new NullPointerException("The provided consumer is null!");
73+
if (this.index >= this.bounds) return false; // hit end of this spliterator
74+
final StructureModifierIntermediate<T> intermediate = new StructureModifierIntermediate<T>(this.structure, this.index++);
75+
// since it's defined as not null we have to perform this check
76+
// yes this makes {@link #estimateSize} inaccurate in some situations, but that's better than a null
77+
if (intermediate.get() == null) return tryAdvance(action);
78+
action.accept(intermediate);
79+
return true;
80+
}
81+
82+
83+
/**
84+
* {@inheritDoc}
85+
*/
86+
@Override
87+
public void forEachRemaining(Consumer<? super StructureModifierIntermediate<T>> action) {
88+
// as demanded by the spec
89+
if (action == null) throw new NullPointerException("The provided consumer is null!");
90+
while (this.index < this.bounds) {
91+
final StructureModifierIntermediate<T> intermediate = new StructureModifierIntermediate<T>(this.structure, this.index++);
92+
// since it's defined as not null we have to perform this check
93+
if (intermediate.get() == null) continue;
94+
action.accept(intermediate);
95+
}
96+
}
97+
98+
/**
99+
* {@inheritDoc}
100+
*/
101+
@Override
102+
public long estimateSize() {
103+
return this.bounds - this.index;
104+
}
105+
106+
107+
/**
108+
* {@inheritDoc}
109+
*
110+
* @apiNote Since this implementation is ordered we do not need to perform the check, instead we can just call the method
111+
*/
112+
@Override
113+
public long getExactSizeIfKnown() {
114+
return this.estimateSize();
115+
}
116+
117+
118+
/**
119+
* {@inheritDoc}
120+
*/
121+
@Override
122+
public int characteristics() {
123+
return Spliterator.DISTINCT/* | Spliterator.IMMUTABLE*/ | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
124+
}
125+
126+
}

0 commit comments

Comments
 (0)