diff options
-rw-r--r-- | Changes | 7 | ||||
-rw-r--r-- | mmap.c | 162 | ||||
-rw-r--r-- | tests/mmapt.rb | 37 |
3 files changed, 147 insertions, 59 deletions
@@ -17,3 +17,10 @@ * corrected strip! * corrected mm_bang_i (reverse!, etc) * added a small test (make test) + +-- 0.1.5 + +* added str[/a(a)/, 1] for 1.7.1 +* corrected mm_aset (mm_update(str, ...)) +* corrected ==, ===, eql? +* corrected mm_sub_bang, mm_gsub_bang (to_str)
\ No newline at end of file @@ -53,6 +53,8 @@ mm_free(t_mm) if (t_mm->path != (char *)-1) { if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE && truncate(t_mm->path, t_mm->real) == -1) { + free(t_mm->path); + free(t_mm); rb_raise(rb_eTypeError, "truncate"); } free(t_mm->path); @@ -118,19 +120,28 @@ mm_str(obj, modify) VALUE ret; GetMmap(obj, t_mm, modify & ~MM_ORIGIN); +#if RUBY_VERSION_CODE >= 171 + ret = rb_obj_alloc(rb_cString); + if (rb_obj_tainted(obj)) { + OBJ_TAINT(ret); + } +#else if (rb_obj_tainted(obj)) { ret = rb_tainted_str_new2(""); } else { ret = rb_str_new2(""); } +#endif if (modify & MM_MODIFY) { if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap"); if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify mmap"); } if (t_mm->frozen & MM_FROZEN) ret = rb_obj_freeze(ret); +#if RUBY_VERSION_CODE < 171 free(RSTRING(ret)->ptr); +#endif RSTRING(ret)->ptr = t_mm->addr; RSTRING(ret)->len = t_mm->real; if (modify & MM_ORIGIN) @@ -181,7 +192,7 @@ mm_i_options(arg, obj) } static VALUE -mm_map(argc, argv, obj) +mm_s_new(argc, argv, obj) VALUE obj, *argv; int argc; { @@ -406,7 +417,7 @@ mm_mprotect(obj, a) if ((pmode & PROT_WRITE) && (t_mm->frozen & MM_FROZEN)) rb_error_frozen("mmap"); if ((ret = mprotect(t_mm->addr, t_mm->len, pmode)) != 0) { - rb_raise(rb_eArgError, "msync(%d)", ret); + rb_raise(rb_eArgError, "mprotect(%d)", ret); } t_mm->pmode = pmode; if (pmode & PROT_READ) { @@ -439,22 +450,20 @@ mm_madvise(obj, a) return Qnil; } -#define StringMmap(b, bp, bl) \ - do { \ - if (TYPE(b) == T_DATA && rb_obj_is_kind_of(b, mm_cMap)) { \ - mm_mmap *b_mm; \ - \ - GetMmap(b, b_mm, 0); \ - bp = b_mm->addr; \ - bl = b_mm->real; \ - } \ - else { \ - if (TYPE(b) != T_STRING) b = rb_str_to_str(b); \ - bp = RSTRING(b)->ptr; \ - bl = RSTRING(b)->len; \ - } \ - } while (0); - +#define StringMmap(b, bp, bl) \ +do { \ + if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \ + mm_mmap *b_mm; \ + GetMmap(b, b_mm, 0); \ + bp = b_mm->addr; \ + bl = b_mm->real; \ + } \ + else { \ + if (TYPE(b) != T_STRING) b = rb_str_to_str(b); \ + bp = RSTRING(b)->ptr; \ + bl = RSTRING(b)->len; \ + } \ +} while (0); static void mm_update(str, beg, len, val) @@ -512,7 +521,7 @@ mm_match(x, y) long start; x = mm_str(x, MM_ORIGIN); - if (TYPE(y) == T_DATA && rb_obj_is_kind_of(y, mm_cMap)) { + if (TYPE(y) == T_DATA && RDATA(y)->dfree == (RUBY_DATA_FUNC)mm_free) { y = mm_to_str(y); } switch (TYPE(y)) { @@ -592,7 +601,7 @@ mm_sub_bang(argc, argv, obj) iter = 1; } else if (argc == 2) { - repl = rb_obj_as_string(argv[1]);; + repl = rb_str_to_str(argv[1]); if (OBJ_TAINTED(repl)) tainted = 1; } else { @@ -634,7 +643,7 @@ mm_sub_bang(argc, argv, obj) } memcpy(RSTRING(str)->ptr + start, RSTRING(repl)->ptr, RSTRING(repl)->len); - RSTRING(str)->len += RSTRING(repl)->len - plen; + t_mm->real += RSTRING(repl)->len - plen; if (tainted) OBJ_TAINT(obj); res = obj; @@ -661,7 +670,7 @@ mm_gsub_bang(argc, argv, obj) iter = 1; } else if (argc == 2) { - repl = rb_obj_as_string(argv[1]); + repl = rb_str_to_str(argv[1]); if (OBJ_TAINTED(repl)) tainted = 1; } else { @@ -727,6 +736,39 @@ mm_gsub_bang(argc, argv, obj) static VALUE mm_index __((int, VALUE *, VALUE)); +#if RUBY_VERSION_CODE >= 171 + +static VALUE +mm_subpat_set(obj, re, offset, val) + VALUE obj, re; + int offset; + VALUE val; +{ + VALUE str, match; + int start, end, len; + mm_mmap *t_mm; + + str = mm_str(obj, MM_MODIFY | MM_ORIGIN); + if (rb_reg_search(re, str, 0, 0) < 0) { + rb_raise(rb_eIndexError, "regexp not matched"); + } + match = rb_backref_get(); + if (offset >= RMATCH(match)->regs->num_regs) { + rb_raise(rb_eIndexError, "index %d out of regexp", offset); + } + + start = RMATCH(match)->BEG(offset); + if (start == -1) { + rb_raise(rb_eIndexError, "regexp group %d not matched", offset); + } + end = RMATCH(match)->END(offset); + len = end - start; + GetMmap(str, t_mm, MM_MODIFY); + mm_update(t_mm, start, len, val); +} + +#endif + static VALUE mm_aset(str, indx, val) VALUE str; @@ -759,18 +801,22 @@ mm_aset(str, indx, val) return val; case T_REGEXP: +#if RUBY_VERSION_CODE >= 171 + mm_subpat_set(str, 0, indx, val); +#else { VALUE args[2]; args[0] = indx; args[1] = val; mm_sub_bang(2, args, str); } +#endif return val; case T_STRING: beg = mm_index(1, &indx, str); if (beg != -1) { - mm_update(str, beg, RSTRING(indx)->len, val); + mm_update(t_mm, beg, RSTRING(indx)->len, val); } return val; @@ -800,10 +846,17 @@ mm_aset_m(argc, argv, str) if (argc == 3) { long beg, len; - if (TYPE(argv[2]) != T_STRING) argv[2] = rb_str_to_str(argv[2]); - beg = NUM2INT(argv[0]); - len = NUM2INT(argv[1]); - mm_update(t_mm, beg, len, argv[2]); +#if RUBY_VERSION_CODE >= 171 + if (TYPE(argv[0]) == T_REGEXP) { + mm_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]); + } + else +#endif + { + beg = NUM2INT(argv[0]); + len = NUM2INT(argv[1]); + mm_update(t_mm, beg, len, argv[2]); + } return argv[2]; } if (argc != 2) { @@ -997,7 +1050,7 @@ mm_strip_bang(str) VALUE str; { VALUE l = mm_lstrip_bang(str); - VALUE r = mm_str_rstrip_bang(str); + VALUE r = mm_rstrip_bang(str); if (NIL_P(l) && NIL_P(r)) return Qnil; return str; @@ -1005,16 +1058,16 @@ mm_strip_bang(str) #endif -#define MmapStr(b, recycle) \ -do { \ - recycle = 0; \ - if (TYPE(b) == T_DATA && rb_obj_is_kind_of(b, mm_cMap) == Qtrue) { \ - recycle = 1; \ - b = mm_str(b, MM_ORIGIN); \ - } \ - else { \ - b = rb_str_to_str(b); \ - } \ +#define MmapStr(b, recycle) \ +do { \ + recycle = 0; \ + if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \ + recycle = 1; \ + b = mm_str(b, MM_ORIGIN); \ + } \ + else { \ + b = rb_str_to_str(b); \ + } \ } while (0); @@ -1057,13 +1110,34 @@ mm_equal(a, b) VALUE a, b; { VALUE result; - int recycle = 0; + if (a == b) return Qtrue; + if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free) + return Qfalse; + a = mm_str(a, MM_ORIGIN); - MmapStr(b, recycle); + b = mm_str(b, MM_ORIGIN); result = rb_funcall2(a, rb_intern("=="), 1, &b); rb_gc_force_recycle(a); - if (recycle) rb_gc_force_recycle(b); + rb_gc_force_recycle(b); + return result; +} + +static VALUE +mm_eql(a, b) + VALUE a, b; +{ + VALUE result; + + if (a == b) return Qtrue; + if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free) + return Qfalse; + + a = mm_str(a, MM_ORIGIN); + b = mm_str(b, MM_ORIGIN); + result = rb_funcall2(a, rb_intern("eql?"), 1, &b); + rb_gc_force_recycle(a); + rb_gc_force_recycle(b); return result; } @@ -1468,7 +1542,7 @@ Init_mmap() rb_include_module(mm_cMap, rb_mComparable); rb_include_module(mm_cMap, rb_mEnumerable); - rb_define_singleton_method(mm_cMap, "new", mm_map, -1); + rb_define_singleton_method(mm_cMap, "new", mm_s_new, -1); rb_define_singleton_method(mm_cMap, "mlockall", mm_mlockall, 1); rb_define_singleton_method(mm_cMap, "lockall", mm_mlockall, 1); rb_define_singleton_method(mm_cMap, "munlockall", mm_munlockall, 0); @@ -1495,7 +1569,7 @@ Init_mmap() rb_define_method(mm_cMap, "<=>", mm_cmp, 1); rb_define_method(mm_cMap, "==", mm_equal, 1); rb_define_method(mm_cMap, "===", mm_equal, 1); - rb_define_method(mm_cMap, "eql?", mm_equal, 1); + rb_define_method(mm_cMap, "eql?", mm_eql, 1); rb_define_method(mm_cMap, "hash", mm_hash, 0); #if RUBY_VERSION_CODE >= 171 rb_define_method(mm_cMap, "casecmp", mm_casecmp, 1); @@ -1524,7 +1598,7 @@ Init_mmap() rb_define_method(mm_cMap, "to_i", mm_undefined, -1); rb_define_method(mm_cMap, "to_f", mm_undefined, -1); - rb_define_method(mm_cMap, "to_s", mm_undefined, 0); + rb_define_method(mm_cMap, "to_s", rb_any_to_s, 0); rb_define_method(mm_cMap, "to_str", mm_to_str, 0); rb_define_method(mm_cMap, "inspect", mm_inspect, 0); rb_define_method(mm_cMap, "dump", mm_undefined, -1); diff --git a/tests/mmapt.rb b/tests/mmapt.rb index 1c515a6..15fe5e4 100644 --- a/tests/mmapt.rb +++ b/tests/mmapt.rb @@ -1,6 +1,7 @@ #!/usr/bin/ruby $LOAD_PATH.unshift *%w{.. . tests} require 'mmap' +require 'ftools' require 'runit/testcase' require 'runit/cui/testrunner' @@ -9,15 +10,10 @@ $mmap, $str = nil, nil class TestMmap < RUNIT::TestCase def internal_init $mmap.unmap if $mmap - mmap = open("tmp/mmap", "w") - $str = <<-EOT - - some randomly generated text - - well, in reality not really, really random - EOT - mmap.print $str - mmap.close + file = "mmap.c" + file = "../mmap.c" unless File.exist? file + File.syscopy file, "tmp/mmap" + $str = File.readlines("tmp/mmap", nil)[0] assert_kind_of(Mmap, $mmap = Mmap.new("tmp/mmap", "rw"), "<open>") end @@ -140,18 +136,18 @@ class TestMmap < RUNIT::TestCase end def test_04_reg - assert_equal($mmap.scan(/random/), $str.scan(/random/), "<scan>") - assert_equal($mmap.index("really"), $str.index("really"), "<index>") - assert_equal($mmap.rindex("really"), $str.rindex("really"), "<rindex>") + assert_equal($mmap.scan(/include/), $str.scan(/include/), "<scan>") + assert_equal($mmap.index("rb_raise"), $str.index("rb_raise"), "<index>") + assert_equal($mmap.rindex("rb_raise"), $str.rindex("rb_raise"), "<rindex>") ('a' .. 'z').each do |i| assert_equal($mmap.index(i), $str.index(i), "<index>") assert_equal($mmap.rindex(i), $str.rindex(i), "<rindex>") end - assert_equal($mmap.sub!(/real/, 'XXXX'), $str.sub!(/real/, 'XXXX'), "<sub!>") + $mmap.sub!(/GetMmap/, 'XXXX'); $str.sub!(/GetMmap/, 'XXXX') assert_equal($mmap.to_str, $str, "<after sub!>") - assert_equal($mmap.gsub!(/real/, 'XXXX'), $str.gsub!(/real/, 'XXXX'), "<sub!>") + $mmap.gsub!(/GetMmap/, 'XXXX'); $str.gsub!(/GetMmap/, 'XXXX') assert_equal($mmap.to_str, $str, "<after gsub!>") - assert_equal($mmap.gsub!(/YYYY/, 'XXXX'), $str.gsub!(/YYYY/, 'XXXX'), "<sub!>") + $mmap.gsub!(/YYYY/, 'XXXX'); $str.gsub!(/YYYY/, 'XXXX') assert_equal($mmap.to_str, $str, "<after gsub!>") assert_equal($mmap.split(/\w+/), $str.split(/\w+/), "<split>") assert_equal($mmap.split(/\W+/), $str.split(/\W+/), "<split>") @@ -176,10 +172,21 @@ class TestMmap < RUNIT::TestCase internal_modify(:strip!) internal_modify(:chop!) internal_modify(:chomp!) + internal_modify(:squeeze!) internal_modify(:tr!, 'abcdefghi', '123456789') internal_modify(:tr_s!, 'jklmnopqr', '123456789') + internal_modify(:delete!, 'A-Z') end + def test_06_iterate + internal_init + mmap = []; $mmap.each {|l| mmap << l} + str = []; $str.each {|l| str << l} + assert_equal(mmap, str, "<each>") + mmap = []; $mmap.each_byte {|l| mmap << l} + str = []; $str.each_byte {|l| str << l} + assert_equal(mmap, str, "<each_byte>") + end end |