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