Moving indexOf(String, int) and indexOf(String, int, int) over to CharSequence. LANG-687. This, plus the same happening for the String, String, int variant will open up a lot of methods. 

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1082062 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java
index 2b2ce45..81f5a33 100644
--- a/src/main/java/org/apache/commons/lang3/StringUtils.java
+++ b/src/main/java/org/apache/commons/lang3/StringUtils.java
@@ -800,10 +800,10 @@
     // IndexOf
     //-----------------------------------------------------------------------
     /**
-     * <p>Finds the first index within a String, handling {@code null}.
-     * This method uses {@link String#indexOf(int)}.</p>
+     * <p>Finds the first index within a CharSequence, handling {@code null}.
+     * This method uses {@link String#indexOf(int, int)} if possible.</p>
      *
-     * <p>A {@code null} or empty ("") String will return {@code INDEX_NOT_FOUND (-1)}.</p>
+     * <p>A {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}.</p>
      *
      * <pre>
      * StringUtils.indexOf(null, *)         = -1
@@ -812,25 +812,25 @@
      * StringUtils.indexOf("aabaabaa", 'b') = 2
      * </pre>
      *
-     * @param str  the String to check, may be null
+     * @param seq  the CharSequence to check, may be null
      * @param searchChar  the character to find
      * @return the first index of the search character,
      *  -1 if no match or {@code null} string input
      * @since 2.0
      */
-    public static int indexOf(String str, int searchChar) {
-        if (isEmpty(str)) {
+    public static int indexOf(CharSequence seq, int searchChar) {
+        if (isEmpty(seq)) {
             return INDEX_NOT_FOUND;
         }
-        return str.indexOf(searchChar);
+        return StringUtils.indexOfSequence(seq, searchChar, 0);
     }
 
     /**
-     * <p>Finds the first index within a String from a start position,
+     * <p>Finds the first index within a CharSequence from a start position,
      * handling {@code null}.
-     * This method uses {@link String#indexOf(int, int)}.</p>
+     * This method uses {@link String#indexOf(int, int)} if possible.</p>
      *
-     * <p>A {@code null} or empty ("") String will return {@code (INDEX_NOT_FOUND) -1}.
+     * <p>A {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}.
      * A negative start position is treated as zero.
      * A start position greater than the string length returns {@code -1}.</p>
      *
@@ -843,18 +843,18 @@
      * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
      * </pre>
      *
-     * @param str  the String to check, may be null
+     * @param seq  the CharSequence to check, may be null
      * @param searchChar  the character to find
      * @param startPos  the start position, negative treated as zero
      * @return the first index of the search character,
      *  -1 if no match or {@code null} string input
      * @since 2.0
      */
-    public static int indexOf(String str, int searchChar, int startPos) {
-        if (isEmpty(str)) {
+    public static int indexOf(CharSequence seq, int searchChar, int startPos) {
+        if (isEmpty(seq)) {
             return INDEX_NOT_FOUND;
         }
-        return str.indexOf(searchChar, startPos);
+        return StringUtils.indexOfSequence(seq, searchChar, startPos);
     }
 
     /**
@@ -6416,4 +6416,34 @@
         return cs == null ? null : cs.subSequence(start, cs.length());
     }
 
+    // Used by the indexOf(CharSequence methods) as a green implementation of indexOf
+    static int indexOfSequence(CharSequence cs, int searchChar, int start) {
+        if (cs instanceof String) {
+            return ((String) cs).indexOf(searchChar, start);
+        } else {
+            int sz = cs.length();
+            if ( start < 0 ) {
+                start = 0;
+            }
+            for ( int i=start; i < sz; i++ ) {
+                if ( cs.charAt(i) == searchChar) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    }
+    // Used by the indexOf(CharSequence methods) as a green implementation of indexOf
+    static int indexOfSequence(CharSequence cs, CharSequence searchChar, int start) {
+        if (cs instanceof String && searchChar instanceof String) {
+            // TODO: Do we assume searchChar is usually relatively small; 
+            //       If so then calling toString() on it is better than reverting to 
+            //       the green implementation in the else block
+            return ((String) cs).indexOf( (String) searchChar, start);
+        } else {
+            // TODO: Implement rather than convert to String
+            return cs.toString().indexOf(searchChar.toString(), start);
+        }
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
index 1296d50..39a5cd1 100644
--- a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
@@ -467,6 +467,8 @@
         assertEquals(-1, StringUtils.indexOf("", ' '));
         assertEquals(0, StringUtils.indexOf("aabaabaa", 'a'));
         assertEquals(2, StringUtils.indexOf("aabaabaa", 'b'));
+
+        assertEquals(2, StringUtils.indexOf(new StringBuilder("aabaabaa"), 'b'));
     }
 
     public void testIndexOf_charInt() {
@@ -479,6 +481,8 @@
         assertEquals(5, StringUtils.indexOf("aabaabaa", 'b', 3));
         assertEquals(-1, StringUtils.indexOf("aabaabaa", 'b', 9));
         assertEquals(2, StringUtils.indexOf("aabaabaa", 'b', -1));
+
+        assertEquals(5, StringUtils.indexOf(new StringBuilder("aabaabaa"), 'b', 3));
     }
 
     public void testIndexOf_String() {