succ()
public
Returns the successor to str. The successor is calculated by
incrementing characters starting from the rightmost alphanumeric (or the
rightmost character if there are no alphanumerics) in the string.
Incrementing a digit always results in another digit, and incrementing a
letter results in another letter of the same case. Incrementing
nonalphanumerics uses the underlying character set’s collating sequence.
If the increment generates a “carry,” the character to the left of it
is incremented. This process repeats until there is no carry, adding an
additional character if necessary.
"abcd".succ
"THX1138".succ
"<<koala>>".succ
"1999zzz".succ
"ZZZ9999".succ
"***".succ
Show source
/*
* call-seq:
* str.succ => new_str
* str.next => new_str
*
* Returns the successor to <i>str</i>. The successor is calculated by
* incrementing characters starting from the rightmost alphanumeric (or
* the rightmost character if there are no alphanumerics) in the
* string. Incrementing a digit always results in another digit, and
* incrementing a letter results in another letter of the same case.
* Incrementing nonalphanumerics uses the underlying character set's
* collating sequence.
*
* If the increment generates a ``carry,'' the character to the left of
* it is incremented. This process repeats until there is no carry,
* adding an additional character if necessary.
*
* "abcd".succ #=> "abce"
* "THX1138".succ #=> "THX1139"
* "<<koala>>".succ #=> "<<koalb>>"
* "1999zzz".succ #=> "2000aaa"
* "ZZZ9999".succ #=> "AAAA0000"
* "***".succ #=> "**+"
*/
static VALUE
rb_str_succ(orig)
VALUE orig;
{
VALUE str;
char *sbeg, *s;
int c = -1;
long n = 0;
str = rb_str_new5(orig, RSTRING(orig)->ptr, RSTRING(orig)->len);
OBJ_INFECT(str, orig);
if (RSTRING(str)->len == 0) return str;
sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1;
while (sbeg <= s) {
if (ISALNUM(*s)) {
if ((c = succ_char(s)) == 0) break;
n = s - sbeg;
}
s--;
}
if (c == -1) { /* str contains no alnum */
sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1;
c = '\001';
while (sbeg <= s) {
if ((*s += 1) != 0) break;
s--;
}
}
if (s < sbeg) {
RESIZE_CAPA(str, RSTRING(str)->len + 1);
s = RSTRING(str)->ptr + n;
memmove(s+1, s, RSTRING(str)->len - n);
*s = c;
RSTRING(str)->len += 1;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
}
return str;
}