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-codec.git

commit 72e2540a4b302fa0434e605b75d5a764fc226fba
Author: Gary Gregory <[email protected]>
AuthorDate: Thu Aug 6 07:40:05 2026 -0400

    Optimize honeticEngine.encode(String, LanguageSet) for speed.
---
 src/changes/changes.xml                            |  1 +
 .../commons/codec/language/bm/PhoneticEngine.java  | 25 ++++++++++++++++++++--
 .../codec/language/bm/BeiderMorseEncoderTest.java  |  6 ++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 9b38caeb..ba60f6cd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -45,6 +45,7 @@ The <action> type attribute can be add,update,fix,remove.
   <body>
     <release version="1.22.2" date="YYYY-MM-DD" description="This is a feature 
and maintenance release. Java 8 or later is required.">
       <!-- FIX -->
+      <action type="fix" dev="ggregory" due-to="Yu Bao, Gary Gregory">Optimize 
honeticEngine.encode(String, LanguageSet) for speed.</action>
       <!-- ADD -->
       <!-- UPDATE -->
     </release>
diff --git 
a/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java 
b/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
index a08d7067..5a13a7d5 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
@@ -387,8 +387,13 @@ public class PhoneticEngine {
         input = input.toLowerCase(Locale.ENGLISH).replace('-', ' ').trim();
 
         if (this.nameType == NameType.GENERIC) {
-            if (input.startsWith("d'")) { // check for d'
-                final String remainder = input.substring(2);
+            final String dQuotePrefix = "d'";
+            final int dqpLen = dQuotePrefix.length();
+            if (input.startsWith(dQuotePrefix)) { // check for d'
+                String remainder = input.substring(dqpLen);
+                // Find remainder without allocating new string.
+                final int start = lastRepeat(remainder, dQuotePrefix, dqpLen);
+                remainder = remainder.substring(start);
                 final String combined = "d" + remainder;
                 return "(" + encode(remainder) + ")-(" + encode(combined) + 
")";
             }
@@ -503,4 +508,20 @@ public class PhoneticEngine {
     public boolean isConcat() {
         return this.concat;
     }
+
+    private int lastRepeat(final String source, final String prefix, final int 
prefixLen) {
+        // Find without allocating new string.
+        int start = 0;
+        while (start + prefixLen <= source.length()) {
+            int i = 0;
+            while (i < prefixLen && source.charAt(start + i) == 
prefix.charAt(i)) {
+                i++;
+            }
+            if (i != prefixLen) {
+                break;
+            }
+            start += prefixLen;
+        }
+        return start;
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/codec/language/bm/BeiderMorseEncoderTest.java
 
b/src/test/java/org/apache/commons/codec/language/bm/BeiderMorseEncoderTest.java
index 0dd274b4..56cfe3cf 100644
--- 
a/src/test/java/org/apache/commons/codec/language/bm/BeiderMorseEncoderTest.java
+++ 
b/src/test/java/org/apache/commons/codec/language/bm/BeiderMorseEncoderTest.java
@@ -30,6 +30,7 @@ import java.util.regex.Pattern;
 import org.apache.commons.codec.AbstractStringEncoderTest;
 import org.apache.commons.codec.EncoderException;
 import org.apache.commons.codec.StringEncoder;
+import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -93,6 +94,11 @@ class BeiderMorseEncoderTest extends 
AbstractStringEncoderTest<StringEncoder> {
         }
     }
 
+    @Test
+    void testDQuoteRepeat() throws Exception {
+        assertEquals("(D|a|i|o)-(dD|da|di|do)", new 
BeiderMorseEncoder().encode(StringUtils.repeat("d'", 20000) + "aaa"));
+    }
+
     @Test
     void testEncodeAtzNotEmpty() throws EncoderException {
         final BeiderMorseEncoder bmpm = createGenericApproxEncoder();

Reply via email to