This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new bd7ffdf5b Add StringUtils.trimControl(String) (#1681)
bd7ffdf5b is described below

commit bd7ffdf5b27004908f10345f3048d4790291fbe0
Author: Gary Gregory <[email protected]>
AuthorDate: Fri May 29 06:13:12 2026 -0400

    Add StringUtils.trimControl(String) (#1681)
---
 .../java/org/apache/commons/lang3/StringUtils.java | 37 +++++++++++++++++++++-
 .../apache/commons/lang3/StringUtilsTrimTest.java  | 26 +++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java 
b/src/main/java/org/apache/commons/lang3/StringUtils.java
index 99ef00ff9..74287ab0c 100644
--- a/src/main/java/org/apache/commons/lang3/StringUtils.java
+++ b/src/main/java/org/apache/commons/lang3/StringUtils.java
@@ -8752,7 +8752,7 @@ public static String toString(final byte[] bytes, final 
String charsetName) {
     }
 
     /**
-     * Removes control characters (char &lt;= 32) from both ends of this 
String, handling {@code null} by returning {@code null}.
+     * Removes control characters plus space (char &lt;= 32) from both ends of 
this String, handling {@code null} by returning {@code null}.
      *
      * <p>
      * The String is trimmed using {@link String#trim()}. Trim removes start 
and end characters &lt;= 32. To strip whitespace use {@link #strip(String)}.
@@ -8777,6 +8777,41 @@ public static String trim(final String str) {
         return str == null ? null : str.trim();
     }
 
+    /**
+     * Removes control characters (char &lt;= 31) from both ends of this 
String, handling {@code null} by returning {@code null}.
+     *
+     * <p>
+     * To trim your choice of characters, use the {@link #strip(String, 
String)} methods.
+     * </p>
+     *
+     * <pre>{@code
+     * StringUtils.trim(null)          = null
+     * StringUtils.trim("")            = ""
+     * StringUtils.trim("abc\u0000")   = "abc"
+     * StringUtils.trim("abc")         = "abc"
+     * StringUtils.trim(" abc ")       = " abc "
+     * }</pre>
+     *
+     * @param str the String to be trimmed, may be null.
+     * @return the trimmed string, {@code null} if null String input.
+     * @since 3.21.0
+     */
+    public static String trimControl(final String str) {
+        if (str == null) {
+            return null;
+        }
+        int len = str.length();
+        int st = 0;
+
+        while (st < len && str.charAt(st) < ' ') {
+            st++;
+        }
+        while (st < len && str.charAt(len - 1) < ' ') {
+            len--;
+        }
+        return st > 0 || len < str.length() ? str.substring(st, len) : str;
+    }
+
     /**
      * Removes control characters (char &lt;= 32) from both ends of this 
String returning an empty String ("") if the String is empty ("") after the 
trim or if
      * it is {@code null}.
diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsTrimTest.java 
b/src/test/java/org/apache/commons/lang3/StringUtilsTrimTest.java
index 99d6d84ef..4e2380665 100644
--- a/src/test/java/org/apache/commons/lang3/StringUtilsTrimTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringUtilsTrimTest.java
@@ -42,6 +42,32 @@ void testTrim() {
         assertNull(StringUtils.trim(null));
     }
 
+    @Test
+    void testTrimControl() {
+        // null input returns null
+        assertNull(StringUtils.trimControl(null));
+        // empty string stays empty
+        assertEquals("", StringUtils.trimControl(""));
+        // no control chars: unchanged
+        assertEquals(FOO, StringUtils.trimControl(FOO));
+        // spaces are NOT stripped (space is char 32, not a control char)
+        assertEquals(" " + FOO + " ", StringUtils.trimControl(" " + FOO + " 
"));
+        // trailing NUL (\u0000) is stripped
+        assertEquals(FOO, StringUtils.trimControl(FOO + "\u0000"));
+        // leading NUL (\u0000) is stripped
+        assertEquals(FOO, StringUtils.trimControl("\u0000" + FOO));
+        // control chars on both ends are stripped
+        assertEquals(FOO, StringUtils.trimControl("\t\r\n" + FOO + "\t\r\n"));
+        // only control chars becomes empty string
+        assertEquals("", StringUtils.trimControl("\u0001\u0002\u001F"));
+        // embedded control chars are NOT stripped
+        assertEquals("a\u0001b", StringUtils.trimControl("a\u0001b"));
+        // space in the middle preserved, control chars on ends stripped
+        assertEquals(" " + FOO + " ", StringUtils.trimControl("\u0001 " + FOO 
+ " \u0001"));
+        // char 31 (unit separator) is stripped; char 32 (space) is not
+        assertEquals(" abc ", StringUtils.trimControl("\u001F abc \u001F"));
+    }
+
     @Test
     void testTrimToEmpty() {
         assertEquals(FOO, StringUtils.trimToEmpty(FOO + "  "));

Reply via email to