diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SheetDataWriter.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SheetDataWriter.java index f72b6a2ff3..973a93762e 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SheetDataWriter.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SheetDataWriter.java @@ -39,7 +39,7 @@ import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.util.CellReference; -import org.apache.poi.util.StringCodepointsIterable; +import org.apache.poi.util.CodepointsUtil; import org.apache.poi.util.TempFile; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.usermodel.XSSFRichTextString; @@ -393,7 +393,8 @@ public class SheetDataWriter implements Closeable { return; } - for (String codepoint : new StringCodepointsIterable(s)) { + for (Iterator iter = CodepointsUtil.iteratorFor(s); iter.hasNext(); ) { + String codepoint = iter.next(); switch (codepoint) { case "<": _out.write("<"); diff --git a/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java b/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java index 9a476d503d..abb9978242 100644 --- a/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java +++ b/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java @@ -17,9 +17,8 @@ package org.apache.poi.ss.format; import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.util.CodepointsUtil; import org.apache.poi.util.LocaleUtil; -import org.apache.poi.util.StringCodepointsIterable; -import org.apache.poi.util.StringUtil; import javax.swing.*; @@ -335,7 +334,7 @@ public class CellFormatPart { boolean seenZero = false; while (m.find()) { String repl = m.group(0); - Iterator codePoints = new StringCodepointsIterable(repl).iterator(); + Iterator codePoints = CodepointsUtil.iteratorFor(repl); if (codePoints.hasNext()) { String c1 = codePoints.next(); String c2 = null; @@ -403,7 +402,8 @@ public class CellFormatPart { */ static String quoteSpecial(String repl, CellFormatType type) { StringBuilder sb = new StringBuilder(); - Iterator codePoints = new StringCodepointsIterable(repl).iterator(); + Iterator codePoints = CodepointsUtil.iteratorFor(repl); + while (codePoints.hasNext()) { String ch = codePoints.next(); if ("\'".equals(ch) && type.isSpecial('\'')) { @@ -567,7 +567,7 @@ public class CellFormatPart { */ static String expandChar(String part) { List codePoints = new ArrayList<>(); - new StringCodepointsIterable(part).iterator().forEachRemaining(codePoints::add); + CodepointsUtil.iteratorFor(part).forEachRemaining(codePoints::add); if (codePoints.size() < 2) throw new IllegalArgumentException("Expected part string to have at least 2 chars"); String ch = codePoints.get(1); return ch + ch + ch; diff --git a/poi/src/main/java/org/apache/poi/util/CodepointsUtil.java b/poi/src/main/java/org/apache/poi/util/CodepointsUtil.java new file mode 100644 index 0000000000..107e37416e --- /dev/null +++ b/poi/src/main/java/org/apache/poi/util/CodepointsUtil.java @@ -0,0 +1,29 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.util; + +import java.util.Iterator; + +@Internal +public class CodepointsUtil { + public static Iterator iteratorFor(String text) { + return text.codePoints() + .mapToObj(codePoint -> new StringBuilder().appendCodePoint(codePoint).toString()) + .iterator(); + } +} \ No newline at end of file diff --git a/poi/src/main/java/org/apache/poi/util/StringCodepointsIterable.java b/poi/src/main/java/org/apache/poi/util/StringCodepointsIterable.java deleted file mode 100644 index 5fb83935bb..0000000000 --- a/poi/src/main/java/org/apache/poi/util/StringCodepointsIterable.java +++ /dev/null @@ -1,60 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.util; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -// based on https://gist.github.com/EmmanuelOga/48df70b27ead4d80234b -@Internal -public class StringCodepointsIterable implements Iterable { - private class StringCodepointsIterator implements Iterator { - private int index = 0; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasNext() { - return index < StringCodepointsIterable.this.string.length(); - } - - @Override - public String next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - int codePoint = StringCodepointsIterable.this.string.codePointAt(index); - index += Character.charCount(codePoint); - return new String(Character.toChars(codePoint)); - } - } - - private final String string; - - public StringCodepointsIterable(final String string) { - this.string = string; - } - - @Override - public Iterator iterator() { - return new StringCodepointsIterator(); - } -} \ No newline at end of file diff --git a/poi/src/test/java/org/apache/poi/util/TestStringCodepointsIterable.java b/poi/src/test/java/org/apache/poi/util/TestCodepointsUtil.java similarity index 73% rename from poi/src/test/java/org/apache/poi/util/TestStringCodepointsIterable.java rename to poi/src/test/java/org/apache/poi/util/TestCodepointsUtil.java index 4630a3cd0d..35a05af33e 100644 --- a/poi/src/test/java/org/apache/poi/util/TestStringCodepointsIterable.java +++ b/poi/src/test/java/org/apache/poi/util/TestCodepointsUtil.java @@ -18,28 +18,30 @@ package org.apache.poi.util; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.junit.jupiter.api.Test; /** - * Unit test for StringCodepointsIterable + * Unit test for CodepointsUtil */ -class TestStringCodepointsIterable { +class TestCodepointsUtil { @Test - void testIterable() { + void testIterator() { final String unicodeSurrogates = "\uD835\uDF4A\uD835\uDF4B\uD835\uDF4C\uD835\uDF4D\uD835\uDF4E" + "abcdef123456"; - StringCodepointsIterable sci = new StringCodepointsIterable(unicodeSurrogates); + Iterator sci = CodepointsUtil.iteratorFor(unicodeSurrogates); List codePoints = new ArrayList<>(); - List codePoints2 = new ArrayList<>(); - sci.iterator().forEachRemaining(codePoints::add); - sci.iterator().forEachRemaining(codePoints2::add); + CodepointsUtil.iteratorFor(unicodeSurrogates).forEachRemaining(codePoints::add); assertEquals(17, codePoints.size()); - assertEquals(codePoints, codePoints2); + for(String point : codePoints){ + assertTrue(point.length() >=1 && point.length() <= 2, "codepoint " + point + "is wrong size"); + } } }