From d75fe46b8f1b0d5c27887052ee4714d6a9c7ea4b Mon Sep 17 00:00:00 2001 From: Sebb Date: Fri, 11 Dec 2015 13:41:22 +0000 Subject: [PATCH] LANG-1193 ordinalIndexOf("abc", "ab", 1) gives incorrect answer of -1 (correct answer should be 0) Revert LANG-1077 --- src/changes/changes.xml | 2 +- .../org/apache/commons/lang3/StringUtils.java | 15 ++++++++++++--- .../lang3/StringUtilsEqualsIndexOfTest.java | 17 +++++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ca3408c91..7c197c4a6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + ordinalIndexOf("abc", "ab", 1) gives incorrect answer of -1 (correct answer should be 0); revert fix for LANG-1077 Clarify JavaDoc of StringUtils.containsAny() Add StringUtils methods to compare a string to multiple strings Add remove by regular expression methods in StringUtils @@ -104,7 +105,6 @@ Fix wrong examples in JavaDoc of StringUtils.replaceEachRepeatedly(...), StringUtils.replaceEach(...) Add StringUtils.containsAny(CharSequence, CharSequence...) method Read wrong component type of array in add in ArrayUtils - StringUtils.ordinalIndexOf("aaaaaa", "aa", 2) != 3 in StringUtils Duplicated "0x" check in createBigInteger in NumberUtils StringUtils.abbreviate description doesn't agree with the examples Multiline recursive to string style diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java index 1b58b9599..c7583c96a 100644 --- a/src/main/java/org/apache/commons/lang3/StringUtils.java +++ b/src/main/java/org/apache/commons/lang3/StringUtils.java @@ -1222,6 +1222,13 @@ public static int indexOf(final CharSequence seq, final CharSequence searchSeq, * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 * * + *

Matches may overlap:

+ *
+     * StringUtils.ordinalIndexOf("ababab","aba", 1)          = 0
+     * StringUtils.ordinalIndexOf("ababab","aba", 2)          = 2
+     * StringUtils.ordinalIndexOf("ababab","aba", 3)          = -1
+     * 
+ * *

Note that 'head(CharSequence str, int n)' may be implemented as:

* *
@@ -1248,7 +1255,7 @@ public static int ordinalIndexOf(final CharSequence str, final CharSequence sear
      *
      * @param str  the CharSequence to check, may be null
      * @param searchStr  the CharSequence to find, may be null
-     * @param ordinal  the n-th {@code searchStr} to find
+     * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
      * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
      * @return the n-th index of the search CharSequence,
      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
@@ -1262,12 +1269,14 @@ private static int ordinalIndexOf(final CharSequence str, final CharSequence sea
             return lastIndex ? str.length() : 0;
         }
         int found = 0;
+        // set the initial index beyond the end of the string
+        // this is to allow for the initial index decrement/increment
         int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
         do {
             if (lastIndex) {
-                index = CharSequenceUtils.lastIndexOf(str, searchStr, index - searchStr.length());
+                index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string
             } else {
-                index = CharSequenceUtils.indexOf(str, searchStr, index + searchStr.length());
+                index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
             }
             if (index < 0) {
                 return index;
diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
index 8750de3f1..f509290c2 100644
--- a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
@@ -1148,8 +1148,21 @@ public void testOrdinalIndexOf() {
         assertEquals(8, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 9));
         assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 10));
 
-        assertEquals(3, StringUtils.ordinalIndexOf("aaaaaa", "aa", 2));
-        assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaa", "aa", 3));
+        assertEquals(0, StringUtils.ordinalIndexOf("aaaaaa", "aa", 1));
+        assertEquals(1, StringUtils.ordinalIndexOf("aaaaaa", "aa", 2));
+        assertEquals(2, StringUtils.ordinalIndexOf("aaaaaa", "aa", 3));
+        assertEquals(3, StringUtils.ordinalIndexOf("aaaaaa", "aa", 4));
+        assertEquals(4, StringUtils.ordinalIndexOf("aaaaaa", "aa", 5));
+        assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaa", "aa", 6));
+
+        assertEquals(0, StringUtils.ordinalIndexOf("ababab", "aba", 1));
+        assertEquals(2, StringUtils.ordinalIndexOf("ababab", "aba", 2));
+        assertEquals(-1, StringUtils.ordinalIndexOf("ababab", "aba", 3));
+    }
+    
+    @Test
+    public void testLANG1193() {
+        assertEquals(0, StringUtils.ordinalIndexOf("abc", "ab", 1));        
     }
 
 }