@@ -1981,6 +1981,50 @@ public static String next(final CharSequence self) {
19811981 return buffer .toString ();
19821982 }
19831983
1984+ /**
1985+ * A variant of next with an integer count parameter; equivalent to calling next() count times.
1986+ * <pre class="groovyTestCase">
1987+ * assert 'a'.next(1) == 'a'.next()
1988+ * assert 'a'.next(4) == 'e'
1989+ * assert 'a'.next(0) == 'a'
1990+ * assert 'a'.next(25) == 'z'
1991+ * assert 'A'.next(32) == 'a'
1992+ * assert (0..4).collect('a'::next) == 'a'..'e'
1993+ * assert 'car'.next(2) == 'cat'
1994+ * </pre>
1995+ *
1996+ * @param self a CharSequence
1997+ * @param n how many times to increment
1998+ * @see #next(CharSequence)
1999+ * @return a value obtained by incrementing the toString() of the CharSequence n times
2000+ *
2001+ * @since 5.0.0
2002+ */
2003+ public static String next (final CharSequence self , int n ) {
2004+ if (n < 0 ) {
2005+ throw new IllegalArgumentException ("A negative value for n is not supported" );
2006+ }
2007+ if (n == 0 ) {
2008+ return self .toString ();
2009+ }
2010+ StringBuilder buffer = new StringBuilder (self );
2011+ if (buffer .length () == 0 ) {
2012+ buffer .append (Character .MIN_VALUE );
2013+ } else {
2014+ char last = buffer .charAt (buffer .length () - 1 );
2015+ for (; n > 0 ; n --) {
2016+ if (last == Character .MAX_VALUE ) {
2017+ buffer .append (Character .MIN_VALUE );
2018+ last = Character .MIN_VALUE ;
2019+ } else {
2020+ last ++;
2021+ }
2022+ }
2023+ buffer .setCharAt (buffer .length () - 1 , last );
2024+ }
2025+ return buffer .toString ();
2026+ }
2027+
19842028 /**
19852029 * Returns a String with linefeeds and carriage returns normalized to linefeeds.
19862030 *
@@ -2228,6 +2272,54 @@ public static String previous(final CharSequence self) {
22282272 return buffer .toString ();
22292273 }
22302274
2275+ /**
2276+ * A variant of previous with an integer count parameter; equivalent to calling previous() count times.
2277+ * <pre class="groovyTestCase">
2278+ * assert 'b'.previous(1) == 'b'.previous()
2279+ * assert 'e'.previous(4) == 'a'
2280+ * assert 'a'.previous(0) == 'a'
2281+ * assert 'z'.previous(25) == 'a'
2282+ * assert 'a'.previous(32) == 'A'
2283+ * assert (0..4).collect('z'::previous) == 'z'..'v'
2284+ * assert 'cat'.previous(2) == 'car'
2285+ * </pre>
2286+ *
2287+ * @param self a CharSequence
2288+ * @param n how many times to decrement
2289+ * @see #previous(CharSequence)
2290+ * @return a value obtained by decrementing the toString() of the CharSequence n times
2291+ *
2292+ * @since 5.0.0
2293+ */
2294+ public static String previous (final CharSequence self , int n ) {
2295+ if (n < 0 ) {
2296+ throw new IllegalArgumentException ("A negative value for n is not supported" );
2297+ }
2298+ if (n == 0 ) {
2299+ return self .toString ();
2300+ }
2301+ StringBuilder buffer = new StringBuilder (self );
2302+ if (buffer .length () == 0 ) throw new IllegalArgumentException ("the string is empty" );
2303+ char last = buffer .charAt (buffer .length () - 1 );
2304+ boolean empty = false ;
2305+ for (; n > 0 ; n --) {
2306+ if (empty ) throw new IllegalArgumentException ("the string became empty while decrementing" );
2307+ if (last == Character .MIN_VALUE ) {
2308+ buffer .deleteCharAt (buffer .length () - 1 );
2309+ empty = buffer .length () == 0 ;
2310+ if (!empty ) {
2311+ last = buffer .charAt (buffer .length () - 1 );
2312+ }
2313+ } else {
2314+ last --;
2315+ }
2316+ }
2317+ if (!empty ) {
2318+ buffer .setCharAt (buffer .length () - 1 , last );
2319+ }
2320+ return buffer .toString ();
2321+ }
2322+
22312323 /**
22322324 * Supports the range subscript operator for StringBuffer.
22332325 *
0 commit comments