diff options
| author | h2so5 <[email protected]> | 2013-04-19 14:10:10 +0900 |
|---|---|---|
| committer | h2so5 <[email protected]> | 2013-04-19 21:01:37 +0900 |
| commit | 79e7bbc8e819da79928dbf928382c17d85239497 (patch) | |
| tree | ed3a33b241bc0e7aa2794f069776fadebf8b6b66 /mrbgems | |
| parent | b9674c735e7b06205c3b8bface31792ee1354778 (diff) | |
| download | mruby-79e7bbc8e819da79928dbf928382c17d85239497.tar.gz mruby-79e7bbc8e819da79928dbf928382c17d85239497.zip | |
Add String#swapcase,swapcase!,concat,casecmp,start_with,end_with
Diffstat (limited to 'mrbgems')
| -rw-r--r-- | mrbgems/mruby-string-ext/mrblib/string.rb | 14 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 144 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/test/string.rb | 38 |
3 files changed, 196 insertions, 0 deletions
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 142a63882..005438b38 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -35,4 +35,18 @@ class String s = self.strip (s == self) ? nil : self.replace(s) end + +# call-seq: +# str.casecmp(other_str) -> -1, 0, +1 or nil +# +# Case-insensitive version of <code>String#<=></code>. +# +# "abcdef".casecmp("abcde") #=> 1 +# "aBcDeF".casecmp("abcdef") #=> 0 +# "abcdef".casecmp("abcdefg") #=> -1 +# "abcdef".casecmp("ABCDEF") #=> 0 +# + def casecmp(str) + self.downcase <=> str.downcase + end end diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index b10b021a2..5acff9deb 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -1,5 +1,7 @@ #include "mruby.h" #include "mruby/string.h" +#include <ctype.h> +#include <string.h> static mrb_value mrb_str_getbyte(mrb_state *mrb, mrb_value str) @@ -15,6 +17,142 @@ mrb_str_getbyte(mrb_state *mrb, mrb_value str) return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]); } +/* + * call-seq: + * str.swapcase! -> str or nil + * + * Equivalent to <code>String#swapcase</code>, but modifies the receiver in + * place, returning <i>str</i>, or <code>nil</code> if no changes were made. + * Note: case conversion is effective only in ASCII region. + */ +static mrb_value +mrb_str_swapcase_bang(mrb_state *mrb, mrb_value str) +{ + char *p, *pend; + int modify = 0; + struct RString *s = mrb_str_ptr(str); + + mrb_str_modify(mrb, s); + p = s->ptr; + pend = s->ptr + s->len; + while (p < pend) { + if (ISUPPER(*p)) { + *p = TOLOWER(*p); + modify = 1; + } + else if (ISLOWER(*p)) { + *p = TOUPPER(*p); + modify = 1; + } + p++; + } + + if (modify) return str; + return mrb_nil_value(); +} + +/* + * call-seq: + * str.swapcase -> new_str + * + * Returns a copy of <i>str</i> with uppercase alphabetic characters converted + * to lowercase and lowercase characters converted to uppercase. + * Note: case conversion is effective only in ASCII region. + * + * "Hello".swapcase #=> "hELLO" + * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" + */ +static mrb_value +mrb_str_swapcase(mrb_state *mrb, mrb_value self) +{ + mrb_value str; + + str = mrb_str_dup(mrb, self); + mrb_str_swapcase_bang(mrb, str); + return str; +} + +/* + * call-seq: + * str << integer -> str + * str.concat(integer) -> str + * str << obj -> str + * str.concat(obj) -> str + * + * Append---Concatenates the given object to <i>str</i>. If the object is a + * <code>Integer</code>, it is considered as a codepoint, and is converted + * to a character before concatenation. + * + * a = "hello " + * a << "world" #=> "hello world" + * a.concat(33) #=> "hello world!" + */ +static mrb_value +mrb_str_concat2(mrb_state *mrb, mrb_value self) +{ + mrb_value str; + mrb_get_args(mrb, "S", &str); + mrb_str_concat(mrb, self, str); + return self; +} + +/* + * call-seq: + * str.start_with?([prefixes]+) -> true or false + * + * Returns true if +str+ starts with one of the +prefixes+ given. + * + * "hello".start_with?("hell") #=> true + * + * # returns true if one of the prefixes matches. + * "hello".start_with?("heaven", "hell") #=> true + * "hello".start_with?("heaven", "paradise") #=> false + */ +static mrb_value +mrb_str_start_with(mrb_state *mrb, mrb_value self) +{ + mrb_value *argv; + int argc, i; + mrb_get_args(mrb, "*", &argv, &argc); + + for (i = 0; i < argc; i++) { + size_t len_l, len_r, len_cmp; + len_l = RSTRING_LEN(self); + len_r = RSTRING_LEN(argv[i]); + len_cmp = (len_l > len_r) ? len_r : len_l; + if (memcmp(RSTRING_PTR(self), RSTRING_PTR(argv[i]), len_cmp) == 0) { + return mrb_true_value(); + } + } + return mrb_false_value(); +} + +/* + * call-seq: + * str.end_with?([suffixes]+) -> true or false + * + * Returns true if +str+ ends with one of the +suffixes+ given. + */ +static mrb_value +mrb_str_end_with(mrb_state *mrb, mrb_value self) +{ + mrb_value *argv; + int argc, i; + mrb_get_args(mrb, "*", &argv, &argc); + + for (i = 0; i < argc; i++) { + size_t len_l, len_r, len_cmp; + len_l = RSTRING_LEN(self); + len_r = RSTRING_LEN(argv[i]); + len_cmp = (len_l > len_r) ? len_r : len_l; + if (memcmp(RSTRING_PTR(self) + (len_l - len_cmp), + RSTRING_PTR(argv[i]) + (len_r - len_cmp), + len_cmp) == 0) { + return mrb_true_value(); + } + } + return mrb_false_value(); +} void mrb_mruby_string_ext_gem_init(mrb_state* mrb) @@ -23,6 +161,12 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "dump", mrb_str_dump, ARGS_NONE()); mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, ARGS_REQ(1)); + mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, ARGS_NONE()); + mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, ARGS_NONE()); + mrb_define_method(mrb, s, "concat", mrb_str_concat2, ARGS_REQ(1)); + mrb_define_method(mrb, s, "<<", mrb_str_concat2, ARGS_REQ(1)); + mrb_define_method(mrb, s, "start_with?", mrb_str_start_with, ARGS_REST()); + mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, ARGS_REST()); } void diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index eaff81890..ce4bc7352 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -70,3 +70,41 @@ assert('String#rstrip!') do t = " abc" s.rstrip! == " abc" and s == " abc" and t.rstrip! == nil end + +assert('String#swapcase') do + assert_equal "Hello".swapcase, "hELLO" + assert_equal "cYbEr_PuNk11".swapcase, "CyBeR_pUnK11" +end + +assert('String#swapcase!') do + s = "Hello" + t = s.clone + t.swapcase! + assert_equal s.swapcase, t +end + +assert('String#concat') do + s = "Hello " + s.concat "World!" + t = "Hello " + t << "World!" + assert_equal "Hello World!", t + assert_equal "Hello World!", s +end + +assert('String#casecmp') do + assert_equal "abcdef".casecmp("abcde"), 1 + assert_equal "aBcDeF".casecmp("abcdef"), 0 + assert_equal "abcdef".casecmp("abcdefg"),-1 + assert_equal "abcdef".casecmp("ABCDEF"), 0 +end + +assert('String#start_with?') do + assert_true "hello".start_with?("heaven", "hell") + assert_true !"hello".start_with?("heaven", "paradise") +end + +assert('String#end_with?') do + assert_true "string".end_with?("ing", "mng") + assert_true !"string".end_with?("str", "tri") +end |
