/** * Returns a stream of code point values (as {@code Integer} objects) from this sequence. Any * surrogate pairs encountered in the sequence are combined as if by {@linkplain * Character#toCodePoint Character.toCodePoint} and the result is passed to the stream. Any other * code units, including ordinary BMP characters, unpaired surrogates, and undefined code units, * are zero-extended to @{code int} values which are then passed to the stream. * * <p>If the sequence is mutated while the stream is being read, the result is undefined. * * @return an Iterable of Unicode code points from this sequence */ public default IntStream codePoints() { class CodePointIterator implements IntStream.IntIterator { int cur = 0; @Override public void forEachInt(IntConsumer block) { while (cur < length()) { int cp = Character.codePointAt(CharSequence.this, cur); cur += Character.charCount(cp); block.accept(cp); } } public boolean hasNext() { return cur < length(); } public int nextInt() { if (!hasNext()) throw new NoSuchElementException(); // TODO: It probably would be faster if the logic from // the following two methods were inlined and simplified. int cp = Character.codePointAt(CharSequence.this, cur); cur += Character.charCount(cp); return cp; } } return Streams.intStream( () -> Streams.intSpliteratorUnknownSize(new CodePointIterator(), Spliterator.ORDERED), Spliterator.UNIFORM | Spliterator.SIZED | Spliterator.ORDERED); }