You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2018/12/27 06:56:45 UTC

[groovy] branch master updated: GROOVY-8939: Add methods in StringGroovyMethods for better API Usage (closes #846)

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

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c5ad7b  GROOVY-8939: Add methods in StringGroovyMethods for better API Usage (closes #846)
8c5ad7b is described below

commit 8c5ad7b0ddc5704d514cbaf135bceaaf401d2324
Author: Adithyan K <ad...@gmail.com>
AuthorDate: Wed Dec 26 07:24:30 2018 +0530

    GROOVY-8939: Add methods in StringGroovyMethods for better API Usage (closes #846)
---
 .../groovy/runtime/StringGroovyMethods.java        | 516 +++++++++++++++++++++
 src/test/groovy/GroovyMethodsTest.groovy           | 334 +++++++++++++
 2 files changed, 850 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
index ddca930..66b886c 100644
--- a/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
@@ -3888,4 +3888,520 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
 
         return self.toString().matches("\\s*");
     }
+
+    /**
+     * Returns the last <code>num</code> elements from this CharSequence.
+     * <pre class="groovyTestCase">
+     * def text = "Groovy"
+     * assert text.takeRight( 0 ) == ''
+     * assert text.takeRight( 2 ) == 'vy'
+     * assert text.takeRight( 7 ) == 'Groovy'
+     * </pre>
+     *
+     * @param self the original CharSequence
+     * @param num  the number of chars to take from this CharSequence from the right
+     * @return a CharSequence consisting of the last <code>num</code> chars,
+     * or else the whole CharSequence if it has less than <code>num</code> elements.
+     * @since 3.0.0
+     */
+    public static CharSequence takeRight(CharSequence self, int num) {
+        if (num < 0)
+            return self.subSequence(0, 0);
+
+        int begin = Math.max(0, self.length() - num);
+        return self.subSequence(begin, self.length());
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #takeRight(CharSequence, int)}
+     *
+     * @param self the original CharSequence
+     * @param num  the number of chars to take from this CharSequence from the right
+     * @return a String consisting of the last <code>num</code> chars,
+     * or else the whole CharSequence if it has less than <code>num</code> elements.
+     * @since 3.0.0
+     */
+    public static String takeRight(String self, int num) {
+        return (String) takeRight((CharSequence) self, num);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #takeRight(CharSequence, int)}
+     *
+     * @param self the original GString
+     * @param num  the number of chars to take from this GString from the right
+     * @return a String consisting of the last <code>num</code> chars,
+     * or else the whole GString if it has less than <code>num</code> elements.
+     * @since 3.0.0
+     */
+    public static String takeRight(GString self, int num) {
+        return takeRight(self.toString(), num);
+    }
+
+    /**
+     * Returns the {@code CharSequence} that exists after the first occurrence of the given
+     * {@code searchString} in this CharSequence
+     *
+     * <pre class="groovyTestCase">
+     * def text = "Groovy development. Groovy team"
+     * assert text.takeAfter( 'Groovy' )           == ' development. Groovy team'
+     * assert text.takeAfter( 'team' )             == ''
+     * assert text.takeAfter( '' )                 == ''
+     * assert text.takeAfter( 'Unavailable text' ) == ''
+     * assert text.takeAfter( null )               == ''
+     * </pre>
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence that is searched in this CharSequence
+     * @return CharSequence that is after the given searchString and empty string if it does not exist
+     * @since 3.0.0
+     */
+    public static CharSequence takeAfter(CharSequence self, CharSequence searchString) {
+        if (searchString == null || searchString.toString().isEmpty() || self.length() <= searchString.length())
+            return self.subSequence(0, 0);
+
+        String s = self.toString();
+
+        int index = s.indexOf(searchString.toString());
+
+        return (index == -1) ? self.subSequence(0, 0) : self.subSequence(index + searchString.length(), self.length());
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #takeAfter(CharSequence, CharSequence)}
+     *
+     * @param self         the original CharSequence
+     * @param searchString String that is searched in this CharSequence
+     * @return String that is after the given searchString and empty string if it does not exist
+     * @since 3.0.0
+     */
+    public static String takeAfter(String self, CharSequence searchString) {
+        return (String) takeAfter((CharSequence) self, searchString);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #takeAfter(CharSequence, CharSequence)}
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence that is searched in this CharSequence
+     * @return String that is after the given searchString and empty string if it does not exist
+     * @since 3.0.0
+     */
+    public static String takeAfter(GString self, CharSequence searchString) {
+        return takeAfter(self.toString(), searchString);
+    }
+
+    /**
+     * Returns the {@code CharSequence} that exists before the first occurrence of the given
+     * {@code searchString} in this CharSequence
+     *
+     * <pre class="groovyTestCase">
+     * def text = "Groovy development. Groovy team"
+     *
+     * assert text.takeBefore( ' Groovy ' )         == 'Groovy development.'
+     * assert text.takeBefore( ' ' )                == 'Groovy'
+     * assert text.takeBefore( 'Unavailable text' ) == ''
+     * assert text.takeBefore( null )               == ''
+     * </pre>
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence that is searched in this CharSequence
+     * @return CharSequence that is before the given searchString
+     * @since 3.0.0
+     */
+    public static CharSequence takeBefore(CharSequence self, CharSequence searchString) {
+        if (searchString == null || searchString.toString().isEmpty() || self.length() <= searchString.length())
+            return self.subSequence(0, 0);
+
+        String s = self.toString();
+
+        int index = s.indexOf(searchString.toString());
+
+        return (index == -1) ? self.subSequence(0, 0) : self.subSequence(0, index);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #takeBefore(CharSequence, CharSequence)}
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence that is searched in this CharSequence
+     * @return String that is before the given searchString
+     * @since 3.0.0
+     */
+    public static String takeBefore(GString self, String searchString) {
+        return takeBefore(self.toString(), searchString);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #takeBefore(CharSequence, CharSequence)}
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence that is searched in this CharSequence
+     * @return String that is before the given searchString
+     * @since 3.0.0
+     */
+    public static String takeBefore(String self, String searchString) {
+        return (String) takeBefore((CharSequence) self, searchString);
+    }
+
+    /**
+     * The method returns new CharSequence after removing the right {@code num} chars. Returns empty String if the
+     * {@code num} is greater than the length of the CharSequence
+     *
+     * <pre class="groovyTestCase">
+     * def text = "groovy"
+     *
+     * assert text.dropRight(  3 ) == 'gro'
+     * assert text.dropRight(  6 ) == ''
+     * assert text.dropRight(  0 ) == 'groovy'
+     * assert text.dropRight( -1 ) == 'groovy'
+     * assert text.dropRight( 10 ) == ''
+     *
+     * 	</pre>
+     *
+     * @param self the original CharSequence
+     * @param num  number of characters
+     * @return CharSequence after removing the right {@code num} chars and empty of the {@code num} is greater than the
+     * length of the CharSequence
+     * @since 3.0.0
+     */
+    public static CharSequence dropRight(CharSequence self, int num) {
+
+        if (num < 0)
+            return self;
+
+        if (num >= self.length())
+            return self.subSequence(0, 0);
+
+        return take(self, self.length() - num);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #dropRight(CharSequence, int)}
+     *
+     * @param self the original CharSequence
+     * @param num  number of characters
+     * @return String after removing the right {@code num} chars and empty of the {@code num} is greater than the
+     * length of the CharSequence
+     * @since 3.0.0
+     */
+    public static String dropRight(String self, int num) {
+        return (String) dropRight((CharSequence) self, num);
+    }
+
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #dropRight(CharSequence, int)}
+     *
+     * @param self the original CharSequence
+     * @param num  number of characters
+     * @return String after removing the right {@code num} chars and empty of the {@code num} is greater than the
+     * length of the CharSequence
+     * @since 3.0.0
+     */
+    public static String dropRight(GString self, int num) {
+        return dropRight(self.toString(), num);
+    }
+
+    /**
+     * Returns the CharSequence that is in between the first occurrence of the given {@code from} and {@code to}
+     * CharSequences and empty if the unavailable inputs are given
+     *
+     * <pre class="groovyTestCase">
+     * def text = "Groovy"
+     *
+     * assert text.takeBetween( 'r', 'v' ) == 'oo'
+     * assert text.takeBetween( 'r', 'z' ) == ''
+     * assert text.takeBetween( 'a', 'r' ) == ''
+     *
+     * 	</pre>
+     *
+     * @param self the original CharSequence
+     * @param from beginning of search
+     * @param to   end of search
+     * @return the CharSequence that is in between the given two CharSequences and empty if the unavailable inputs are
+     * given
+     * @see #takeBetween(CharSequence, CharSequence, CharSequence, int)
+     * @since 3.0.0
+     */
+    public static CharSequence takeBetween(CharSequence self, CharSequence from, CharSequence to) {
+        if (from == null || to == null || from.length() == 0 || to.length() == 0 || from.length() > self.length() || to.length() > self.length())
+            return self.subSequence(0, 0);
+
+        String s = self.toString();
+        String f = from.toString();
+
+        int fi = s.indexOf(f);
+
+        if (fi == -1)
+            return self.subSequence(0, 0);
+
+        String t = to.toString();
+
+        int ti = s.indexOf(t, fi + from.length());
+
+        if (ti == -1)
+            return self.subSequence(0, 0);
+
+        return self.subSequence(fi + from.length(), ti);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #takeBetween(CharSequence, CharSequence, CharSequence)}
+     *
+     * @param self the original CharSequence
+     * @param from beginning of search
+     * @param to   end of search
+     * @return String that is in between the given two CharSequences and empty if the unavailable inputs are
+     * given
+     * @since 3.0.0
+     */
+    public static String takeBetween(String self, CharSequence from, CharSequence to) {
+        return (String) takeBetween((CharSequence) self, from, to);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #takeBetween(CharSequence, CharSequence, CharSequence)}
+     *
+     * @param self the original CharSequence
+     * @param from beginning of search
+     * @param to   end of search
+     * @return String that is in between the given two CharSequences and empty if the unavailable inputs are
+     * given
+     * @since 3.0.0
+     */
+    public static String takeBetween(GString self, CharSequence from, CharSequence to) {
+        return takeBetween(self.toString(), from, to);
+    }
+
+    /**
+     * Method to take the characters between the first occurrence of the two subsequent {@code enclosure} strings
+     *
+     * <pre class="groovyTestCase">
+     * def text = "name = 'some name'"
+     *
+     * assert text.takeBetween( "'" ) == 'some name'
+     * assert text.takeBetween( 'z' ) == ''
+     *
+     * </pre>
+     *
+     * @param self      the original CharSequence
+     * @param enclosure Enclosure String
+     * @return CharSequence between the 2 subsequent {@code enclosure} strings
+     * @see #takeBetween(CharSequence, CharSequence, int)
+     * @since 3.0.0
+     */
+    public static CharSequence takeBetween(CharSequence self, CharSequence enclosure) {
+        return takeBetween(self, enclosure, enclosure);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method {@link #takeBetween(CharSequence, CharSequence)}
+     *
+     * @param self      the original GString
+     * @param enclosure Enclosure String
+     * @return String between the 2 subsequent {@code enclosure} strings
+     * @since 3.0.0
+     */
+    public static String takeBetween(String self, CharSequence enclosure) {
+        return (String) takeBetween((CharSequence) self, enclosure);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method {@link #takeBetween(CharSequence, CharSequence)}
+     *
+     * @param self      the original GString
+     * @param enclosure Enclosure String
+     * @return String between the 2 subsequent {@code enclosure} strings
+     * @since 3.0.0
+     */
+    public static String takeBetween(GString self, CharSequence enclosure) {
+        return takeBetween(self.toString(), enclosure);
+    }
+
+    /**
+     * Returns the CharSequence that is in between the given the nth (specified by occurrence) pair of
+     * {@code from} and {@code to} CharSequences and empty if the unavailable inputs are given.
+     *
+     * <pre class="groovyTestCase">
+     * def text = "t1=10 ms, t2=100 ms"
+     *
+     * assert text.takeBetween( '=', ' ', 0 ) == '10'
+     * assert text.takeBetween( '=', ' ', 1 ) == '100'
+     * assert text.takeBetween( 't1', 'z' ) == ''
+     * </pre>
+     *
+     * @param self       the original CharSequence
+     * @param from       beginning of search
+     * @param to         end of search
+     * @param occurrence nth occurrence that is to be returned. 0 represents first one
+     * @return the CharSequence that is in between the given the nth (specified by occurrence) pair of
+     * {@code from} and {@code to} CharSequences and empty if the unavailable inputs are given.
+     * @see #takeBetween(CharSequence, CharSequence, CharSequence)
+     * @since 3.0.0
+     */
+    public static CharSequence takeBetween(CharSequence self, CharSequence from, CharSequence to, int occurrence) {
+        if (from == null || to == null || from.length() > self.length() || to.length() > self.length() || (to.length() + from.length() >= self.length()) || occurrence < 0)
+            return self.subSequence(0, 0);
+
+        String s = self.toString();
+        String f = from.toString();
+
+        int start = 0;
+        int counter = 0;
+
+        while (counter <= occurrence) {
+            int fi = s.indexOf(f, start);
+
+            if (fi == -1)
+                return self.subSequence(0, 0);
+
+            int ti = s.indexOf(to.toString(), fi + f.length());
+
+            if (ti == -1)
+                return self.subSequence(0, 0);
+
+            if (counter == occurrence)
+                return self.subSequence(fi + f.length(), ti);
+
+            start = ti + to.length() + 1;
+            counter++;
+        }
+
+        return self.subSequence(0, 0);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method
+     * {@link #takeBetween(CharSequence, CharSequence, CharSequence, int)}
+     *
+     * @param self       the original CharSequence
+     * @param from       beginning of search
+     * @param to         end of search
+     * @param occurrence nth occurrence that is to be returned. 0 represents first one
+     * @return the String that is in between the given nth (specified by occurrence) pair of
+     * {@code from} and {@code to} CharSequences and empty if the unavailable inputs are given.
+     * @since 3.0.0
+     */
+    public static String takeBetween(String self, CharSequence from, CharSequence to, int occurrence) {
+        return (String) takeBetween((CharSequence) self, from, to, occurrence);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method
+     * {@link #takeBetween(CharSequence, CharSequence, CharSequence, int)}
+     *
+     * @param self       the original CharSequence
+     * @param from       beginning of search
+     * @param to         end of search
+     * @param occurrence nth occurrence that is to be returned. 0 represents first one
+     * @return the String that is in between the given nth (specified by occurrence) pair of
+     * {@code from} and {@code to} CharSequences and empty if the unavailable inputs are given.
+     * @since 3.0.0
+     */
+    public static String takeBetween(GString self, CharSequence from, CharSequence to, int occurrence) {
+        return takeBetween(self.toString(), from, to, occurrence);
+    }
+
+    /**
+     * Method to take the characters between nth (specified by occurrence) pair of @code enclosure} strings
+     *
+     * <pre class="groovyTestCase">
+     * def text = "t1='10' ms, t2='100' ms"
+     *
+     * assert text.takeBetween( "'", 0 ) == '10'
+     * assert text.takeBetween( "'", 1 ) == '100'
+     * assert text.takeBetween( "'", 2 ) == ''
+     * </pre>
+     *
+     * @param self       the original CharSequence
+     * @param enclosure  Enclosure String
+     * @param occurrence nth occurrence being returned
+     * @return CharSequence between the nth occurrence of pair of {@code enclosure} strings
+     * @see #takeBetween(CharSequence, CharSequence, int)
+     * @since 3.0.0
+     */
+    public static CharSequence takeBetween(CharSequence self, CharSequence enclosure, int occurrence) {
+        return takeBetween(self, enclosure, enclosure, occurrence);
+    }
+
+    /**
+     * A String variant of the equivalent CharSequence method
+     * {@link #takeBetween(CharSequence, CharSequence, int)}
+     *
+     * @param self       the original CharSequence
+     * @param enclosure  Enclosure String
+     * @param occurrence nth occurrence being returned
+     * @return String between the nth occurrence of pair of {@code enclosure} strings
+     * @since 3.0.0
+     */
+    public static String takeBetween(String self, CharSequence enclosure, int occurrence) {
+        return (String) takeBetween((CharSequence) self, enclosure, occurrence);
+    }
+
+    /**
+     * A GString variant of the equivalent CharSequence method
+     * {@link #takeBetween(CharSequence, CharSequence, int)}
+     *
+     * @param self       the original CharSequence
+     * @param enclosure  Enclosure String
+     * @param occurrence nth occurrence being returned
+     * @return String between the nth occurrence of pair of {@code enclosure} strings
+     * @since 3.0.0
+     */
+    public static String takeBetween(GString self, CharSequence enclosure, int occurrence) {
+        return takeBetween(self.toString(), enclosure, occurrence);
+    }
+
+    /**
+     * Checks whether this CharSequence starts with the {@code searchString} ignoring the case considerations
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence being checked against this
+     * @return {@code true} if the character sequence represented by the argument is a prefix of this CharSequence
+     * ignoring the case considerations. {@code false} otherwise. Returns false if the argument is null
+     * @since 3.0.0
+     */
+    public static boolean startsWithIgnoreCase(CharSequence self, CharSequence searchString) {
+        if (searchString == null || searchString.length() == 0 || self.length() < searchString.length())
+            return false;
+
+        String s = take(self.toString(), searchString.length()).toString();
+
+        return s.equalsIgnoreCase(searchString.toString());
+    }
+
+    /**
+     * Checks whether this CharSequence ends with the {@code searchString} ignoring the case considerations
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence bring checked against this
+     * @return {@code true} if the character sequence represented by the argument is a suffix of this CharSequence
+     * ignoring the case considerations. {@code false} otherwise. Returns false if the argument is null
+     * @since 3.0.0
+     */
+    public static boolean endsWithIgnoreCase(CharSequence self, CharSequence searchString) {
+        if (searchString == null || searchString.length() == 0 || self.length() < searchString.length())
+            return false;
+
+        String s = takeRight(self.toString(), searchString.length()).toString();
+
+        return s.equalsIgnoreCase(searchString.toString());
+    }
+
+    /**
+     * Checks whether this CharSequence contains the {@code searchString} ignoring the caseConsiderations
+     *
+     * @param self         the original CharSequence
+     * @param searchString CharSequence being checked against this
+     * @return {@code true} if the character sequence represented by the argument exists in this CharSequence
+     * ignoring the case considerations. {@code false} otherwise. Returns false if the argument is null
+     * @since 3.0.0
+     */
+    public static boolean containsIgnoreCase(CharSequence self, CharSequence searchString) {
+        if (searchString == null || searchString.length() == 0 || self.length() < searchString.length())
+            return false;
+
+        return self.toString().toLowerCase().contains(searchString.toString().toLowerCase());
+    }
 }
diff --git a/src/test/groovy/GroovyMethodsTest.groovy b/src/test/groovy/GroovyMethodsTest.groovy
index b773890..b23fd27 100644
--- a/src/test/groovy/GroovyMethodsTest.groovy
+++ b/src/test/groovy/GroovyMethodsTest.groovy
@@ -19,6 +19,7 @@
 package groovy
 
 import java.awt.Dimension
+import java.nio.CharBuffer
 import java.util.concurrent.LinkedBlockingQueue
 import org.codehaus.groovy.util.StringUtil
 
@@ -1820,6 +1821,339 @@ class GroovyMethodsTest extends GroovyTestCase {
             ([] as int[]).swap(1, 2)
         }
     }
+
+    void testCharSequenceTakeRight() {
+        def data = ['groovy',      // String
+                    "${'groovy'}", // GString
+                    java.nio.CharBuffer.wrap('groovy'),
+                    new StringBuffer('groovy'),
+                    new StringBuilder('groovy')]
+        data.each {
+            // Need toString() as CharBuffer.subSequence returns a java.nio.StringCharBuffer
+            assert it.takeRight(-1).toString() == ''
+            assert it.takeRight(0).toString() == ''
+            assert it.takeRight(3).toString() == 'ovy'
+            assert it.takeRight(6).toString() == 'groovy'
+            assert it.takeRight(10).toString() == 'groovy'
+        }
+    }
+
+    void testCharSequenceTakeAfter() {
+        def text = 'Groovy development. Groovy team'
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        List<List<String>> searchStringsAndResults = [
+
+                ['Groovy', ' development. Groovy team'],
+                ['team', ''],
+                ['Java.', ''],
+                ['Unavailable text', ''],
+                ['Some larger String than self', ''],
+                ['', ''],
+                [null, '']
+        ]
+
+        data.each { s ->
+
+            searchStringsAndResults.each { r ->
+
+                // Need toString() as CharBuffer.subSequence returns a java.nio.StringCharBuffer
+
+                assert s.takeAfter(r[0]).toString() == r[1]                //String as searchString
+                assert s.takeAfter("${r[0]}").toString() == r[1]  //GString as searchString
+
+                if (r[0]) {
+                    assert s.takeAfter(java.nio.CharBuffer.wrap(r[0])).toString() == r[1] //CharBuffer as searchString
+                    assert s.takeAfter(new StringBuffer(r[0])).toString() == r[1]  //StringBuffer as searchString
+                    assert s.takeAfter(new StringBuilder(r[0])).toString() == r[1] //StringBuilder as searchString
+                }
+            }
+        }
+
+    }
+
+    void testCharSequenceTakeBefore() {
+        def text = "Groovy development. Groovy team"
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        List<List<String>> searchStringsAndResults = [
+
+                [' Groovy ', 'Groovy development.'],
+                ['Groovy', ''],
+                [' ', 'Groovy'],
+                ['Unavailable text', ''],
+                ['Some larger String than self', ''],
+                ['r', 'G'],
+                ['', ''],
+                [null, '']
+        ]
+
+        data.each { s ->
+
+            searchStringsAndResults.each { r ->
+
+                // Need toString() as CharBuffer.subSequence returns a java.nio.StringCharBuffer
+
+                assert s.takeBefore(r[0]).toString() == r[1]                //String as searchString
+                assert s.takeBefore("${r[0]}").toString() == r[1]  //GString as searchString
+
+                if (r[0]) {
+                    assert s.takeBefore(java.nio.CharBuffer.wrap(r[0])).toString() == r[1] //CharBuffer as searchString
+                    assert s.takeBefore(new StringBuffer(r[0])).toString() == r[1]  //StringBuffer as searchString
+                    assert s.takeBefore(new StringBuilder(r[0])).toString() == r[1] //StringBuilder as searchString
+                }
+            }
+        }
+
+    }
+
+    void testCharSequenceDropRight() {
+        def data = ['groovy',      // String
+                    "${'groovy'}", // GString
+                    java.nio.CharBuffer.wrap('groovy'),
+                    new StringBuffer('groovy'),
+                    new StringBuilder('groovy')]
+        data.each {
+            // Need toString() as CharBuffer.subSequence returns a java.nio.StringCharBuffer
+            assert it.dropRight(-1).toString() == 'groovy'
+            assert it.dropRight(0).toString() == 'groovy'
+            assert it.dropRight(3).toString() == 'gro'
+            assert it.dropRight(6).toString() == ''
+            assert it.dropRight(10).toString() == ''
+        }
+    }
+
+    void testCharSequenceTakeBetween() {
+
+        def text = 'Time taken for Select Query = 12 ms, Update Query = 15 ms. Result = "One", "Two"'
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        data.each { s ->
+
+            List<List<String>> fromToCasesWithoutNum = [
+
+                    ['Query = ', ' ms', '12'], //positive case
+                    ['Query = ', ' MS', ''],   //negative case with invalid 'to'
+                    ['Query123 = ', ' ms', '']     //negative case with invalid 'from'
+            ]
+
+            fromToCasesWithoutNum.each { r ->
+
+                assert s.takeBetween(r[0], r[1]).toString() == r[2]
+                assert s.takeBetween("${r[0]}", "${r[1]}").toString() == r[2]
+
+                if (r[0] && r[1]) {
+                    assert s.takeBetween(CharBuffer.wrap(r[0]), CharBuffer.wrap(r[1])).toString() == r[2]
+                    assert s.takeBetween(new StringBuffer(r[0]), CharBuffer.wrap(r[1])).toString() == r[2]
+                    assert s.takeBetween(CharBuffer.wrap(r[0]), new StringBuilder(r[1])).toString() == r[2]
+                }
+            }
+        }
+
+        data.each { s ->
+
+            List<List<String>> enclosureWithoutNum = [
+
+                    ['"', 'One'],               //positive case
+                    ['Query', ' = 12 ms, Update '], //negative case with invalid enclosure
+                    ['Query123', '']                   //negative case with invalid enclosure
+            ]
+
+            enclosureWithoutNum.each { r ->
+
+                assert s.takeBetween(r[0]).toString() == r[1]
+                assert s.takeBetween("${r[0]}").toString() == r[1]
+
+                if (r[0] && r[1]) {
+                    assert s.takeBetween(CharBuffer.wrap(r[0])).toString() == r[1]
+                    assert s.takeBetween(new StringBuffer(r[0])).toString() == r[1]
+                    assert s.takeBetween(new StringBuilder(r[0])).toString() == r[1]
+                }
+            }
+        }
+
+        data.each { s ->
+
+            List<List<Object>> fromToCasesWithNum = [
+
+                    ['Query = ', ' ms', 1, '15'],
+                    ['Query = ', ' ms', 2, '']
+            ]
+
+            fromToCasesWithNum.each { r ->
+
+                assert s.takeBetween(r[0], r[1], r[2]).toString() == r[3]
+                assert s.takeBetween("${r[0]}", "${r[1]}", r[2]).toString() == r[3]
+
+                if (r[0] && r[1]) {
+                    assert s.takeBetween(CharBuffer.wrap(r[0]), CharBuffer.wrap(r[1]), r[2]).toString() == r[3]
+                    assert s.takeBetween(new StringBuffer(r[0]), new StringBuffer(r[1]), r[2]).toString() == r[3]
+                    assert s.takeBetween(new StringBuilder(r[0]), new StringBuilder(r[1]), r[2]).toString() == r[3]
+                }
+            }
+        }
+
+        data.each { s ->
+
+            List<List<Object>> enclosureWithNum = [
+
+                    ['"', 1, 'Two'],
+                    ['"', 2, ''],
+                    ['"', -1, '']
+            ]
+
+            enclosureWithNum.each { r ->
+
+                assert s.takeBetween(r[0], r[1]).toString() == r[2]
+                assert s.takeBetween("${r[0]}", r[1]).toString() == r[2]
+
+                if (r[0] && r[1]) {
+                    assert s.takeBetween(CharBuffer.wrap(r[0]), r[1]).toString() == r[2]
+                    assert s.takeBetween(new StringBuffer(r[0]), r[1]).toString() == r[2]
+                    assert s.takeBetween(new StringBuilder(r[0]), r[1]).toString() == r[2]
+                }
+            }
+        }
+
+        assert 'smalltext'.takeBetween('somelargertextfrom', 'somelargertextto') == ''
+        assert 'smalltext'.takeBetween('somelargertextfrom', 'somelargertextto', 0) == ''
+
+        def text2 = "name = 'some name'"
+
+        assert text2.takeBetween("'") == 'some name'
+        assert text2.takeBetween('z') == ''
+
+        def text3 = "t1=10 ms, t2=100 ms"
+
+        assert text3.takeBetween('=', ' ', 0) == '10'
+        assert text3.takeBetween('=', ' ', 1) == '100'
+        assert text3.takeBetween('t1', 'z') == ''
+
+        assert 'one\ntwo\nthree'.takeBetween('\n') == 'two'
+    }
+
+    void testCharSequenceStartsWithIgnoreCase() {
+        def text = 'Some Text'
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        List<List<Object>> searchStringsAndResults = [
+
+                ['SOME', true],
+                ['some', true],
+                ['Some', true],
+                ['Wrong', false],
+                ['Some larger String than self', false],
+                ['', false],
+                [null, false]
+        ]
+
+        data.each { s ->
+
+            searchStringsAndResults.each { r ->
+
+                assert s.startsWithIgnoreCase(r[0]) == r[1]
+                assert s.startsWithIgnoreCase("${r[0]}") == r[1]
+
+                if (r[0]) {
+                    assert s.startsWithIgnoreCase(CharBuffer.wrap(r[0])) == r[1]
+                    assert s.startsWithIgnoreCase(new StringBuffer(r[0])) == r[1]
+                    assert s.startsWithIgnoreCase(new StringBuilder(r[0])) == r[1]
+                }
+            }
+        }
+    }
+
+    void testCharSequenceEndsWithIgnoreCase() {
+        def text = 'Some Text'
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        List<List<Object>> searchStringsAndResults = [
+
+                ['TEXT', true],
+                ['text', true],
+                ['Text', true],
+                ['Wrong', false],
+                ['Some larger String than self', false],
+                ['', false],
+                [null, false]
+        ]
+
+        data.each { s ->
+
+            searchStringsAndResults.each { r ->
+
+                assert s.endsWithIgnoreCase(r[0]) == r[1]
+                assert s.endsWithIgnoreCase("${r[0]}") == r[1]
+
+                if (r[0]) {
+                    assert s.endsWithIgnoreCase(CharBuffer.wrap(r[0])) == r[1]
+                    assert s.endsWithIgnoreCase(new StringBuffer(r[0])) == r[1]
+                    assert s.endsWithIgnoreCase(new StringBuilder(r[0])) == r[1]
+                }
+            }
+        }
+    }
+
+    void testCharSequenceContainsIgnoreCase() {
+        def text = 'Some Text'
+
+        def data = [text,      // String
+                    "${text}", // GString
+                    java.nio.CharBuffer.wrap(text),
+                    new StringBuffer(text),
+                    new StringBuilder(text)]
+
+        List<List<Object>> searchStringsAndResults = [
+
+                ['E TEX', true],
+                ['Me t', true],
+                ['me T', true],
+                ['Wrong', false],
+                ['Some larger String than self', false],
+                ['', false],
+                [null, false]
+        ]
+
+        data.each { s ->
+
+            searchStringsAndResults.each { r ->
+
+                assert s.containsIgnoreCase(r[0]) == r[1]
+                assert s.containsIgnoreCase("${r[0]}") == r[1]
+
+                if (r[0]) {
+                    assert s.containsIgnoreCase(CharBuffer.wrap(r[0])) == r[1]
+                    assert s.containsIgnoreCase(new StringBuffer(r[0])) == r[1]
+                    assert s.containsIgnoreCase(new StringBuilder(r[0])) == r[1]
+                }
+            }
+        }
+    }
 }
 
 class WackyList extends LinkedList {