summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-string-ext/src/string.c
diff options
context:
space:
mode:
authormattn <[email protected]>2014-08-08 17:58:07 +0900
committermattn <[email protected]>2014-08-08 17:58:07 +0900
commitdc0c3546581fb10b2a9abb0e399f1f58488a2fc5 (patch)
tree5db5a93d4e89bd9dc2dfce2a5e919604edc019d1 /mrbgems/mruby-string-ext/src/string.c
parent569c7dec5f884c3d1345dcc22b7ac0f568a06437 (diff)
downloadmruby-dc0c3546581fb10b2a9abb0e399f1f58488a2fc5.tar.gz
mruby-dc0c3546581fb10b2a9abb0e399f1f58488a2fc5.zip
Add String#succ, String#succ!, String#next, String#next!
Diffstat (limited to 'mrbgems/mruby-string-ext/src/string.c')
-rw-r--r--mrbgems/mruby-string-ext/src/string.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c
index f04f12c4b..2d745589b 100644
--- a/mrbgems/mruby-string-ext/src/string.c
+++ b/mrbgems/mruby-string-ext/src/string.c
@@ -239,6 +239,76 @@ mrb_str_lines(mrb_state *mrb, mrb_value self)
return result;
}
+/*
+ * call-seq:
+ * string.succ -> string
+ *
+ * Returns next sequence of the string;
+ *
+ * a = "abc"
+ * a.succ #=> "abd"
+ */
+static mrb_value
+mrb_str_succ_bang(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ char *p, *e, *b, *t, *prepend;
+ struct RString *s = mrb_str_ptr(self);
+ size_t l;
+
+ if (RSTRING_LEN(self) == 0)
+ return self;
+
+ mrb_str_modify(mrb, s);
+ l = RSTRING_LEN(self);
+ b = p = RSTRING_PTR(self);
+ t = e = p + l;
+ *(e--) = 0;
+
+ while (b < e) {
+ if (ISALNUM(*b))
+ break;
+ b++;
+ }
+ result = mrb_str_new(mrb, p, b - p);
+
+ while (e >= b) {
+ if (!ISALNUM(*e))
+ break;
+ prepend = NULL;
+ if (*e == '9') {
+ if (e == b) prepend = "1";
+ *e = '0';
+ } else if (*e == 'z') {
+ if (e == b) prepend = "a";
+ *e = 'a';
+ } else if (*e == 'Z') {
+ if (e == b) prepend = "A";
+ *e = 'A';
+ } else {
+ (*e)++;
+ break;
+ }
+ if (prepend) mrb_str_cat_cstr(mrb, result, prepend);
+ e--;
+ }
+ result = mrb_str_cat(mrb, result, b, t - b);
+ l = RSTRING_LEN(result);
+ mrb_str_resize(mrb, self, l);
+ memcpy(RSTRING_PTR(self), RSTRING_PTR(result), l);
+ return self;
+}
+
+static mrb_value
+mrb_str_succ(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_succ_bang(mrb, str);
+ return str;
+}
+
void
mrb_mruby_string_ext_gem_init(mrb_state* mrb)
{
@@ -256,6 +326,10 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "oct", mrb_str_oct, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE());
+ mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
+ mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
}
void