From 6e0b5f40cc708f93013262c55991a6ab4e115823 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 8 Jul 2008 16:38:40 +0000 Subject: [PATCH] * string.c (rb_str_succ): alphabets or numerics mutually enclosing non-alphanumeric characters can carry up. e.g., "1.999".succ should be "2.000". git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17963 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ string.c | 25 +++++++++++++++++-------- test/ruby/test_string.rb | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0320aced2c..baef55cb0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Wed Jul 9 01:38:37 2008 Nobuyoshi Nakada + + * string.c (rb_str_succ): alphabets or numerics mutually enclosing + non-alphanumeric characters can carry up. e.g., "1.999".succ should + be "2.000". + Wed Jul 9 00:12:31 2008 Yusuke Endoh * thread.c (rb_set_coverages, rb_reset_coverages): enable and disable diff --git a/string.c b/string.c index 8c1cf0d831..e1bb65599e 100644 --- a/string.c +++ b/string.c @@ -2516,11 +2516,12 @@ rb_str_succ(VALUE orig) { rb_encoding *enc; VALUE str; - char *sbeg, *s, *e; + char *sbeg, *s, *e, *last_alnum = 0; int c = -1; long l; char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1"; int carry_pos = 0, carry_len = 1; + enum neighbor_char neighbor = NEIGHBOR_FOUND; str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig)); rb_enc_cr_str_copy_for_substr(str, orig); @@ -2532,19 +2533,27 @@ rb_str_succ(VALUE orig) s = e = sbeg + RSTRING_LEN(str); while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) { - enum neighbor_char neighbor; + if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) { + if (ISALPHA(*last_alnum) ? ISDIGIT(*s) : + ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) { + s = last_alnum; + break; + } + } if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue; neighbor = enc_succ_alnum_char(s, l, enc, carry); - if (neighbor == NEIGHBOR_NOT_CHAR) { - if (c == -1) continue; - s++; + switch (neighbor) { + case NEIGHBOR_NOT_CHAR: + continue; + case NEIGHBOR_FOUND: + return str; + case NEIGHBOR_WRAPPED: + last_alnum = s; + break; } - else if (neighbor == NEIGHBOR_FOUND) - return str; c = 1; carry_pos = s - sbeg; carry_len = l; - if (neighbor == NEIGHBOR_NOT_CHAR) break; } if (c == -1) { /* str contains no alnum */ s = e; diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 29bc2672ec..37278b192a 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1221,6 +1221,7 @@ class TestString < Test::Unit::TestCase assert_equal(S("124"), S("123").succ) assert_equal(S("1000"), S("999").succ) + assert_equal(S("2.000"), S("1.999").succ) assert_equal(S("No.10"), S("No.9").succ) assert_equal(S("2000aaa"), S("1999zzz").succ)