1ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/*
2ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
5ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is free software; you can redistribute it and/or modify it
6ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * under the terms of the GNU General Public License version 2 only, as
7ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * published by the Free Software Foundation.  Oracle designates this
8ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * particular file as subject to the "Classpath" exception as provided
9ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * by Oracle in the LICENSE file that accompanied this code.
10ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
11ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * This code is distributed in the hope that it will be useful, but WITHOUT
12ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * version 2 for more details (a copy is included in the LICENSE file that
15ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * accompanied this code).
16ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
17ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * You should have received a copy of the GNU General Public License version
18ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * 2 along with this work; if not, write to the Free Software Foundation,
19ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
21ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * or visit www.oracle.com if you need additional information or have any
23ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * questions.
24ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
25ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinpackage java.util.stream;
26ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
27ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.EnumMap;
28ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Map;
29ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkinimport java.util.Spliterator;
30ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
31ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin/**
32ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Flags corresponding to characteristics of streams and operations. Flags are
33ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * utilized by the stream framework to control, specialize or optimize
34ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * computation.
35ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
36ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>
37ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Stream flags may be used to describe characteristics of several different
38ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * entities associated with streams: stream sources, intermediate operations,
39ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * and terminal operations.  Not all stream flags are meaningful for all
40ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * entities; the following table summarizes which flags are meaningful in what
41ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * contexts:
42ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
43ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <div>
44ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <table>
45ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   <caption>Type Characteristics</caption>
46ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   <thead class="tableSubHeadingColor">
47ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     <tr>
48ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th colspan="2">&nbsp;</th>
49ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th>{@code DISTINCT}</th>
50ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th>{@code SORTED}</th>
51ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th>{@code ORDERED}</th>
52ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th>{@code SIZED}</th>
53ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <th>{@code SHORT_CIRCUIT}</th>
54ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     </tr>
55ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   </thead>
56ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   <tbody>
57ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      <tr>
58ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <th colspan="2" class="tableSubHeadingColor">Stream source</th>
59ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>Y</td>
60ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>Y</td>
61ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>Y</td>
62ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>Y</td>
63ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>N</td>
64ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      </tr>
65ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      <tr>
66ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <th colspan="2" class="tableSubHeadingColor">Intermediate operation</th>
67ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PCI</td>
68ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PCI</td>
69ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PCI</td>
70ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PC</td>
71ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PI</td>
72ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      </tr>
73ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      <tr>
74ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <th colspan="2" class="tableSubHeadingColor">Terminal operation</th>
75ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>N</td>
76ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>N</td>
77ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PC</td>
78ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>N</td>
79ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *        <td>PI</td>
80ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *      </tr>
81ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   </tbody>
82ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   <tfoot>
83ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr>
84ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *         <th class="tableSubHeadingColor" colspan="2">Legend</th>
85ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *         <th colspan="6" rowspan="7">&nbsp;</th>
86ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       </tr>
87ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr>
88ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *         <th class="tableSubHeadingColor">Flag</th>
89ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *         <th class="tableSubHeadingColor">Meaning</th>
90ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *         <th colspan="6"></th>
91ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       </tr>
92ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr><td>Y</td><td>Allowed</td></tr>
93ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr><td>N</td><td>Invalid</td></tr>
94ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr><td>P</td><td>Preserves</td></tr>
95ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr><td>C</td><td>Clears</td></tr>
96ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *       <tr><td>I</td><td>Injects</td></tr>
97ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *   </tfoot>
98ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * </table>
99ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * </div>
100ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
101ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>In the above table, "PCI" means "may preserve, clear, or inject"; "PC"
102ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * means "may preserve or clear", "PI" means "may preserve or inject", and "N"
103ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * means "not valid".
104ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
105ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>Stream flags are represented by unioned bit sets, so that a single word
106ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * may describe all the characteristics of a given stream entity, and that, for
107ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * example, the flags for a stream source can be efficiently combined with the
108ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * flags for later operations on that stream.
109ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
110ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>The bit masks {@link #STREAM_MASK}, {@link #OP_MASK}, and
111ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link #TERMINAL_OP_MASK} can be ANDed with a bit set of stream flags to
112ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * produce a mask containing only the valid flags for that entity type.
113ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
114ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>When describing a stream source, one only need describe what
115ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * characteristics that stream has; when describing a stream operation, one need
116ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * describe whether the operation preserves, injects, or clears that
117ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * characteristic.  Accordingly, two bits are used for each flag, so as to allow
118ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * representing not only the presence of of a characteristic, but how an
119ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * operation modifies that characteristic.  There are two common forms in which
120ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * flag bits are combined into an {@code int} bit set.  <em>Stream flags</em>
121ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * are a unioned bit set constructed by ORing the enum characteristic values of
122ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link #set()} (or, more commonly, ORing the corresponding static named
123ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * constants prefixed with {@code IS_}).  <em>Operation flags</em> are a unioned
124ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * bit set constructed by ORing the enum characteristic values of {@link #set()}
125ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * or {@link #clear()} (to inject, or clear, respectively, the corresponding
126ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * flag), or more commonly ORing the corresponding named constants prefixed with
127ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@code IS_} or {@code NOT_}.  Flags that are not marked with {@code IS_} or
128ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@code NOT_} are implicitly treated as preserved.  Care must be taken when
129ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * combining bitsets that the correct combining operations are applied in the
130ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * correct order.
131ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
132ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>
133ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * With the exception of {@link #SHORT_CIRCUIT}, stream characteristics can be
134ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * derived from the equivalent {@link java.util.Spliterator} characteristics:
135ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link java.util.Spliterator#DISTINCT}, {@link java.util.Spliterator#SORTED},
136ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link java.util.Spliterator#ORDERED}, and
137ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link java.util.Spliterator#SIZED}.  A spliterator characteristics bit set
138ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * can be converted to stream flags using the method
139ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link #fromCharacteristics(java.util.Spliterator)} and converted back using
140ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link #toCharacteristics(int)}.  (The bit set
141ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link #SPLITERATOR_CHARACTERISTICS_MASK} is used to AND with a bit set to
142ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * produce a valid spliterator characteristics bit set that can be converted to
143ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * stream flags.)
144ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
145ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>
146ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * The source of a stream encapsulates a spliterator. The characteristics of
147ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * that source spliterator when transformed to stream flags will be a proper
148ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * subset of stream flags of that stream.
149ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * For example:
150ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <pre> {@code
151ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     Spliterator s = ...;
152ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     Stream stream = Streams.stream(s);
153ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     flagsFromSplitr = fromCharacteristics(s.characteristics());
154ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     assert(flagsFromSplitr & stream.getStreamFlags() == flagsFromSplitr);
155ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * }</pre>
156ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
157ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>
158ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * An intermediate operation, performed on an input stream to create a new
159ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * output stream, may preserve, clear or inject stream or operation
160ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * characteristics.  Similarly, a terminal operation, performed on an input
161ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * stream to produce an output result may preserve, clear or inject stream or
162ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * operation characteristics.  Preservation means that if that characteristic
163ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * is present on the input, then it is also present on the output.  Clearing
164ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * means that the characteristic is not present on the output regardless of the
165ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * input.  Injection means that the characteristic is present on the output
166ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * regardless of the input.  If a characteristic is not cleared or injected then
167ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * it is implicitly preserved.
168ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
169ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>
170ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * A pipeline consists of a stream source encapsulating a spliterator, one or
171ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * more intermediate operations, and finally a terminal operation that produces
172ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * a result.  At each stage of the pipeline, a combined stream and operation
173ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * flags can be calculated, using {@link #combineOpFlags(int, int)}.  Such flags
174ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * ensure that preservation, clearing and injecting information is retained at
175ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * each stage.
176ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
177ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * The combined stream and operation flags for the source stage of the pipeline
178ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * is calculated as follows:
179ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <pre> {@code
180ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     int flagsForSourceStage = combineOpFlags(sourceFlags, INITIAL_OPS_VALUE);
181ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * }</pre>
182ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
183ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * The combined stream and operation flags of each subsequent intermediate
184ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * operation stage in the pipeline is calculated as follows:
185ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <pre> {@code
186ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *     int flagsForThisStage = combineOpFlags(flagsForPreviousStage, thisOpFlags);
187ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * }</pre>
188ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
189ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * Finally the flags output from the last intermediate operation of the pipeline
190ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * are combined with the operation flags of the terminal operation to produce
191ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * the flags output from the pipeline.
192ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
193ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * <p>Those flags can then be used to apply optimizations. For example, if
194ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@code SIZED.isKnown(flags)} returns true then the stream size remains
195ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * constant throughout the pipeline, this information can be utilized to
196ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * pre-allocate data structures and combined with
197ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * {@link java.util.Spliterator#SUBSIZED} that information can be utilized to
198ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * perform concurrent in-place updates into a shared array.
199ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
200ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * For specific details see the {@link AbstractPipeline} constructors.
201ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin *
202ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin * @since 1.8
203289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin * @hide Visible for CTS testing only (OpenJDK8 tests).
204ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin */
205289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkinpublic enum StreamOpFlag {
206ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
207ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /*
208ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Each characteristic takes up 2 bits in a bit set to accommodate
209ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * preserving, clearing and setting/injecting information.
210ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
211ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * This applies to stream flags, intermediate/terminal operation flags, and
212ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * combined stream and operation flags. Even though the former only requires
213ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * 1 bit of information per characteristic, is it more efficient when
214ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * combining flags to align set and inject bits.
215ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
216ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristics belong to certain types, see the Type enum. Bit masks for
217ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * the types are constructed as per the following table:
218ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
219ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                        DISTINCT  SORTED  ORDERED  SIZED  SHORT_CIRCUIT
220ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *          SPLITERATOR      01       01       01      01        00
221ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *               STREAM      01       01       01      01        00
222ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *                   OP      11       11       11      10        01
223ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *          TERMINAL_OP      00       00       10      00        01
224ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * UPSTREAM_TERMINAL_OP      00       00       10      00        00
225ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
226ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * 01 = set/inject
227ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * 10 = clear
228ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * 11 = preserve
229ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
230ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Construction of the columns is performed using a simple builder for
231ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * non-zero values.
232ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
233ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
234ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
235ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // The following flags correspond to characteristics on Spliterator
236ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // and the values MUST be equal.
237ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
238ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
239ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
240ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristic value signifying that, for each pair of
241ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * encountered elements in a stream {@code x, y}, {@code !x.equals(y)}.
242ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
243ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A stream may have this value or an intermediate operation can preserve,
244ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * clear or inject this value.
245ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
246ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 0, 0x00000001
247ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Matches Spliterator.DISTINCT
248ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    DISTINCT(0,
249ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin             set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)),
250ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
251ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
252ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristic value signifying that encounter order follows a natural
253ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * sort order of comparable elements.
254ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
255ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A stream can have this value or an intermediate operation can preserve,
256ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * clear or inject this value.
257ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
258ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Note: The {@link java.util.Spliterator#SORTED} characteristic can define
259ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * a sort order with an associated non-null comparator.  Augmenting flag
260ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * state with addition properties such that those properties can be passed
261ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * to operations requires some disruptive changes for a singular use-case.
262ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Furthermore, comparing comparators for equality beyond that of identity
263ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * is likely to be unreliable.  Therefore the {@code SORTED} characteristic
264ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * for a defined non-natural sort order is not mapped internally to the
265ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@code SORTED} flag.
266ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
267ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 1, 0x00000004
268ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Matches Spliterator.SORTED
269ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    SORTED(1,
270ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin           set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)),
271ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
272ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
273ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristic value signifying that an encounter order is
274ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * defined for stream elements.
275ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
276ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A stream can have this value, an intermediate operation can preserve,
277ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * clear or inject this value, or a terminal operation can preserve or clear
278ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * this value.
279ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
280ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 2, 0x00000010
281ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Matches Spliterator.ORDERED
282ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    ORDERED(2,
283ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP).clear(Type.TERMINAL_OP)
284ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                    .clear(Type.UPSTREAM_TERMINAL_OP)),
285ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
286ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
287ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristic value signifying that size of the stream
288ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * is of a known finite size that is equal to the known finite
289ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * size of the source spliterator input to the first stream
290ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * in the pipeline.
291ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
292ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A stream can have this value or an intermediate operation can preserve or
293ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * clear this value.
294ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
295ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 3, 0x00000040
296ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // Matches Spliterator.SIZED
297ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    SIZED(3,
298ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin          set(Type.SPLITERATOR).set(Type.STREAM).clear(Type.OP)),
299ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
300ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // The following Spliterator characteristics are not currently used but a
301ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // gap in the bit set is deliberately retained to enable corresponding
302ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // stream flags if//when required without modification to other flag values.
303ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
304ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 4, 0x00000100 NONNULL(4, ...
305ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 5, 0x00000400 IMMUTABLE(5, ...
306ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 6, 0x00001000 CONCURRENT(6, ...
307ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 7, 0x00004000 SUBSIZED(7, ...
308ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
309ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // The following 4 flags are currently undefined and a free for any further
310ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // spliterator characteristics.
311ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
312ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //  8, 0x00010000
313ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //  9, 0x00040000
314ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 10, 0x00100000
315ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 11, 0x00400000
316ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
317ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // The following flags are specific to streams and operations
318ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
319ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
320ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
321ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Characteristic value signifying that an operation may short-circuit the
322ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * stream.
323ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
324ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * An intermediate operation can preserve or inject this value,
325ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * or a terminal operation can preserve or inject this value.
326ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
327ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 12, 0x01000000
328ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    SHORT_CIRCUIT(12,
329ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                  set(Type.OP).set(Type.TERMINAL_OP));
330ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
331ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // The following 2 flags are currently undefined and a free for any further
332ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // stream flags if/when required
333ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    //
334ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 13, 0x04000000
335ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 14, 0x10000000
336ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    // 15, 0x40000000
337ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
338ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
339ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Type of a flag
340ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
341ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    enum Type {
342ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
343ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * The flag is associated with spliterator characteristics.
344ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
345ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        SPLITERATOR,
346ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
347ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
348ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * The flag is associated with stream flags.
349ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
350ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        STREAM,
351ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
352ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
353ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * The flag is associated with intermediate operation flags.
354ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
355ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        OP,
356ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
357ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
358ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * The flag is associated with terminal operation flags.
359ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
360ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        TERMINAL_OP,
361ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
362ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        /**
363ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * The flag is associated with terminal operation flags that are
364ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         * propagated upstream across the last stateful operation boundary
365ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin         */
366ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        UPSTREAM_TERMINAL_OP
367ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
368ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
369ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
370ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit pattern for setting/injecting a flag.
371ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
372ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int SET_BITS = 0b01;
373ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
374ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
375ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit pattern for clearing a flag.
376ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
377ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int CLEAR_BITS = 0b10;
378ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
379ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
380ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit pattern for preserving a flag.
381ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
382ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int PRESERVE_BITS = 0b11;
383ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
384ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static MaskBuilder set(Type t) {
385ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return new MaskBuilder(new EnumMap<>(Type.class)).set(t);
386ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
387ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
388ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static class MaskBuilder {
389ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        final Map<Type, Integer> map;
390ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
391ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        MaskBuilder(Map<Type, Integer> map) {
392ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            this.map = map;
393ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
394ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
395ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        MaskBuilder mask(Type t, Integer i) {
396ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            map.put(t, i);
397ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return this;
398ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
399ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
400ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        MaskBuilder set(Type t) {
401ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return mask(t, SET_BITS);
402ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
403ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
404ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        MaskBuilder clear(Type t) {
405ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return mask(t, CLEAR_BITS);
406ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
407ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
408ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        MaskBuilder setAndClear(Type t) {
409ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return mask(t, PRESERVE_BITS);
410ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
411ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
412ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        Map<Type, Integer> build() {
413ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            for (Type t : Type.values()) {
414ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin                map.putIfAbsent(t, 0b00);
415ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            }
416ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return map;
417ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
418ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
419ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
420ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
421ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The mask table for a flag, this is used to determine if a flag
422ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * corresponds to a certain flag type and for creating mask constants.
423ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
424ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private final Map<Type, Integer> maskTable;
425ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
426ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
427ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit position in the bit mask.
428ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
429ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private final int bitPosition;
430ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
431ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
432ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The set 2 bit set offset at the bit position.
433ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
434ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private final int set;
435ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
436ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
437ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The clear 2 bit set offset at the bit position.
438ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
439ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private final int clear;
440ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
441ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
442ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The preserve 2 bit set offset at the bit position.
443ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
444ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private final int preserve;
445ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
446ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private StreamOpFlag(int position, MaskBuilder maskBuilder) {
447ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        this.maskTable = maskBuilder.build();
448ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Two bits per flag
449ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        position *= 2;
450ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        this.bitPosition = position;
451ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        this.set = SET_BITS << position;
452ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        this.clear = CLEAR_BITS << position;
453ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        this.preserve = PRESERVE_BITS << position;
454ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
455ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
456ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
457ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Gets the bitmap associated with setting this characteristic.
458ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
459ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the bitmap for setting this characteristic
460ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
461289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public int set() {
462ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return set;
463ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
464ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
465ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
466ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Gets the bitmap associated with clearing this characteristic.
467ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
468ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the bitmap for clearing this characteristic
469ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
470289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public int clear() {
471ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return clear;
472ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
473ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
474ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
475ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Determines if this flag is a stream-based flag.
476ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
477ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return true if a stream-based flag, otherwise false.
478ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
479289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public boolean isStreamFlag() {
480ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return maskTable.get(Type.STREAM) > 0;
481ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
482ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
483ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
484ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Checks if this flag is set on stream flags, injected on operation flags,
485ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and injected on combined stream and operation flags.
486ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
487ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flags the stream flags, operation flags, or combined stream and
488ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *        operation flags
489ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return true if this flag is known, otherwise false.
490ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
491289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public boolean isKnown(int flags) {
492ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (flags & preserve) == set;
493ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
494ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
495ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
496ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Checks if this flag is cleared on operation flags or combined stream and
497ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * operation flags.
498ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
499ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flags the operation flags or combined stream and operations flags.
500ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return true if this flag is preserved, otherwise false.
501ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
502289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public boolean isCleared(int flags) {
503ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (flags & preserve) == clear;
504ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
505ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
506ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
507ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Checks if this flag is preserved on combined stream and operation flags.
508ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
509ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param flags the combined stream and operations flags.
510ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return true if this flag is preserved, otherwise false.
511ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
512289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public boolean isPreserved(int flags) {
513ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (flags & preserve) == preserve;
514ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
515ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
516ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
517ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Determines if this flag can be set for a flag type.
518ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
519ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param t the flag type.
520ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return true if this flag can be set for the flag type, otherwise false.
521ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
522289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public boolean canSet(Type t) {
523ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (maskTable.get(t) & SET_BITS) > 0;
524ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
525ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
526ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
527ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit mask for spliterator characteristics
528ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
529289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int SPLITERATOR_CHARACTERISTICS_MASK = createMask(Type.SPLITERATOR);
530ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
531ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
532ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit mask for source stream flags.
533ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
534289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int STREAM_MASK = createMask(Type.STREAM);
535ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
536ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
537ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit mask for intermediate operation flags.
538ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
539289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int OP_MASK = createMask(Type.OP);
540ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
541ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
542ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit mask for terminal operation flags.
543ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
544289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int TERMINAL_OP_MASK = createMask(Type.TERMINAL_OP);
545ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
546ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
547ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit mask for upstream terminal operation flags.
548ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
549289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int UPSTREAM_TERMINAL_OP_MASK = createMask(Type.UPSTREAM_TERMINAL_OP);
550ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
551ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static int createMask(Type t) {
552ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int mask = 0;
553ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        for (StreamOpFlag flag : StreamOpFlag.values()) {
554ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            mask |= flag.maskTable.get(t) << flag.bitPosition;
555ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
556ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return mask;
557ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
558ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
559ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
560ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Complete flag mask.
561ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
562ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int FLAG_MASK = createFlagMask();
563ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
564ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static int createFlagMask() {
565ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int mask = 0;
566ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        for (StreamOpFlag flag : StreamOpFlag.values()) {
567ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            mask |= flag.preserve;
568ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
569ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return mask;
570ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
571ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
572ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
573ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flag mask for stream flags that are set.
574ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
575ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int FLAG_MASK_IS = STREAM_MASK;
576ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
577ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
578ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Flag mask for stream flags that are cleared.
579ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
580ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static final int FLAG_MASK_NOT = STREAM_MASK << 1;
581ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
582ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
583ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The initial value to be combined with the stream flags of the first
584ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * stream in the pipeline.
585ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
586289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int INITIAL_OPS_VALUE = FLAG_MASK_IS | FLAG_MASK_NOT;
587ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
588ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
589ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to set or inject {@link #DISTINCT}.
590ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
591289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int IS_DISTINCT = DISTINCT.set;
592ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
593ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
594ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to clear {@link #DISTINCT}.
595ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
596289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int NOT_DISTINCT = DISTINCT.clear;
597ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
598ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
599ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to set or inject {@link #SORTED}.
600ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
601289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int IS_SORTED = SORTED.set;
602ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
603ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
604ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to clear {@link #SORTED}.
605ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
606289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int NOT_SORTED = SORTED.clear;
607ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
608ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
609ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to set or inject {@link #ORDERED}.
610ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
611289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int IS_ORDERED = ORDERED.set;
612ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
613ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
614ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to clear {@link #ORDERED}.
615ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
616289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int NOT_ORDERED = ORDERED.clear;
617ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
618ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
619ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to set {@link #SIZED}.
620ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
621289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int IS_SIZED = SIZED.set;
622ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
623ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
624ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to clear {@link #SIZED}.
625ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
626289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int NOT_SIZED = SIZED.clear;
627ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
628ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
629ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * The bit value to inject {@link #SHORT_CIRCUIT}.
630ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
631289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static final int IS_SHORT_CIRCUIT = SHORT_CIRCUIT.set;
632ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
633ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    private static int getMask(int flags) {
634ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (flags == 0)
635ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               ? FLAG_MASK
636ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin               : ~(flags | ((FLAG_MASK_IS & flags) << 1) | ((FLAG_MASK_NOT & flags) >> 1));
637ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
638ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
639ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
640ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Combines stream or operation flags with previously combined stream and
641ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * operation flags to produce updated combined stream and operation flags.
642ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
643ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag set on stream flags or injected on operation flags,
644ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and injected combined stream and operation flags,
645ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be injected on the updated combined stream and operation flags.
646ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
647ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
648ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag set on stream flags or injected on operation flags,
649ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and cleared on the combined stream and operation flags,
650ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be cleared on the updated combined stream and operation flags.
651ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
652ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
653ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag set on the stream flags or injected on operation flags,
654ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and preserved on the combined stream and operation flags,
655ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be injected on the updated combined stream and operation flags.
656ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
657ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
658ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag not set on the stream flags or cleared/preserved on operation
659ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * flags, and injected on the combined stream and operation flags,
660ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be injected on the updated combined stream and operation flags.
661ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
662ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
663ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag not set on the stream flags or cleared/preserved on operation
664ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * flags, and cleared on the combined stream and operation flags,
665ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be cleared on the updated combined stream and operation flags.
666ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
667ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
668ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag not set on the stream flags,
669ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and preserved on the combined stream and operation flags
670ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be preserved on the updated combined stream and operation flags.
671ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
672ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
673ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag cleared on operation flags,
674ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and preserved on the combined stream and operation flags
675ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be cleared on the updated combined stream and operation flags.
676ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
677ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>
678ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * A flag preserved on operation flags,
679ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * and preserved on the combined stream and operation flags
680ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * will be preserved on the updated combined stream and operation flags.
681ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
682ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param newStreamOrOpFlags the stream or operation flags.
683ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param prevCombOpFlags previously combined stream and operation flags.
684ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *        The value {#link INITIAL_OPS_VALUE} must be used as the seed value.
685ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the updated combined stream and operation flags.
686ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
687289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static int combineOpFlags(int newStreamOrOpFlags, int prevCombOpFlags) {
688ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // 0x01 or 0x10 nibbles are transformed to 0x11
689ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // 0x00 nibbles remain unchanged
690ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Then all the bits are flipped
691ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Then the result is logically or'ed with the operation flags.
692ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return (prevCombOpFlags & StreamOpFlag.getMask(newStreamOrOpFlags)) | newStreamOrOpFlags;
693ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
694ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
695ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
696ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Converts combined stream and operation flags to stream flags.
697ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
698ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * <p>Each flag injected on the combined stream and operation flags will be
699ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * set on the stream flags.
700ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
701ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param combOpFlags the combined stream and operation flags.
702ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the stream flags.
703ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
704289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static int toStreamFlags(int combOpFlags) {
705ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // By flipping the nibbles 0x11 become 0x00 and 0x01 become 0x10
706ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        // Shift left 1 to restore set flags and mask off anything other than the set flags
707ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return ((~combOpFlags) >> 1) & FLAG_MASK_IS & combOpFlags;
708ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
709ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
710ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
711ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Converts stream flags to a spliterator characteristic bit set.
712ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
713ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param streamFlags the stream flags.
714ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the spliterator characteristic bit set.
715ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
716289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static int toCharacteristics(int streamFlags) {
717ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return streamFlags & SPLITERATOR_CHARACTERISTICS_MASK;
718ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
719ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
720ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
721ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Converts a spliterator characteristic bit set to stream flags.
722ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
723ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @implSpec
724ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * If the spliterator is naturally {@code SORTED} (the associated
725ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * {@code Comparator} is {@code null}) then the characteristic is converted
726ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * to the {@link #SORTED} flag, otherwise the characteristic is not
727ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * converted.
728ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
729ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param spliterator the spliterator from which to obtain characteristic
730ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *        bit set.
731ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the stream flags.
732ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
733289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static int fromCharacteristics(Spliterator<?> spliterator) {
734ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        int characteristics = spliterator.characteristics();
735ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) {
736ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // Do not propagate the SORTED characteristic if it does not correspond
737ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            // to a natural sort order
738ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED;
739ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
740ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        else {
741ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin            return characteristics & SPLITERATOR_CHARACTERISTICS_MASK;
742ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        }
743ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
744ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin
745ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    /**
746ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * Converts a spliterator characteristic bit set to stream flags.
747ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     *
748ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @param characteristics the spliterator characteristic bit set.
749ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     * @return the stream flags.
750ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin     */
751289e51c2258b001f2aa6d6e67b21be7bb65d5102Igor Murashkin    public static int fromCharacteristics(int characteristics) {
752ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin        return characteristics & SPLITERATOR_CHARACTERISTICS_MASK;
753ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin    }
754ff18b5f136f92154f2e05217e3953d10f459e561Igor Murashkin}
755