diff --git a/src/main/java/org/apache/commons/lang3/text/WordUtils.java b/src/main/java/org/apache/commons/lang3/text/WordUtils.java index feed32d1579..e7c4907c56f 100644 --- a/src/main/java/org/apache/commons/lang3/text/WordUtils.java +++ b/src/main/java/org/apache/commons/lang3/text/WordUtils.java @@ -265,7 +265,7 @@ public static String initials(final String str, final char... delimiters) { return StringUtils.EMPTY; } final int strLen = str.length(); - final char[] buf = new char[strLen / 2 + 1]; + final char[] buf = new char[strLen]; int count = 0; boolean lastWasGap = true; for (int i = 0; i < strLen; i++) { @@ -276,6 +276,10 @@ public static String initials(final String str, final char... delimiters) { } if (lastWasGap) { buf[count++] = ch; + // keep a supplementary code point's low surrogate with its high half + if (Character.isHighSurrogate(ch) && i + 1 < strLen && Character.isLowSurrogate(str.charAt(i + 1))) { + buf[count++] = str.charAt(++i); + } lastWasGap = false; } } diff --git a/src/test/java/org/apache/commons/lang3/text/WordUtilsTest.java b/src/test/java/org/apache/commons/lang3/text/WordUtilsTest.java index 479b626402a..305f01c2cba 100644 --- a/src/test/java/org/apache/commons/lang3/text/WordUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/text/WordUtilsTest.java @@ -185,6 +185,14 @@ void testInitials_String() { assertEquals("iah1", WordUtils.initials("i am here 123")); } + @Test + void testInitials_SupplementaryCodePoint() { + final String emoji = new String(Character.toChars(0x1F600)); + assertEquals("B" + emoji + "L", WordUtils.initials("Ben " + emoji + "mile Lee")); + assertEquals(emoji, WordUtils.initials(emoji + "abc")); + assertEquals("B" + emoji + "L", WordUtils.initials("Ben." + emoji + "mile.Lee", '.')); + } + @Test void testInitials_String_charArray() { char[] array = null;