diff options
Diffstat (limited to 'mrbgems/mruby-string-ext')
| -rw-r--r-- | mrbgems/mruby-string-ext/mrblib/string.rb | 50 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 65 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/test/string.rb | 58 |
3 files changed, 106 insertions, 67 deletions
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index c3b765a5f..8895b7ad3 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -45,7 +45,7 @@ class String def lstrip a = 0 z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z + a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) (z >= 0) ? self[a..z] : "" end @@ -62,7 +62,7 @@ class String def rstrip a = 0 z = self.size - 1 - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z + z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) (z >= 0) ? self[a..z] : "" end @@ -78,8 +78,8 @@ class String def strip a = 0 z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z + a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) + z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) (z >= 0) ? self[a..z] : "" end @@ -275,15 +275,11 @@ class String # "hello".ljust(20) #=> "hello " # "hello".ljust(20, '1234') #=> "hello123412341234123" def ljust(idx, padstr = ' ') - if idx <= self.size - return self - end - newstr = self.dup - newstr << padstr - while newstr.size <= idx - newstr << padstr - end - return newstr.slice(0,idx) + raise ArgumentError, 'zero width padding' if padstr == '' + return self if idx <= self.size + pad_repetitions = (idx / padstr.length).ceil + padding = (padstr * pad_repetitions)[0...(idx - self.length)] + self + padding end ## @@ -298,15 +294,11 @@ class String # "hello".rjust(20) #=> " hello" # "hello".rjust(20, '1234') #=> "123412341234123hello" def rjust(idx, padstr = ' ') - if idx <= self.size - return self - end - padsize = idx - self.size - newstr = padstr.dup - while newstr.size <= padsize - newstr << padstr - end - return newstr.slice(0,padsize) + self + raise ArgumentError, 'zero width padding' if padstr == '' + return self if idx <= self.size + pad_repetitions = (idx / padstr.length).ceil + padding = (padstr * pad_repetitions)[0...(idx - self.length)] + padding + self end # str.upto(other_str, exclusive=false) {|s| block } -> str @@ -385,4 +377,18 @@ class String end end alias each_codepoint codepoints + + ## + # call-seq: + # str.prepend(other_str) -> str + # + # Prepend---Prepend the given string to <i>str</i>. + # + # a = "world" + # a.prepend("hello ") #=> "hello world" + # a #=> "hello world" + def prepend(arg) + self[0, 0] = arg + self + end end diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 2a52d53b3..7e87b3db4 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -23,10 +23,11 @@ static mrb_value mrb_str_setbyte(mrb_state *mrb, mrb_value str) { mrb_int pos, byte; - long len = RSTRING_LEN(str); + long len; mrb_get_args(mrb, "ii", &pos, &byte); + len = RSTRING_LEN(str); if (pos < -len || len <= pos) mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); if (pos < 0) @@ -55,8 +56,14 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str) mrb_int beg; len = RSTRING_LEN(str); - if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { + switch (mrb_range_beg_len(mrb, a1, &beg, &len, len, TRUE)) { + case 0: /* not range */ + break; + case 1: /* range */ return mrb_str_substr(mrb, str, beg, len); + case 2: /* out of range */ + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", a1); + break; } return mrb_nil_value(); } @@ -307,13 +314,14 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) int ai; mrb_int len; mrb_value arg; - char *p = RSTRING_PTR(self), *t; - char *e = p + RSTRING_LEN(self); + char *b = RSTRING_PTR(self); + char *p = b, *t; + char *e = b + RSTRING_LEN(self); mrb_get_args(mrb, "&", &blk); result = mrb_ary_new(mrb); - + ai = mrb_gc_arena_save(mrb); if (!mrb_nil_p(blk)) { while (p < e) { t = p; @@ -322,11 +330,17 @@ mrb_str_lines(mrb_state *mrb, mrb_value self) len = (mrb_int) (p - t); arg = mrb_str_new(mrb, t, len); mrb_yield_argv(mrb, blk, 1, &arg); + mrb_gc_arena_restore(mrb, ai); + if (b != RSTRING_PTR(self)) { + ptrdiff_t diff = p - b; + b = RSTRING_PTR(self); + p = b + diff; + } + e = b + RSTRING_LEN(self); } return self; } while (p < e) { - ai = mrb_gc_arena_save(mrb); t = p; while (p < e && *p != '\n') p++; if (*p == '\n') p++; @@ -429,44 +443,6 @@ mrb_str_succ(mrb_state *mrb, mrb_value self) return str; } -/* - * call-seq: - * str.prepend(other_str) -> str - * - * Prepend---Prepend the given string to <i>str</i>. - * - * a = "world" - * a.prepend("hello ") #=> "hello world" - * a #=> "hello world" - */ -static mrb_value -mrb_str_prepend(mrb_state *mrb, mrb_value self) -{ - struct RString *s1 = mrb_str_ptr(self), *s2, *temp_s; - mrb_int len; - mrb_value other, temp_str; - - mrb_get_args(mrb, "S", &other); - - mrb_str_modify(mrb, s1); - if (!mrb_string_p(other)) { - other = mrb_str_to_str(mrb, other); - } - s2 = mrb_str_ptr(other); - len = RSTR_LEN(s1) + RSTR_LEN(s2); - temp_str = mrb_str_new(mrb, NULL, RSTR_LEN(s1)); - temp_s = mrb_str_ptr(temp_str); - memcpy(RSTR_PTR(temp_s), RSTR_PTR(s1), RSTR_LEN(s1)); - if (RSTRING_CAPA(self) < len) { - mrb_str_resize(mrb, self, len); - } - memcpy(RSTR_PTR(s1), RSTR_PTR(s2), RSTR_LEN(s2)); - memcpy(RSTR_PTR(s1) + RSTR_LEN(s2), RSTR_PTR(temp_s), RSTR_LEN(temp_s)); - RSTR_SET_LEN(s1, len); - RSTR_PTR(s1)[len] = '\0'; - return self; -} - #ifdef MRB_UTF8_STRING static const char utf8len_codepage_zero[256] = { @@ -554,7 +530,6 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) 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_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1)); 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!")); mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index a5d55a7ee..24bc859d8 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -30,6 +30,18 @@ assert('String#setbyte') do assert_equal("Hello", str1) end +assert("String#setbyte raises IndexError if arg conversion resizes String") do + $s = "01234\n" + class Tmp + def to_i + $s.chomp! '' + 95 + end + end + tmp = Tmp.new + assert_raise(IndexError) { $s.setbyte(5, tmp) } +end + assert('String#byteslice') do str1 = "hello" assert_equal("e", str1.byteslice(1)) @@ -421,6 +433,7 @@ end assert('String#ljust') do assert_equal "hello", "hello".ljust(4) assert_equal "hello ", "hello".ljust(20) + assert_equal 20, "hello".ljust(20).length assert_equal "hello123412341234123", "hello".ljust(20, '1234') assert_equal "hello", "hello".ljust(-3) end @@ -428,10 +441,55 @@ end assert('String#rjust') do assert_equal "hello", "hello".rjust(4) assert_equal " hello", "hello".rjust(20) + assert_equal 20, "hello".rjust(20).length assert_equal "123412341234123hello", "hello".rjust(20, '1234') assert_equal "hello", "hello".rjust(-3) end +if UTF8STRING + assert('String#ljust with UTF8') do + assert_equal "helloん ", "helloん".ljust(20) + assert_equal "helloó ", "helloó".ljust(34) + assert_equal 34, "helloó".ljust(34).length + assert_equal "helloんんんんんんんんんんんんんん", "hello".ljust(19, 'ん') + assert_equal "helloんんんんんんんんんんんんんんん", "hello".ljust(20, 'ん') + end + + assert('String#rjust with UTF8') do + assert_equal " helloん", "helloん".rjust(20) + assert_equal " helloó", "helloó".rjust(34) + # assert_equal 34, "helloó".rjust(34).length + assert_equal "んんんんんんんんんんんんんんhello", "hello".rjust(19, 'ん') + assert_equal "んんんんんんんんんんんんんんんhello", "hello".rjust(20, 'ん') + end + + assert('UTF8 byte counting') do + ret = ' ' + ret[-6..-1] = "helloó" + assert_equal 34, ret.length + end +end + +assert('String#ljust should not change string') do + a = "hello" + a.ljust(20) + assert_equal "hello", a +end + +assert('String#rjust should not change string') do + a = "hello" + a.rjust(20) + assert_equal "hello", a +end + +assert('String#ljust should raise on zero width padding') do + assert_raise(ArgumentError) { "foo".ljust(10, '') } +end + +assert('String#rjust should raise on zero width padding') do + assert_raise(ArgumentError) { "foo".rjust(10, '') } +end + assert('String#upto') do a = "aa" start = "aa" |
