diff options
Diffstat (limited to 'mrbgems')
| -rw-r--r-- | mrbgems/mruby-array-ext/src/array.c | 44 | ||||
| -rw-r--r-- | mrbgems/mruby-array-ext/test/array.rb | 8 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mruby/bintest/mruby.rb | 14 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-ext/mrblib/enum.rb | 26 | ||||
| -rw-r--r-- | mrbgems/mruby-enum-ext/test/enum.rb | 16 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/mrblib/hash.rb | 11 | ||||
| -rw-r--r-- | mrbgems/mruby-hash-ext/test/hash.rb | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-kernel-ext/src/kernel.c | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/mrblib/string.rb | 9 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/test/sprintf.rb | 9 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/mrblib/string.rb | 93 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 66 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/test/string.rb | 32 | ||||
| -rw-r--r-- | mrbgems/mruby-string-utf8/mrbgem.rake | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-string-utf8/src/string.c | 133 | ||||
| -rw-r--r-- | mrbgems/mruby-string-utf8/test/string.rb | 41 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/src/struct.c | 98 | ||||
| -rw-r--r-- | mrbgems/mruby-time/src/time.c | 2 |
19 files changed, 493 insertions, 124 deletions
diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index 014137e99..d69f0ac44 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -2,6 +2,7 @@ #include "mruby/value.h" #include "mruby/array.h" #include "mruby/range.h" +#include "mruby/hash.h" /* * call-seq: @@ -105,6 +106,48 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self) return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref); } +/* + * call-seq: + * ary.to_h -> Hash + * + * Returns the result of interpreting <i>aray</i> as an array of + * <tt>[key, value]</tt> paris. + * + * [[:foo, :bar], [1, 2]].to_h + * # => {:foo => :bar, 1 => 2} + */ + +static mrb_value +mrb_ary_to_h(mrb_state *mrb, mrb_value ary) +{ + mrb_int i; + mrb_value v, hash; + + hash = mrb_hash_new_capa(mrb, 0); + + for (i = 0; i < RARRAY_LEN(ary); ++i) { + v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]); + + if (mrb_nil_p(v)) { + mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)", + mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])), + mrb_fixnum_value(i) + ); + } + + if (RARRAY_LEN(v) != 2) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)", + mrb_fixnum_value(i), + mrb_fixnum_value(RARRAY_LEN(v)) + ); + } + + mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]); + } + + return hash; +} + void mrb_mruby_array_ext_gem_init(mrb_state* mrb) { @@ -114,6 +157,7 @@ mrb_mruby_array_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1)); mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1)); mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY()); + mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0)); } void diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index cb5652dde..8c919f7e0 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -285,3 +285,11 @@ assert('Array#values_at') do assert_equal ['none', nil, nil, 'red', 'green', 'purple'], a.values_at(4..6, 0...3) assert_raise(TypeError) { a.values_at 'tt' } end + +assert('Array#to_h') do + assert_equal({}, [].to_h) + assert_equal({a: 1, b:2}, [[:a, 1], [:b, 2]].to_h) + + assert_raise(TypeError) { [1].to_h } + assert_raise(ArgumentError) { [[1]].to_h } +end diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 5c9524161..dece361a5 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -258,7 +258,7 @@ check_keyword(const char *buf, const char *word) size_t len = strlen(word); /* skip preceding spaces */ - while (*p && isspace(*p)) { + while (*p && isspace((unsigned char)*p)) { p++; } /* check keyword */ @@ -268,7 +268,7 @@ check_keyword(const char *buf, const char *word) p += len; /* skip trailing spaces */ while (*p) { - if (!isspace(*p)) return 0; + if (!isspace((unsigned char)*p)) return 0; p++; } return 1; @@ -424,7 +424,7 @@ main(int argc, char **argv) else { /* no */ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ - result = mrb_any_to_s(mrb,result); + result = mrb_any_to_s(mrb, result); } p(mrb, result, 1); } diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index a453400fc..de211c1ba 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -30,3 +30,17 @@ assert '$0 value' do # one liner assert_equal '"-e"', `./bin/mruby -e 'p $0'`.chomp end + +assert '__END__', '8.6' do + script = Tempfile.new('test.rb') + + script.write <<EOS +p 'test' + __END__ = 'fin' +p __END__ +__END__ +p 'legend' +EOS + script.flush + assert_equal "\"test\"\n\"fin\"\n", `./bin/mruby #{script.path}` +end diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 5abb75d54..b13d00a84 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -669,4 +669,30 @@ module Enumerable end ary end + + ## + # call-seq: + # enum.to_h -> hash + # + # Returns the result of interpreting <i>enum</i> as a list of + # <tt>[key, value]</tt> pairs. + # + # %i[hello world].each_with_index.to_h + # # => {:hello => 0, :world => 1} + # + + def to_h + h = {} + self.each do |*v| + v = v.__svalue + raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array + raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2 + h[v[0]] = v[1] + end + h + end + + def nil.to_h + {} + end end diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb index bce9cb15d..08b553fe5 100644 --- a/mrbgems/mruby-enum-ext/test/enum.rb +++ b/mrbgems/mruby-enum-ext/test/enum.rb @@ -144,3 +144,19 @@ assert("Enumerable#zip") do assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b) assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8]) end + +assert("Enumerable#to_h") do + c = Class.new { + include Enumerable + def each + yield [1,2] + yield [3,4] + end + } + h0 = {1=>2, 3=>4} + h = c.new.to_h + assert_equal Hash, h.class + assert_equal h0, h + # mruby-enum-ext also provides nil.to_h + assert_equal Hash.new, nil.to_h +end diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index 504848a74..9da08dc3a 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -182,4 +182,15 @@ class Hash end nil end + + ## + # call-seq: + # hsh.to_h -> hsh or new_hash + # + # Returns +self+. If called on a subclass of Hash, converts + # the receiver to a Hash object. + # + def to_h + self + end end diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb index 62cfc8856..2bc5b911a 100644 --- a/mrbgems/mruby-hash-ext/test/hash.rb +++ b/mrbgems/mruby-hash-ext/test/hash.rb @@ -115,3 +115,9 @@ assert("Hash#key") do assert_nil h.key('nil') assert_equal 'nil', h.key(nil) end + +assert("Hash#to_h") do + h = { "a" => 100, "b" => 200 } + assert_equal Hash, h.to_h.class + assert_equal h, h.to_h +end diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 1ce63ac94..a6ecd72bd 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -26,7 +26,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb) { struct RClass *krn = mrb->kernel_module; - mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_NONE()); + mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2)); mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE()); } diff --git a/mrbgems/mruby-sprintf/mrblib/string.rb b/mrbgems/mruby-sprintf/mrblib/string.rb new file mode 100644 index 000000000..d7e55536a --- /dev/null +++ b/mrbgems/mruby-sprintf/mrblib/string.rb @@ -0,0 +1,9 @@ +class String + def %(args) + if args.is_a? Array + sprintf(self, *args) + else + sprintf(self, args) + end + end +end diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb index 52e94fb83..7007df1fa 100644 --- a/mrbgems/mruby-sprintf/test/sprintf.rb +++ b/mrbgems/mruby-sprintf/test/sprintf.rb @@ -1,3 +1,8 @@ -## -# Kernel#sprintf Kernel#format Test +#assert('Kernel.sprintf') do +#end +assert('String#%') do + assert_equal "one=1", "one=%d" % 1 + assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ] + assert_equal "123 < 456", "%{num} < %<str>s" % { num: 123, str: "456" } +end diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 45c631b94..1cfb7e2f5 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -1,4 +1,28 @@ class String + + ## + # call-seq: + # string.clear -> string + # + # Makes string empty. + # + # a = "abcde" + # a.clear #=> "" + # + def clear + self.replace("") + end + + ## + # call-seq: + # str.lstrip -> new_str + # + # Returns a copy of <i>str</i> with leading whitespace removed. See also + # <code>String#rstrip</code> and <code>String#strip</code>. + # + # " hello ".lstrip #=> "hello " + # "hello".lstrip #=> "hello" + # def lstrip a = 0 z = self.size - 1 @@ -6,6 +30,16 @@ class String (z >= 0) ? self[a..z] : "" end + ## + # call-seq: + # str.rstrip -> new_str + # + # Returns a copy of <i>str</i> with trailing whitespace removed. See also + # <code>String#lstrip</code> and <code>String#strip</code>. + # + # " hello ".rstrip #=> " hello" + # "hello".rstrip #=> "hello" + # def rstrip a = 0 z = self.size - 1 @@ -13,6 +47,15 @@ class String (z >= 0) ? self[a..z] : "" end + ## + # call-seq: + # str.strip -> new_str + # + # Returns a copy of <i>str</i> with leading and trailing whitespace removed. + # + # " hello ".strip #=> "hello" + # "\tgoodbye\r\n".strip #=> "goodbye" + # def strip a = 0 z = self.size - 1 @@ -21,31 +64,61 @@ class String (z >= 0) ? self[a..z] : "" end + ## + # call-seq: + # str.lstrip! -> self or nil + # + # Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no + # change was made. See also <code>String#rstrip!</code> and + # <code>String#strip!</code>. + # + # " hello ".lstrip #=> "hello " + # "hello".lstrip! #=> nil + # def lstrip! s = self.lstrip (s == self) ? nil : self.replace(s) end + ## + # call-seq: + # str.rstrip! -> self or nil + # + # Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if + # no change was made. See also <code>String#lstrip!</code> and + # <code>String#strip!</code>. + # + # " hello ".rstrip #=> " hello" + # "hello".rstrip! #=> nil + # def rstrip! s = self.rstrip (s == self) ? nil : self.replace(s) end + ## + # call-seq: + # str.strip! -> str or nil + # + # Removes leading and trailing whitespace from <i>str</i>. Returns + # <code>nil</code> if <i>str</i> was not altered. + # def strip! 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 -# + ## + # 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.to_str.downcase rescue NoMethodError diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 2c0a406ad..f04f12c4b 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -1,6 +1,8 @@ #include <ctype.h> #include <string.h> #include "mruby.h" +#include "mruby/array.h" +#include "mruby/class.h" #include "mruby/string.h" static mrb_value @@ -175,6 +177,68 @@ mrb_str_oct(mrb_state *mrb, mrb_value self) return mrb_str_to_inum(mrb, self, 8, FALSE); } +/* + * call-seq: + * string.chr -> string + * + * Returns a one-character string at the beginning of the string. + * + * a = "abcde" + * a.chr #=> "a" + */ +static mrb_value +mrb_str_chr(mrb_state *mrb, mrb_value self) +{ + return mrb_str_substr(mrb, self, 0, 1); +} + +/* + * call-seq: + * string.lines -> array of string + * + * Returns strings per line; + * + * a = "abc\ndef" + * a.lines #=> ["abc\n", "def"] + */ +static mrb_value +mrb_str_lines(mrb_state *mrb, mrb_value self) +{ + mrb_value result; + mrb_value blk; + int ai; + mrb_int len; + mrb_value arg; + char *p = RSTRING_PTR(self), *t; + char *e = p + RSTRING_LEN(self); + + mrb_get_args(mrb, "&", &blk); + + result = mrb_ary_new(mrb); + + if (!mrb_nil_p(blk)) { + while (p < e) { + t = p; + while (p < e && *p != '\n') p++; + if (*p == '\n') p++; + len = (mrb_int) (p - t); + arg = mrb_str_new(mrb, t, len); + mrb_yield_argv(mrb, blk, 1, &arg); + } + return self; + } + while (p < e) { + ai = mrb_gc_arena_save(mrb); + t = p; + while (p < e && *p != '\n') p++; + if (*p == '\n') p++; + len = (mrb_int) (p - t); + mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len)); + mrb_gc_arena_restore(mrb, ai); + } + return result; +} + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -190,6 +254,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, MRB_ARGS_REST()); mrb_define_method(mrb, s, "hex", mrb_str_hex, MRB_ARGS_NONE()); 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()); } void diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 01712a607..72c919b35 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -161,3 +161,35 @@ assert('String#oct') do assert_equal 8, "010".oct assert_equal (-8), "-10".oct end + +assert('String#chr') do + assert_equal "a", "abcde".chr +end + +assert('String#lines') do + assert_equal ["Hel\n", "lo\n", "World!"], "Hel\nlo\nWorld!".lines + assert_equal ["Hel\n", "lo\n", "World!\n"], "Hel\nlo\nWorld!\n".lines + assert_equal ["\n", "\n", "\n"], "\n\n\n".lines + assert_equal [], "".lines +end + +assert('String#clear') do + # embed string + s = "foo" + assert_equal("", s.clear) + assert_equal("", s) + + # not embed string and not shared string + s = "foo" * 100 + a = s + assert_equal("", s.clear) + assert_equal("", s) + assert_equal("", a) + + # shared string + s = "foo" * 100 + a = s[10, 90] # create shared string + assert_equal("", s.clear) # clear + assert_equal("", s) # s is cleared + assert_not_equal("", a) # a should not be affected +end diff --git a/mrbgems/mruby-string-utf8/mrbgem.rake b/mrbgems/mruby-string-utf8/mrbgem.rake index 86d0a6da3..7642d4e07 100644 --- a/mrbgems/mruby-string-utf8/mrbgem.rake +++ b/mrbgems/mruby-string-utf8/mrbgem.rake @@ -2,4 +2,5 @@ MRuby::Gem::Specification.new('mruby-string-utf8') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' spec.summary = 'UTF-8 support in String class' + spec.add_dependency('mruby-string-ext', :core => 'mruby-string-ext') end diff --git a/mrbgems/mruby-string-utf8/src/string.c b/mrbgems/mruby-string-utf8/src/string.c index edda491fc..874fa8dbb 100644 --- a/mrbgems/mruby-string-utf8/src/string.c +++ b/mrbgems/mruby-string-utf8/src/string.c @@ -1,17 +1,12 @@ #include "mruby.h" #include "mruby/array.h" +#include "mruby/class.h" #include "mruby/string.h" #include "mruby/range.h" #include "mruby/re.h" #include <ctype.h> #include <string.h> -#define STR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED) -#define STR_EMBED_LEN(s)\ - (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) -#define STR_PTR(s) ((STR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr) -#define STR_LEN(s) ((STR_EMBED_P(s)) ? STR_EMBED_LEN(s) : (mrb_int)(s)->as.heap.len) - static const char utf8len_codepage[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -36,27 +31,6 @@ static char utf8len_codepage_zero[256] = 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, }; -static const char isspacetable[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define ascii_isspace(c) isspacetable[(unsigned char)(c)] - static mrb_int utf8code(unsigned char* p) { @@ -127,9 +101,7 @@ mrb_utf8_strlen(mrb_value str, mrb_int len) static mrb_value mrb_str_size(mrb_state *mrb, mrb_value str) { - mrb_int size = mrb_utf8_strlen(str, -1); - - return mrb_fixnum_value(size); + return mrb_fixnum_value(mrb_utf8_strlen(str, -1)); } #define RSTRING_LEN_UTF8(s) mrb_utf8_strlen(s, -1) @@ -161,10 +133,10 @@ mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mr qstable[i] = m + 1; for (; x < xe; ++x) qstable[*x] = xe - x; - /* Searching */ + /* Searching */ for (; y + m <= ys + n; y += *(qstable + y[m])) { if (*xs == *y && memcmp(xs, y, m) == 0) - return y - ys; + return y - ys; } return -1; } @@ -272,17 +244,17 @@ str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) mrb_int len = RSTRING_LEN(sub); /* substring longer than string */ - if (STR_LEN(ps) < len) return -1; - if (STR_LEN(ps) - pos < len) { - pos = STR_LEN(ps) - len; + if (RSTR_LEN(ps) < len) return -1; + if (RSTR_LEN(ps) - pos < len) { + pos = RSTR_LEN(ps) - len; } - sbeg = STR_PTR(ps); - s = STR_PTR(ps) + pos; + sbeg = RSTR_PTR(ps); + s = RSTR_PTR(ps) + pos; t = RSTRING_PTR(sub); if (len) { while (sbeg <= s) { if (memcmp(s, t, len) == 0) { - return s - STR_PTR(ps); + return s - RSTR_PTR(ps); } s--; } @@ -572,7 +544,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) if (mrb_string_p(spat)) { split_type = string; if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ - split_type = awk; + split_type = awk; } } else { @@ -594,7 +566,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) int ai = mrb_gc_arena_save(mrb); c = (unsigned char)*ptr++; if (skip) { - if (ascii_isspace(c)) { + if (ISSPACE(c)) { beg = ptr - bptr; } else { @@ -603,7 +575,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) if (lim_p && lim <= i) break; } } - else if (ascii_isspace(c)) { + else if (ISSPACE(c)) { mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, end-beg)); mrb_gc_arena_restore(mrb, ai); skip = 1; @@ -667,6 +639,80 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) return result; } +static mrb_value +mrb_str_chr(mrb_state *mrb, mrb_value self) +{ + return str_substr(mrb, self, 0, 1); +} + +static mrb_value +mrb_str_chars(mrb_state *mrb, mrb_value self) +{ + mrb_value result; + mrb_value blk; + int ai; + mrb_int len; + mrb_value arg; + char *p = RSTRING_PTR(self); + char *e = p + RSTRING_LEN(self); + + mrb_get_args(mrb, "&", &blk); + + result = mrb_ary_new(mrb); + + if (!mrb_nil_p(blk)) { + while (p < e) { + len = utf8len((unsigned char*) p); + arg = mrb_str_new(mrb, p, len); + mrb_yield_argv(mrb, blk, 1, &arg); + p += len; + } + return self; + } + while (p < e) { + ai = mrb_gc_arena_save(mrb); + len = utf8len((unsigned char*) p); + mrb_ary_push(mrb, result, mrb_str_new(mrb, p, len)); + mrb_gc_arena_restore(mrb, ai); + p += len; + } + return result; +} + +static mrb_value +mrb_str_codepoints(mrb_state *mrb, mrb_value self) +{ + mrb_value result; + mrb_value blk; + int ai; + mrb_int len; + mrb_value arg; + char *p = RSTRING_PTR(self); + char *e = p + RSTRING_LEN(self); + + mrb_get_args(mrb, "&", &blk); + + result = mrb_ary_new(mrb); + + if (!mrb_nil_p(blk)) { + while (p < e) { + len = utf8len((unsigned char*) p); + arg = mrb_fixnum_value(utf8code((unsigned char*) p)); + mrb_yield_argv(mrb, blk, 1, &arg); + p += len; + } + return self; + } + while (p < e) { + ai = mrb_gc_arena_save(mrb); + len = utf8len((unsigned char*) p); + mrb_ary_push(mrb, result, mrb_fixnum_value(utf8code((unsigned char*) p))); + mrb_gc_arena_restore(mrb, ai); + p += len; + } + return result; +} + void mrb_mruby_string_utf8_gem_init(mrb_state* mrb) { @@ -682,6 +728,11 @@ mrb_mruby_string_utf8_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY()); + mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE()); + mrb_define_method(mrb, s, "chars", mrb_str_chars, MRB_ARGS_NONE()); + mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_char"), mrb_intern_lit(mrb, "chars")); + mrb_define_method(mrb, s, "codepoints", mrb_str_codepoints, MRB_ARGS_NONE()); + mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_codepoint"), mrb_intern_lit(mrb, "codepoints")); mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE()); } diff --git a/mrbgems/mruby-string-utf8/test/string.rb b/mrbgems/mruby-string-utf8/test/string.rb index 1bfa8512c..5b4180037 100644 --- a/mrbgems/mruby-string-utf8/test/string.rb +++ b/mrbgems/mruby-string-utf8/test/string.rb @@ -66,3 +66,44 @@ assert('String#rindex') do assert_equal 12, str.rindex('ち') assert_equal 3, str.rindex('ち', 10) end + +assert('String#chr(utf-8)') do + assert_equal "こ", "こんにちは世界!".chr +end + +assert('String#chars') do + expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] + assert_equal expect, "こんにちは世界!".chars + s = "" + "こんにちは世界!".chars do |x| + s += x + end + assert_equal "こんにちは世界!", s +end + +assert('String#each_char') do + expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] + s = "" + "こんにちは世界!".each_char do |x| + s += x + end + assert_equal "こんにちは世界!", s +end +assert('String#codepoints') do + expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] + assert_equal expect, "こんにちは世界!".codepoints + cp = [] + "こんにちは世界!".codepoints do |x| + cp << x + end + assert_equal expect, cp +end + +assert('String#each_codepoint') do + expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] + cp = [] + "こんにちは世界!".each_codepoint do |x| + cp << x + end + assert_equal expect, cp +end diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 6894ffec9..930384806 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -4,8 +4,8 @@ ** See Copyright Notice in mruby.h */ +#include <ctype.h> #include <string.h> -#include <stdarg.h> #include "mruby.h" #include "mruby/array.h" #include "mruby/string.h" @@ -40,13 +40,7 @@ struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id) } } -mrb_value -mrb_struct_iv_get(mrb_state *mrb, mrb_value c, const char *name) -{ - return struct_ivar_get(mrb, c, mrb_intern_cstr(mrb, name)); -} - -mrb_value +static mrb_value mrb_struct_s_members(mrb_state *mrb, mrb_value klass) { mrb_value members = struct_ivar_get(mrb, klass, mrb_intern_lit(mrb, "__members__")); @@ -60,7 +54,7 @@ mrb_struct_s_members(mrb_state *mrb, mrb_value klass) return members; } -mrb_value +static mrb_value mrb_struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); @@ -109,7 +103,7 @@ mrb_struct_members_m(mrb_state *mrb, mrb_value obj) return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); } -mrb_value +static mrb_value mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) { mrb_value members, slot, *ptr, *ptr_members; @@ -149,7 +143,7 @@ static mrb_value mrb_struct_ref9(mrb_state* mrb, mrb_value obj) {return RSTRUCT_ #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) #define N_REF_FUNC numberof(ref_func) -static mrb_value (*const ref_func[])(mrb_state*, mrb_value) = { +static const mrb_func_t ref_func[] = { mrb_struct_ref0, mrb_struct_ref1, mrb_struct_ref2, @@ -162,7 +156,7 @@ static mrb_value (*const ref_func[])(mrb_state*, mrb_value) = { mrb_struct_ref9, }; -mrb_sym +static mrb_sym mrb_id_attrset(mrb_state *mrb, mrb_sym id) { const char *name; @@ -185,8 +179,7 @@ static mrb_value mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) { const char *name; - size_t i, len; - mrb_int slen; + mrb_int i, len, slen; mrb_sym mid; mrb_value members, slot, *ptr, *ptr_members; @@ -217,19 +210,18 @@ mrb_struct_set_m(mrb_state *mrb, mrb_value obj) return mrb_struct_set(mrb, obj, val); } -#define is_notop_id(id) (id) /* ((id)>tLAST_TOKEN) */ -#define is_local_id(id) (is_notop_id(id)) /* &&((id)&ID_SCOPE_MASK)==ID_LOCAL) */ -int -mrb_is_local_id(mrb_sym id) +static mrb_bool +is_local_id(mrb_state *mrb, const char *name) { - return is_local_id(id); + if (!name) return FALSE; + return !ISUPPER(name[0]); } -#define is_const_id(id) (is_notop_id(id)) /* &&((id)&ID_SCOPE_MASK)==ID_CONST) */ -int -mrb_is_const_id(mrb_sym id) +static mrb_bool +is_const_id(mrb_state *mrb, const char *name) { - return is_const_id(id); + if (!name) return FALSE; + return ISUPPER(name[0]); } static mrb_value @@ -248,7 +240,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_obj_to_sym(mrb, name); - if (!mrb_is_const_id(id)) { + if (!is_const_id(mrb, mrb_sym2name_len(mrb, id, NULL))) { mrb_name_error(mrb, id, "identifier %S needs to be constant", name); } if (mrb_const_defined_at(mrb, klass, id)) { @@ -270,7 +262,9 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k ai = mrb_gc_arena_save(mrb); for (i=0; i< len; i++) { mrb_sym id = mrb_symbol(ptr_members[i]); - if (mrb_is_local_id(id) || mrb_is_const_id(id)) { + const char *name = mrb_sym2name_len(mrb, id, NULL); + + if (is_local_id(mrb, name) || is_const_id(mrb, name)) { if (i < N_REF_FUNC) { mrb_define_method_id(mrb, c, id, ref_func[i], MRB_ARGS_NONE()); } @@ -284,27 +278,6 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k return nstr; } -mrb_value -mrb_struct_define(mrb_state *mrb, const char *name, ...) -{ - va_list ar; - mrb_value nm, ary; - char *mem; - - if (!name) nm = mrb_nil_value(); - else nm = mrb_str_new_cstr(mrb, name); - ary = mrb_ary_new(mrb); - - va_start(ar, name); - while ((mem = va_arg(ar, char*)) != 0) { - mrb_sym slot = mrb_intern_cstr(mrb, mem); - mrb_ary_push(mrb, ary, mrb_symbol_value(slot)); - } - va_end(ar); - - return make_struct(mrb, nm, ary, struct_class(mrb)); -} - /* 15.2.18.3.1 */ /* * call-seq: @@ -344,7 +317,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) { mrb_value name, rest; mrb_value *pargv; - int argcnt; + mrb_int argcnt; mrb_int i; mrb_value b, st; mrb_sym id; @@ -391,7 +364,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) return st; } -static int +static mrb_int num_members(mrb_state *mrb, struct RClass *klass) { mrb_value members; @@ -407,10 +380,10 @@ num_members(mrb_state *mrb, struct RClass *klass) /* */ static mrb_value -mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) +mrb_struct_initialize_withArg(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); - int i, n; + mrb_int i, n; n = num_members(mrb, klass); if (n < argc) { @@ -436,14 +409,8 @@ mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value return mrb_struct_initialize_withArg(mrb, argc, argv, self); } -mrb_value -mrb_struct_initialize(mrb_state *mrb, mrb_value self, mrb_value values) -{ - return mrb_struct_initialize_withArg(mrb, RARRAY_LEN(values), RARRAY_PTR(values), self); -} - static mrb_value -inspect_struct(mrb_state *mrb, mrb_value s, int recur) +inspect_struct(mrb_state *mrb, mrb_value s, mrb_bool recur) { const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); mrb_value members, str = mrb_str_new_lit(mrb, "#<struct "); @@ -464,6 +431,8 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur) for (i=0; i<len; i++) { mrb_value slot; mrb_sym id; + const char *name; + mrb_int len; if (i > 0) { mrb_str_cat_lit(mrb, str, ", "); @@ -473,11 +442,8 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur) } slot = ptr_members[i]; id = mrb_symbol(slot); - if (mrb_is_local_id(id) || mrb_is_const_id(id)) { - const char *name; - mrb_int len; - - name = mrb_sym2name_len(mrb, id, &len); + name = mrb_sym2name_len(mrb, id, &len); + if (is_local_id(mrb, name) || is_const_id(mrb, name)) { mrb_str_append(mrb, str, mrb_str_new(mrb, name, len)); } else { @@ -501,12 +467,12 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur) static mrb_value mrb_struct_inspect(mrb_state *mrb, mrb_value s) { - return inspect_struct(mrb, s, 0); + return inspect_struct(mrb, s, FALSE); } /* 15.2.18.4.9 */ /* :nodoc: */ -mrb_value +static mrb_value mrb_struct_init_copy(mrb_state *mrb, mrb_value copy) { mrb_value s; @@ -584,7 +550,7 @@ struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i) * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ -mrb_value +static mrb_value mrb_struct_aref(mrb_state *mrb, mrb_value s) { mrb_value idx; @@ -651,7 +617,7 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) * joe.zip #=> "90210" */ -mrb_value +static mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { mrb_int i; diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 3f8ffabef..410b36173 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -713,7 +713,7 @@ mrb_mruby_time_gem_init(mrb_state* mrb) tc = mrb_define_class(mrb, "Time", mrb->object_class); MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA); mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable")); - mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ANY()); /* 15.2.19.6.1 */ + mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); /* 15.2.19.6.1 */ mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.2 */ mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */ mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, MRB_ARGS_ARG(1,6));/* 15.2.19.6.4 */ |
