diff options
-rw-r--r-- | mmap.c | 132 | ||||
-rw-r--r-- | tests/mmapt.rb | 167 | ||||
-rw-r--r-- | tmp/mmap | 1886 |
3 files changed, 237 insertions, 1948 deletions
@@ -1,5 +1,6 @@ #include <ruby.h> #include <fcntl.h> +#include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -7,12 +8,19 @@ #include <rubyio.h> #include <intern.h> #include "version.h" +#include <re.h> -#if RUBY_VERSION_CODE < 180 -#define StringValue(x) do { \ - if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \ +#ifndef StringValue +#define StringValue(x) do { \ + if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \ } while (0) +#endif + +#ifndef StringValuePtr #define StringValuePtr(x) STR2CSTR(x) +#endif + +#ifndef SafeStringValue #define SafeStringValue(x) Check_SafeStr(x) #endif @@ -27,8 +35,6 @@ #endif #endif -#include <re.h> - #define BEG(no) regs->beg[no] #define END(no) regs->end[no] @@ -67,18 +73,10 @@ typedef struct { int advice, flag; size_t len, real, incr; off_t offset; - VALUE io; char *path; } mm_mmap; static void -mm_mark(t_mm) - mm_mmap *t_mm; -{ - rb_gc_mark(t_mm->io); -} - -static void mm_free(t_mm) mm_mmap *t_mm; { @@ -154,7 +152,7 @@ mm_str(obj, modify) int modify; { mm_mmap *t_mm; - VALUE ret; + VALUE ret = Qnil; GetMmap(obj, t_mm, modify & ~MM_ORIGIN); if (modify & MM_MODIFY) { @@ -204,7 +202,7 @@ extern char *ruby_strdup(); static void mm_expandf(t_mm, len) mm_mmap *t_mm; - long len; + size_t len; { int fd; @@ -253,7 +251,7 @@ mm_expandf(t_mm, len) static void mm_realloc(t_mm, len) mm_mmap *t_mm; - long len; + size_t len; { if (t_mm->flag & MM_FROZEN) rb_error_frozen("mmap"); if (len > t_mm->len) { @@ -310,10 +308,11 @@ mm_i_options(arg, obj) t_mm->advice = NUM2INT(value); } else if (strcmp(options, "increment") == 0) { - t_mm->incr = NUM2INT(value); - if (t_mm->incr < 0) { - rb_raise(rb_eArgError, "Invalid value for increment %d", t_mm->incr); + int incr = NUM2INT(value); + if (incr < 0) { + rb_raise(rb_eArgError, "Invalid value for increment %d", incr); } + t_mm->incr = incr; } return Qnil; } @@ -327,7 +326,7 @@ mm_s_alloc(obj) VALUE res; mm_mmap *t_mm; - res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); + res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm); t_mm->incr = EXP_INCR_SIZE; return res; } @@ -343,7 +342,7 @@ mm_s_new(argc, argv, obj) int argc; { struct stat st; - int fd, smode, pmode, vscope, perm, init; + int fd, smode = 0, pmode = 0, vscope, perm, init; MMAP_RETTYPE addr; VALUE res, fname, fdv, vmode, scope, options; mm_mmap *t_mm; @@ -418,7 +417,7 @@ mm_s_new(argc, argv, obj) pmode = PROT_READ; } else if (strcmp(mode, "w") == 0) { - smode = O_WRONLY; + smode = O_RDWR | O_TRUNC; pmode = PROT_WRITE; if (!NIL_P(fdv)) { pmode |= PROT_READ; @@ -455,7 +454,7 @@ mm_s_new(argc, argv, obj) Data_Get_Struct(obj, mm_mmap, t_mm); res = obj; #else - res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); + res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm); t_mm->incr = EXP_INCR_SIZE; #endif offset = 0; @@ -508,6 +507,16 @@ mm_s_new(argc, argv, obj) rb_raise(rb_eArgError, "madvise(%d)", errno); } #endif + if (anonymous && TYPE(options) == T_HASH) { + VALUE val; + char *ptr; + + val = rb_hash_aref(options, rb_str_new2("initialize")); + if (!NIL_P(val)) { + ptr = StringValuePtr(val); + memset(addr, ptr[0], size); + } + } t_mm->addr = addr; t_mm->len = size; if (!init) t_mm->real = size; @@ -515,14 +524,14 @@ mm_s_new(argc, argv, obj) t_mm->vscope = vscope; t_mm->smode = smode; t_mm->path = (path)?ruby_strdup(path):(char *)-1; - if (!NIL_P(fdv)) { - t_mm->io = fname; - } if (smode == O_RDONLY) { res = rb_obj_freeze(res); t_mm->flag |= MM_FROZEN; } else { + if (smode == O_WRONLY) { + t_mm->flag |= MM_FIXED; + } OBJ_TAINT(res); } #if RUBY_VERSION_CODE < 172 @@ -589,22 +598,21 @@ mm_mprotect(obj, a) } if ((pmode & PROT_WRITE) && (t_mm->flag & MM_FROZEN)) rb_error_frozen("mmap"); - if ((ret = mprotect(t_mm->addr, t_mm->len, pmode)) != 0) { + if ((ret = mprotect(t_mm->addr, t_mm->len, pmode | PROT_READ)) != 0) { rb_raise(rb_eArgError, "mprotect(%d)", ret); } t_mm->pmode = pmode; if (pmode & PROT_READ) { if (pmode & PROT_WRITE) t_mm->smode = O_RDWR; else { - t_mm->smode == O_RDONLY; - if (t_mm->vscope == MAP_PRIVATE) { - obj = rb_obj_freeze(obj); - t_mm->flag |= MM_FROZEN; - } + t_mm->smode = O_RDONLY; + obj = rb_obj_freeze(obj); + t_mm->flag |= MM_FROZEN; } } else if (pmode & PROT_WRITE) { - t_mm->smode == O_WRONLY; + t_mm->flag |= MM_FIXED; + t_mm->smode = O_WRONLY; } return obj; } @@ -654,13 +662,13 @@ mm_update(str, beg, len, val) if (beg < 0) { beg += str->real; } - if (beg < 0 || str->real < beg) { + if (beg < 0 || str->real < (size_t)beg) { if (beg < 0) { beg -= str->real; } rb_raise(rb_eIndexError, "index %d out of string", beg); } - if (str->real < beg + len) { + if (str->real < (size_t)(beg + len)) { len = str->real - beg; } @@ -674,15 +682,15 @@ mm_update(str, beg, len, val) } if (vall != len) { - memmove(str->addr + beg + vall, - str->addr + beg + len, + memmove((char *)str->addr + beg + vall, + (char *)str->addr + beg + len, str->real - (beg + len)); } - if (str->real < beg && len < 0) { + if (str->real < (size_t)beg && len < 0) { MEMZERO(str->addr + str->real, char, -len); } if (vall > 0) { - memmove(str->addr+beg, valp, vall); + memmove((char *)str->addr + beg, valp, vall); } str->real += vall - len; } @@ -737,11 +745,9 @@ get_pat(pat) } static int -mm_correct_backref(t_mm) - mm_mmap *t_mm; +mm_correct_backref() { VALUE match; - struct re_registers *regs; int i, start; match = rb_backref_get(); @@ -765,7 +771,7 @@ mm_sub_bang(argc, argv, obj) VALUE *argv; VALUE obj; { - VALUE pat, repl, match, str, res; + VALUE pat, repl = Qnil, match, str, res; struct re_registers *regs; int start, iter = 0; int tainted = 0; @@ -788,7 +794,7 @@ mm_sub_bang(argc, argv, obj) pat = get_pat(argv[0]); res = Qnil; if (rb_reg_search(pat, str, 0, 0) >= 0) { - start = mm_correct_backref(t_mm); + start = mm_correct_backref(); match = rb_backref_get(); regs = RMATCH(match)->regs; if (iter) { @@ -832,7 +838,7 @@ mm_gsub_bang(argc, argv, obj) VALUE *argv; VALUE obj; { - VALUE pat, val, repl, match, str; + VALUE pat, val, repl = Qnil, match, str; struct re_registers *regs; long beg, offset; int start, iter = 0; @@ -861,7 +867,7 @@ mm_gsub_bang(argc, argv, obj) return Qnil; } while (beg >= 0) { - start = mm_correct_backref(t_mm); + start = mm_correct_backref(); match = rb_backref_get(); regs = RMATCH(match)->regs; if (iter) { @@ -911,7 +917,7 @@ static VALUE mm_index __((int, VALUE *, VALUE)); #if RUBY_VERSION_CODE >= 171 -static VALUE +static void mm_subpat_set(obj, re, offset, val) VALUE obj, re; int offset; @@ -936,7 +942,7 @@ mm_subpat_set(obj, re, offset, val) } end = RMATCH(match)->END(offset); len = end - start; - GetMmap(str, t_mm, MM_MODIFY); + GetMmap(obj, t_mm, MM_MODIFY); mm_update(t_mm, start, len, val); } @@ -947,7 +953,7 @@ mm_aset(str, indx, val) VALUE str; VALUE indx, val; { - long idx, beg; + long idx; mm_mmap *t_mm; GetMmap(str, t_mm, MM_MODIFY); @@ -958,11 +964,11 @@ mm_aset(str, indx, val) if (idx < 0) { idx += t_mm->real; } - if (idx < 0 || t_mm->real <= idx) { + if (idx < 0 || t_mm->real <= (size_t)idx) { rb_raise(rb_eIndexError, "index %d out of string", idx); } if (FIXNUM_P(val)) { - if (t_mm->real == idx) { + if (t_mm->real == (size_t)idx) { t_mm->real += 1; mm_realloc(t_mm, t_mm->real); } @@ -975,7 +981,7 @@ mm_aset(str, indx, val) case T_REGEXP: #if RUBY_VERSION_CODE >= 171 - mm_subpat_set(str, 0, indx, val); + mm_subpat_set(str, indx, 0, val); #else { VALUE args[2]; @@ -987,11 +993,15 @@ mm_aset(str, indx, val) return val; case T_STRING: - beg = mm_index(1, &indx, str); - if (beg != -1) { - mm_update(t_mm, beg, RSTRING(indx)->len, val); - } - return val; + { + VALUE res; + + res = mm_index(1, &indx, str); + if (!NIL_P(res)) { + mm_update(t_mm, NUM2LONG(res), RSTRING(indx)->len, val); + } + return val; + } default: /* check if indx is Range */ @@ -1038,6 +1048,8 @@ mm_aset_m(argc, argv, str) return mm_aset(str, argv[0], argv[1]); } +#if RUBY_VERSION_CODE >= 171 + static VALUE mm_insert(str, idx, str2) VALUE str, idx, str2; @@ -1056,6 +1068,8 @@ mm_insert(str, idx, str2) return str; } +#endif + static VALUE mm_aref_m _((int, VALUE *, VALUE)); static VALUE @@ -1188,7 +1202,7 @@ mm_lstrip_bang(str) e = t = s + t_mm->real; while (s < t && ISSPACE(*s)) s++; - if (t_mm->real != (t - s) && (t_mm->flag & MM_FIXED)) { + if (t_mm->real != (size_t)(t - s) && (t_mm->flag & MM_FIXED)) { rb_raise(rb_eTypeError, "try to change the size of a fixed map"); } t_mm->real = t - s; @@ -1213,7 +1227,7 @@ mm_rstrip_bang(str) t--; while (s <= t && ISSPACE(*t)) t--; t++; - if (t_mm->real != (t - s) && (t_mm->flag & MM_FIXED)) { + if (t_mm->real != (size_t)(t - s) && (t_mm->flag & MM_FIXED)) { rb_raise(rb_eTypeError, "try to change the size of a fixed map"); } t_mm->real = t - s; diff --git a/tests/mmapt.rb b/tests/mmapt.rb index b94358c..6b81505 100644 --- a/tests/mmapt.rb +++ b/tests/mmapt.rb @@ -8,14 +8,27 @@ $mmap, $str = nil, nil Inh = defined?(RUNIT) ? RUNIT : Test::Unit +Dir["tmp/*"].each do |f| + File.unlink(f) if FileTest.file?(f) +end + class TestMmap < Inh::TestCase - def internal_init + + def internal_read + File.readlines("tmp/mmap", nil)[0] + end + + def internal_init(io = false) $mmap.unmap if $mmap 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>") + $str = internal_read + if io + assert_kind_of(Mmap, $mmap = Mmap.new(File.new("tmp/mmap", "r+"), "rw"), "<open io>") + else + assert_kind_of(Mmap, $mmap = Mmap.new("tmp/mmap", "rw"), "<open>") + end end def test_00_init @@ -74,6 +87,12 @@ class TestMmap < Inh::TestCase end def test_02_aset + $mmap[/...../] = "change it" + $str[/...../] = "change it" + assert_equal($mmap.to_str, $str, "aset regexp") + $mmap["ge i"] = "change it" + $str["ge i"] = "change it" + assert_equal($mmap.to_str, $str, "aset regexp") max = $str.size * 2 72.times do ran1 = rand(max) @@ -193,6 +212,148 @@ class TestMmap < Inh::TestCase assert_equal(mmap, str, "<each_byte>") end + def test_07_concat + internal_init + [$mmap, $str].each {|l| l << "bc"; l << 12; l << "ab"} + assert_equal($mmap.to_str, $str, "<<") + assert_raises(TypeError) { $mmap << 456 } + end + + def test_08_extend + $mmap.extend(4096) + assert_equal($mmap.to_str, $str, "extend") + if $str.respond_to?(:insert) + 10.times do + pos = rand($mmap.size) + str = "XX" * rand(66) + $str.insert(pos, str) + $mmap.insert(pos, str) + assert_equal($mmap.to_str, $str, "insert") + end + end + end + + def test_09_msync + 3.times do |i| + [$mmap, $str].each {|l| l << "x" * 4096 } + str = internal_read + if str != $mmap.to_str + $mmap.msync + assert_equal($mmap.to_str, internal_read, "msync") + break + end + end + end + + def test_10_protect + assert_equal($mmap, $mmap.protect("w"), "protect") + assert_equal("a", $mmap[12] = "a", "affect") + $str[12] = "a" + assert_equal($mmap.to_str, $str, "protect") + assert_raises(TypeError) { $mmap << "a" } + assert_equal($mmap, $mmap.protect("r"), "protect") + assert_raises(TypeError) { $mmap[12] = "a" } + assert_raises(TypeError) { $mmap.protect("rw") } + end + + def test_11_anonymous + if defined?(Mmap::MAP_ANONYMOUS) + assert_kind_of(Mmap, $mmap = + Mmap.new(nil, "length" => 8192, "offset" => 12, + "increment" => 1024, "initialize" => " ")) + $str = " " * 8192 + 1024.times do + pos = rand(8192) + $mmap[pos] = $str[pos] = 32 + rand(64) + end + assert_equal($mmap.to_str, $str, "insert anonymous") + assert_raises(IndexError) { $mmap[12345] = "a" } + assert_raises(TypeError) { $mmap << "a" } + end + end + + def test_12_fileno + internal_init(true) + test_01_aref + $mmap[12] = "3"; $str[12] = "3" + assert_equal($mmap.to_str, $str, "insert io") + assert_equal(0, $mmap <=> $str, "cmp") + assert_raises(TypeError) { $mmap[12] = "ab" } + $mmap.freeze + if $str.respond_to?(:match) + assert_equal($str.match("rb_match_busy").offset(0), + $mmap.match("rb_match_busy").offset(0), "match") + assert_equal($str.match(/rb_../).offset(0), + $mmap.match(/rb_../).offset(0), "match") + assert_equal($str.match("rb_match_buzy"), + $mmap.match("rb_match_buzy"), "no match") + assert_equal($str =~ /rb_match_busy/, + $mmap =~ /rb_match_busy/, "match") + assert_equal($str =~ /rb_match_buzy/, + $mmap =~ /rb_match_buzy/, "no match") + end + assert_raises(TypeError) { $mmap[12] = "a" } + end + + def test_13_div + string = "azertyuiopqsdfghjklm" + assert_kind_of(Mmap, m0 = Mmap.new("tmp/aa", "a"), "new a") + File.open("tmp/bb", "w") {|f| f.puts "aaa" } + assert_kind_of(Mmap, m1 = Mmap.new("tmp/bb", "w"), "new a") + assert_equal(true, m0.empty?, "empty") + assert_equal(true, m1.empty?, "empty") + assert_equal(m0, m0 << string, "<<") + assert_equal(m1, m1 << string, "<<") + assert_equal(false, m0.empty?, "empty") + assert_equal(false, m1.empty?, "empty") + assert_equal(true, m0 == m1, "==") + if string.respond_to?(:casecmp) + assert_equal(0, m0.casecmp(string.upcase), "casecmp") + assert_equal(0, m0.casecmp(m1), "casecmp") + end + assert_equal(true, m0 === m1, "===") + assert_equal(false, m0 === string, "===") + assert_equal(true, m0.eql?(m1), ".eql?") + assert_equal(true, m1.eql?(m0), ".eql?") + assert_equal(false, m1.eql?(string), ".eql?") + assert_equal(m0.hash, m1.hash, "hash") + assert_equal(true, m0.include?("azert"), "include") + assert_equal(false, m1.include?("aqert"), "include") + i = 0 + m0.scan(/./) {|c| assert_equal(c, string[i,1], "scan"); i += 1} + assert_nil(m0.munmap, "munmap") + assert_nil(m1.munmap, "munmap") + end + + def test_14_other + if File.exist?("tmp/aa") + string = "azertyuiopqsdfghjklm" + assert_kind_of(Mmap, m0 = Mmap.new("tmp/aa", "r"), "new r") + assert_equal(string, m0.to_str, "content") + assert_raises(TypeError) { m0[0] = 12 } + assert_raises(TypeError) { m0 << 12 } + assert_nil(m0.munmap, "munmap") + if defined?(Mmap::MAP_ANONYMOUS) + assert_raises(ArgumentError) { Mmap.new(nil, "w") } + assert_kind_of(Mmap, m0 = Mmap.new(nil, 12), "new w") + assert_equal(false, m0.empty?, "empty") + assert_equal("a", m0[0] = "a", "set") + assert_raises(TypeError) { m0 << 12 } + if defined?(Mmap::MADV_DONTNEED) + assert_nil(m0.advise(Mmap::MADV_DONTNEED), "advise") + assert_equal("a", m0[0,1], "get") + end + assert_equal(m0, m0.sub!(/./) { "y" }, "sub") + assert_equal(m0, m0.gsub!(/./) { "x" }, "gsub") + assert_equal("x" * 12, m0.to_str, "retrieve") + assert_equal("ab", m0[1..2] = "ab", "range") + assert_raises(TypeError) { m0[1..2] = "abc" } + assert_raises(ArgumentError) { m0.lock } + assert_raises(ArgumentError) { Mmap::lockall(0) } + assert_nil(m0.munmap, "munmap") + end + end + end end if defined?(RUNIT) diff --git a/tmp/mmap b/tmp/mmap deleted file mode 100644 index fa04f48..0000000 --- a/tmp/mmap +++ /dev/null @@ -1,1886 +0,0 @@ -#include <ruby.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> -#include <rubyio.h> -#include <intern.h> -#include "version.h" - -#if RUBY_VERSION_CODE < 180 -#define StringValue(x) do { \ - if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \ -} while (0) -#define StringValuePtr(x) STR2CSTR(x) -#define SafeStringValue(x) Check_SafeStr(x) -#endif - -#ifndef MADV_NORMAL -#ifdef POSIX_MADV_NORMAL -#define MADV_NORMAL POSIX_MADV_NORMAL -#define MADV_RANDOM POSIX_MADV_RANDOM -#define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL -#define MADV_WILLNEED POSIX_MADV_WILLNEED -#define MADV_DONTNEED POSIX_MADV_DONTNEED -#define madvise posix_madvise -#endif -#endif - -#include <re.h> - -#define BEG(no) regs->beg[no] -#define END(no) regs->end[no] - -#ifndef MMAP_RETTYPE -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199309 -#endif /* !_POSIX_C_SOURCE */ -#ifdef _POSIX_VERSION -#if _POSIX_VERSION >= 199309 -#define MMAP_RETTYPE void * -#endif /* _POSIX_VERSION >= 199309 */ -#endif /* _POSIX_VERSION */ -#endif /* !MMAP_RETTYPE */ - -#ifndef MMAP_RETTYPE -#define MMAP_RETTYPE caddr_t -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((caddr_t)-1) -#endif /* !MAP_FAILED */ - -#ifndef MAP_ANON -#ifdef MAP_ANONYMOUS -#define MAP_ANON MAP_ANONYMOUS -#endif -#endif - -static VALUE mm_cMap; - -#define EXP_INCR_SIZE 4096 - -typedef struct { - MMAP_RETTYPE addr; - int smode, pmode, vscope; - int advice, flag; - size_t len, real, incr; - off_t offset; - VALUE io; - char *path; -} mm_mmap; - -static void -mm_mark(t_mm) - mm_mmap *t_mm; -{ - rb_gc_mark(t_mm->io); -} - -static void -mm_free(t_mm) - mm_mmap *t_mm; -{ - if (t_mm->path) { - munmap(t_mm->addr, t_mm->len); - 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); - } - } - free(t_mm); -} - -#define MM_MODIFY 1 -#define MM_ORIGIN 2 -#define MM_CHANGE (MM_MODIFY | 4) -#define MM_PROTECT 8 - -#define MM_FROZEN (1<<0) -#define MM_FIXED (1<<1) -#define MM_ANON (1<<2) -#define MM_LOCK (1<<3) - -#define GetMmap(obj, t_mm, t_modify) \ - Data_Get_Struct(obj, mm_mmap, t_mm); \ - if (!t_mm->path) { \ - rb_raise(rb_eIOError, "unmapped file"); \ - } \ - if ((t_modify & MM_MODIFY) && (t_mm->flag & MM_FROZEN)) { \ - rb_error_frozen("mmap"); \ - } - -static VALUE -mm_unmap(obj) - VALUE obj; -{ - mm_mmap *t_mm; - - GetMmap(obj, t_mm, 0); - if (t_mm->path) { - munmap(t_mm->addr, t_mm->len); - 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) { - rb_raise(rb_eTypeError, "truncate"); - } - free(t_mm->path); - } - t_mm->path = '\0'; - } - return Qnil; -} - -static VALUE -mm_freeze(obj) - VALUE obj; -{ - mm_mmap *t_mm; - rb_obj_freeze(obj); - GetMmap(obj, t_mm, 0); - t_mm->flag |= MM_FROZEN; - return obj; -} - -static VALUE -mm_str(obj, modify) - VALUE obj; - int modify; -{ - mm_mmap *t_mm; - VALUE ret; - - GetMmap(obj, t_mm, modify & ~MM_ORIGIN); - if (modify & MM_MODIFY) { - if (t_mm->flag & MM_FROZEN) rb_error_frozen("mmap"); - if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't modify mmap"); - } -#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(""); - } - free(RSTRING(ret)->ptr); -#endif - RSTRING(ret)->ptr = t_mm->addr; - RSTRING(ret)->len = t_mm->real; - if (modify & MM_ORIGIN) { -#if RUBY_VERSION_CODE >= 172 - RSTRING(ret)->aux.shared = ret; - FL_SET(ret, ELTS_SHARED); -#else - RSTRING(ret)->orig = ret; -#endif - } - if (t_mm->flag & MM_FROZEN) { - ret = rb_obj_freeze(ret); - } - return ret; -} - -static VALUE -mm_to_str(obj) - VALUE obj; -{ - return mm_str(obj, MM_ORIGIN); -} - -extern char *ruby_strdup(); - -static void -mm_expandf(t_mm, len) - mm_mmap *t_mm; - long len; -{ - int fd; - - if (t_mm->vscope == MAP_PRIVATE) { - rb_raise(rb_eTypeError, "expand for a private map"); - } - if (t_mm->flag & MM_FIXED) { - rb_raise(rb_eTypeError, "expand for a fixed map"); - } - if (!t_mm->path || t_mm->path == (char *)-1) { - rb_raise(rb_eTypeError, "expand for an anonymous map"); - } - if (munmap(t_mm->addr, t_mm->len)) { - rb_raise(rb_eArgError, "munmap failed"); - } - if ((fd = open(t_mm->path, t_mm->smode)) == -1) { - rb_raise(rb_eArgError, "Can't open %s", t_mm->path); - } - if (len > t_mm->len) { - if (lseek(fd, len - t_mm->len - 1, SEEK_END) == -1) { - rb_raise(rb_eIOError, "Can't lseek %d", len - t_mm->len - 1); - } - if (write(fd, "\000", 1) != 1) { - rb_raise(rb_eIOError, "Can't extend %s", t_mm->path); - } - } - else if (len < t_mm->len && truncate(t_mm->path, len) == -1) { - rb_raise(rb_eIOError, "Can't truncate %s", t_mm->path); - } - t_mm->addr = mmap(0, len, t_mm->pmode, t_mm->vscope, fd, t_mm->offset); - close(fd); - if (t_mm->addr == MAP_FAILED) { - rb_raise(rb_eArgError, "mmap failed"); - } -#ifdef MADV_NORMAL - if (t_mm->advice && madvise(t_mm->addr, len, t_mm->advice) == -1) { - rb_raise(rb_eArgError, "madvise(%d)", errno); - } -#endif - if ((t_mm->flag & MM_LOCK) && mlock(t_mm->addr, len) == -1) { - rb_raise(rb_eArgError, "mlock(%d)", errno); - } - t_mm->len = len; -} - -static void -mm_realloc(t_mm, len) - mm_mmap *t_mm; - long len; -{ - if (t_mm->flag & MM_FROZEN) rb_error_frozen("mmap"); - if (len > t_mm->len) { - if ((len - t_mm->len) < t_mm->incr) { - len = t_mm->len + t_mm->incr; - } - mm_expandf(t_mm, len); - } -} - -static VALUE -mm_extend(obj, a) - VALUE obj, a; -{ - mm_mmap *t_mm; - long len; - - GetMmap(obj, t_mm, MM_MODIFY); - len = NUM2LONG(a); - if (len > 0) { - mm_expandf(t_mm, t_mm->len + len); - } - return INT2NUM(t_mm->len); -} - -static VALUE -mm_i_options(arg, obj) - VALUE arg, obj; -{ - mm_mmap *t_mm; - char *options; - VALUE key, value; - - Data_Get_Struct(obj, mm_mmap, t_mm); - key = rb_ary_entry(arg, 0); - value = rb_ary_entry(arg, 1); - key = rb_obj_as_string(key); - options = StringValuePtr(key); - if (strcmp(options, "length") == 0) { - t_mm->len = NUM2INT(value); - if (t_mm->len <= 0) { - rb_raise(rb_eArgError, "Invalid value for length %d", t_mm->len); - } - t_mm->flag |= MM_FIXED; - } - else if (strcmp(options, "offset") == 0) { - t_mm->offset = NUM2INT(value); - if (t_mm->offset < 0) { - rb_raise(rb_eArgError, "Invalid value for offset %d", t_mm->offset); - } - t_mm->flag |= MM_FIXED; - } - else if (strcmp(options, "advice") == 0) { - t_mm->advice = NUM2INT(value); - } - else if (strcmp(options, "increment") == 0) { - t_mm->incr = NUM2INT(value); - if (t_mm->incr < 0) { - rb_raise(rb_eArgError, "Invalid value for increment %d", t_mm->incr); - } - } - return Qnil; -} - - -#if RUBY_VERSION_CODE >= 172 -static VALUE -mm_s_alloc(obj) - VALUE obj; -{ - VALUE res; - mm_mmap *t_mm; - - res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); - t_mm->incr = EXP_INCR_SIZE; - return res; -} -#endif - -static VALUE -#if RUBY_VERSION_CODE >= 172 -mm_init(argc, argv, obj) -#else -mm_s_new(argc, argv, obj) -#endif - VALUE obj, *argv; - int argc; -{ - struct stat st; - int fd, smode, pmode, vscope, perm, init; - MMAP_RETTYPE addr; - VALUE res, fname, fdv, vmode, scope, options; - mm_mmap *t_mm; - char *path, *mode; - size_t size = 0; - off_t offset; - int anonymous; - - options = Qnil; - if (argc > 1 && TYPE(argv[argc - 1]) == T_HASH) { - options = argv[argc - 1]; - argc--; - } - rb_scan_args(argc, argv, "12", &fname, &vmode, &scope); - vscope = 0; - path = 0; - fd = -1; - anonymous = 0; - fdv = Qnil; -#ifdef MAP_ANON - if (NIL_P(fname)) { - vscope = MAP_ANON | MAP_SHARED; - anonymous = 1; - } - else -#endif - { - if (rb_safe_level() > 0 && OBJ_TAINTED(fname)){ - rb_raise(rb_eSecurityError, "Insecure operation"); - } - rb_secure(4); - if (rb_respond_to(fname, rb_intern("fileno"))) { - fdv = rb_funcall2(fname, rb_intern("fileno"), 0, 0); - } - if (NIL_P(fdv)) { - fname = rb_str_to_str(fname); - SafeStringValue(fname); - path = StringValuePtr(fname); - } - else { - fd = NUM2INT(fdv); - if (fd < 0) { - rb_raise(rb_eArgError, "invalid file descriptor %d", fd); - } - } - if (!NIL_P(scope)) { - vscope = NUM2INT(scope); -#ifdef MAP_ANON - if (vscope & MAP_ANON) { - rb_raise(rb_eArgError, "filename specified for an anonymous map"); - } -#endif - } - } - vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope); - size = 0; - perm = 0666; - if (!anonymous) { - if (NIL_P(vmode)) { - mode = "r"; - } - else if (TYPE(vmode) == T_ARRAY && RARRAY(vmode)->len >= 2) { - VALUE tmp = RARRAY(vmode)->ptr[0]; - mode = StringValuePtr(tmp); - perm = NUM2INT(RARRAY(vmode)->ptr[1]); - } - else { - mode = StringValuePtr(vmode); - } - if (strcmp(mode, "r") == 0) { - smode = O_RDONLY; - pmode = PROT_READ; - } - else if (strcmp(mode, "w") == 0) { - smode = O_WRONLY; - pmode = PROT_WRITE; - if (!NIL_P(fdv)) { - pmode |= PROT_READ; - } - } - else if (strcmp(mode, "rw") == 0 || strcmp(mode, "wr") == 0) { - smode = O_RDWR; - pmode = PROT_READ | PROT_WRITE; - } - else if (strcmp(mode, "a") == 0) { - smode = O_RDWR | O_CREAT; - pmode = PROT_READ | PROT_WRITE; - } - else { - rb_raise(rb_eArgError, "Invalid mode %s", mode); - } - if (NIL_P(fdv)) { - if ((fd = open(path, smode, perm)) == -1) { - rb_raise(rb_eArgError, "Can't open %s", path); - } - } - if (fstat(fd, &st) == -1) { - rb_raise(rb_eArgError, "Can't stat %s", path); - } - size = st.st_size; - } - else { - fd = -1; - if (!NIL_P(vmode) && TYPE(vmode) != T_STRING) { - size = NUM2INT(vmode); - } - } -#if RUBY_VERSION_CODE >= 172 - Data_Get_Struct(obj, mm_mmap, t_mm); - res = obj; -#else - res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); - t_mm->incr = EXP_INCR_SIZE; -#endif - offset = 0; - if (options != Qnil) { - rb_iterate(rb_each, options, mm_i_options, res); - if (path && (t_mm->len + t_mm->offset) > st.st_size) { - rb_raise(rb_eArgError, "invalid value for length (%d) or offset (%d)", - t_mm->len, t_mm->offset); - } - if (t_mm->len) size = t_mm->len; - offset = t_mm->offset; - } - init = 0; - if (anonymous) { - if (size <= 0) { - rb_raise(rb_eArgError, "length not specified for an anonymous map"); - } - if (offset) { - rb_warning("Ignoring offset for an anonymous map"); - offset = 0; - } - smode = O_RDWR; - pmode = PROT_READ | PROT_WRITE; - t_mm->flag |= MM_FIXED; - } - else { - if (size == 0 && (smode & O_RDWR)) { - if (lseek(fd, t_mm->incr - 1, SEEK_END) == -1) { - rb_raise(rb_eIOError, "Can't lseek %d", t_mm->incr - 1); - } - if (write(fd, "\000", 1) != 1) { - rb_raise(rb_eIOError, "Can't extend %s", path); - } - init = 1; - size = t_mm->incr; - } - if (!NIL_P(fdv)) { - t_mm->flag |= MM_FIXED; - } - } - addr = mmap(0, size, pmode, vscope, fd, offset); - if (NIL_P(fdv) && !anonymous) { - close(fd); - } - if (addr == MAP_FAILED || !addr) { - rb_raise(rb_eArgError, "mmap failed (%d)", errno); - } -#ifdef MADV_NORMAL - if (t_mm->advice && madvise(addr, size, t_mm->advice) == -1) { - rb_raise(rb_eArgError, "madvise(%d)", errno); - } -#endif - t_mm->addr = addr; - t_mm->len = size; - if (!init) t_mm->real = size; - t_mm->pmode = pmode; - t_mm->vscope = vscope; - t_mm->smode = smode; - t_mm->path = (path)?ruby_strdup(path):(char *)-1; - if (!NIL_P(fdv)) { - t_mm->io = fname; - } - if (smode == O_RDONLY) { - res = rb_obj_freeze(res); - t_mm->flag |= MM_FROZEN; - } - else { - OBJ_TAINT(res); - } -#if RUBY_VERSION_CODE < 172 - rb_obj_call_init(res, argc, argv); -#endif - return res; -} - -#if RUBY_VERSION_CODE < 171 -static VALUE -mm_init(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return obj; -} -#endif - - -static VALUE -mm_msync(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - mm_mmap *t_mm; - VALUE oflag; - int ret; - int flag = MS_SYNC; - - if (argc) { - rb_scan_args(argc, argv, "01", &oflag); - flag = NUM2INT(oflag); - } - GetMmap(obj, t_mm, MM_MODIFY); - if ((ret = msync(t_mm->addr, t_mm->len, flag)) != 0) { - rb_raise(rb_eArgError, "msync(%d)", ret); - } - if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE) - mm_expandf(t_mm, t_mm->real); - return obj; -} - -static VALUE -mm_mprotect(obj, a) - VALUE obj, a; -{ - mm_mmap *t_mm; - int ret, pmode; - char *smode; - - GetMmap(obj, t_mm, 0); - if (TYPE(a) == T_STRING) { - smode = StringValuePtr(a); - if (strcmp(smode, "r") == 0) pmode = PROT_READ; - else if (strcmp(smode, "w") == 0) pmode = PROT_WRITE; - else if (strcmp(smode, "rw") == 0 || strcmp(smode, "wr") == 0) - pmode = PROT_READ | PROT_WRITE; - else { - rb_raise(rb_eArgError, "Invalid mode %s", smode); - } - } - else { - pmode = NUM2INT(a); - } - if ((pmode & PROT_WRITE) && (t_mm->flag & MM_FROZEN)) - rb_error_frozen("mmap"); - if ((ret = mprotect(t_mm->addr, t_mm->len, pmode)) != 0) { - rb_raise(rb_eArgError, "mprotect(%d)", ret); - } - t_mm->pmode = pmode; - if (pmode & PROT_READ) { - if (pmode & PROT_WRITE) t_mm->smode = O_RDWR; - else { - t_mm->smode == O_RDONLY; - if (t_mm->vscope == MAP_PRIVATE) { - obj = rb_obj_freeze(obj); - t_mm->flag |= MM_FROZEN; - } - } - } - else if (pmode & PROT_WRITE) { - t_mm->smode == O_WRONLY; - } - return obj; -} - -#ifdef MADV_NORMAL -static VALUE -mm_madvise(obj, a) - VALUE obj, a; -{ - mm_mmap *t_mm; - - GetMmap(obj, t_mm, 0); - if (madvise(t_mm->addr, t_mm->len, NUM2INT(a)) == -1) { - rb_raise(rb_eTypeError, "madvise(%d)", errno); - } - t_mm->advice = NUM2INT(a); - return Qnil; -} -#endif - -#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 { \ - bp = StringValuePtr(b); \ - bl = RSTRING(b)->len; \ - } \ -} while (0); - -static void -mm_update(str, beg, len, val) - mm_mmap *str; - VALUE val; - long beg; - long len; -{ - char *valp; - long vall; - - if (str->flag & MM_FROZEN) rb_error_frozen("mmap"); - if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len); - if (beg < 0) { - beg += str->real; - } - if (beg < 0 || str->real < beg) { - if (beg < 0) { - beg -= str->real; - } - rb_raise(rb_eIndexError, "index %d out of string", beg); - } - if (str->real < beg + len) { - len = str->real - beg; - } - - StringMmap(val, valp, vall); - - if ((str->flag & MM_FIXED) && vall != len) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - if (len < vall) { - mm_realloc(str, str->real + vall - len); - } - - if (vall != len) { - memmove(str->addr + beg + vall, - str->addr + beg + len, - str->real - (beg + len)); - } - if (str->real < beg && len < 0) { - MEMZERO(str->addr + str->real, char, -len); - } - if (vall > 0) { - memmove(str->addr+beg, valp, vall); - } - str->real += vall - len; -} - -static VALUE -mm_match(x, y) - VALUE x, y; -{ - VALUE reg, res; - long start; - - x = mm_str(x, MM_ORIGIN); - if (TYPE(y) == T_DATA && RDATA(y)->dfree == (RUBY_DATA_FUNC)mm_free) { - y = mm_to_str(y); - } - switch (TYPE(y)) { - case T_REGEXP: - res = rb_reg_match(y, x); - break; - - case T_STRING: - reg = rb_reg_regcomp(y); - start = rb_reg_search(reg, x, 0, 0); - if (start == -1) res = Qnil; - else res = INT2NUM(start); - break; - - default: - res = rb_funcall(y, rb_intern("=~"), 1, x); - break; - } - return res; -} - -static VALUE -get_pat(pat) - VALUE pat; -{ - switch (TYPE(pat)) { - case T_REGEXP: - break; - - case T_STRING: - pat = rb_reg_regcomp(pat); - break; - - default: - /* type failed */ - Check_Type(pat, T_REGEXP); - } - return pat; -} - -static int -mm_correct_backref(t_mm) - mm_mmap *t_mm; -{ - VALUE match; - struct re_registers *regs; - int i, start; - - match = rb_backref_get(); - if (NIL_P(match)) return 0; - if (RMATCH(match)->BEG(0) == -1) return 0; - start = RMATCH(match)->BEG(0); - RMATCH(match)->str = rb_str_new(StringValuePtr(RMATCH(match)->str) + start, - RMATCH(match)->END(0) - start); - if (OBJ_TAINTED(match)) OBJ_TAINT(RMATCH(match)->str); - for (i = 0; i < RMATCH(match)->regs->num_regs && RMATCH(match)->BEG(i) != -1; i++) { - RMATCH(match)->BEG(i) -= start; - RMATCH(match)->END(i) -= start; - } - rb_backref_set(match); - return start; -} - -static VALUE -mm_sub_bang(argc, argv, obj) - int argc; - VALUE *argv; - VALUE obj; -{ - VALUE pat, repl, match, str, res; - struct re_registers *regs; - int start, iter = 0; - int tainted = 0; - long plen; - mm_mmap *t_mm; - - if (argc == 1 && rb_block_given_p()) { - iter = 1; - } - else if (argc == 2) { - repl = rb_str_to_str(argv[1]); - if (OBJ_TAINTED(repl)) tainted = 1; - } - else { - rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc); - } - GetMmap(obj, t_mm, MM_MODIFY); - str = mm_str(obj, MM_MODIFY | MM_ORIGIN); - - pat = get_pat(argv[0]); - res = Qnil; - if (rb_reg_search(pat, str, 0, 0) >= 0) { - start = mm_correct_backref(t_mm); - match = rb_backref_get(); - regs = RMATCH(match)->regs; - if (iter) { - rb_match_busy(match); - repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match))); - rb_backref_set(match); - } - else { - RSTRING(str)->ptr += start; - repl = rb_reg_regsub(repl, str, regs); - RSTRING(str)->ptr -= start; - } - if (OBJ_TAINTED(repl)) tainted = 1; - plen = END(0) - BEG(0); - if (RSTRING(repl)->len > plen) { - mm_realloc(t_mm, RSTRING(str)->len + RSTRING(repl)->len - plen); - RSTRING(str)->ptr = t_mm->addr; - } - if (RSTRING(repl)->len != plen) { - if (t_mm->flag & MM_FIXED) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - memmove(RSTRING(str)->ptr + start + BEG(0) + RSTRING(repl)->len, - RSTRING(str)->ptr + start + BEG(0) + plen, - RSTRING(str)->len - start - BEG(0) - plen); - } - memcpy(RSTRING(str)->ptr + start + BEG(0), - RSTRING(repl)->ptr, RSTRING(repl)->len); - t_mm->real += RSTRING(repl)->len - plen; - if (tainted) OBJ_TAINT(obj); - - res = obj; - } - rb_gc_force_recycle(str); - return res; -} - -static VALUE -mm_gsub_bang(argc, argv, obj) - int argc; - VALUE *argv; - VALUE obj; -{ - VALUE pat, val, repl, match, str; - struct re_registers *regs; - long beg, offset; - int start, iter = 0; - int tainted = 0; - long plen; - mm_mmap *t_mm; - - if (argc == 1 && rb_block_given_p()) { - iter = 1; - } - else if (argc == 2) { - repl = rb_str_to_str(argv[1]); - if (OBJ_TAINTED(repl)) tainted = 1; - } - else { - rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc); - } - GetMmap(obj, t_mm, MM_MODIFY); - str = mm_str(obj, MM_MODIFY | MM_ORIGIN); - - pat = get_pat(argv[0]); - offset = 0; - beg = rb_reg_search(pat, str, 0, 0); - if (beg < 0) { - rb_gc_force_recycle(str); - return Qnil; - } - while (beg >= 0) { - start = mm_correct_backref(t_mm); - match = rb_backref_get(); - regs = RMATCH(match)->regs; - if (iter) { - rb_match_busy(match); - val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match))); - rb_backref_set(match); - } - else { - RSTRING(str)->ptr += start; - val = rb_reg_regsub(repl, str, regs); - RSTRING(str)->ptr -= start; - } - if (OBJ_TAINTED(repl)) tainted = 1; - plen = END(0) - BEG(0); - if ((t_mm->real + RSTRING(val)->len - plen) > t_mm->len) { - mm_realloc(t_mm, RSTRING(str)->len + RSTRING(val)->len - plen); - } - if (RSTRING(val)->len != plen) { - if (t_mm->flag & MM_FIXED) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - memmove(RSTRING(str)->ptr + start + BEG(0) + RSTRING(val)->len, - RSTRING(str)->ptr + start + BEG(0) + plen, - RSTRING(str)->len - start - BEG(0) - plen); - } - memcpy(RSTRING(str)->ptr + start + BEG(0), - RSTRING(val)->ptr, RSTRING(val)->len); - RSTRING(str)->len += RSTRING(val)->len - plen; - t_mm->real = RSTRING(str)->len; - if (BEG(0) == END(0)) { - offset = start + END(0) + mbclen2(RSTRING(str)->ptr[END(0)], pat); - offset += RSTRING(val)->len - plen; - } - else { - offset = start + END(0) + RSTRING(val)->len - plen; - } - if (offset > RSTRING(str)->len) break; - beg = rb_reg_search(pat, str, offset, 0); - } - rb_backref_set(match); - if (tainted) OBJ_TAINT(obj); - rb_gc_force_recycle(str); - return 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; - VALUE indx, val; -{ - long idx, beg; - mm_mmap *t_mm; - - GetMmap(str, t_mm, MM_MODIFY); - switch (TYPE(indx)) { - case T_FIXNUM: - num_index: - idx = NUM2INT(indx); - if (idx < 0) { - idx += t_mm->real; - } - if (idx < 0 || t_mm->real <= idx) { - rb_raise(rb_eIndexError, "index %d out of string", idx); - } - if (FIXNUM_P(val)) { - if (t_mm->real == idx) { - t_mm->real += 1; - mm_realloc(t_mm, t_mm->real); - } - ((char *)t_mm->addr)[idx] = NUM2INT(val) & 0xff; - } - else { - mm_update(t_mm, idx, 1, 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(t_mm, beg, RSTRING(indx)->len, val); - } - return val; - - default: - /* check if indx is Range */ - { - long beg, len; - if (rb_range_beg_len(indx, &beg, &len, t_mm->real, 2)) { - mm_update(t_mm, beg, len, val); - return val; - } - } - idx = NUM2LONG(indx); - goto num_index; - } -} - -static VALUE -mm_aset_m(argc, argv, str) - int argc; - VALUE *argv; - VALUE str; -{ - mm_mmap *t_mm; - - GetMmap(str, t_mm, MM_MODIFY); - if (argc == 3) { - long beg, len; - -#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) { - rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc); - } - return mm_aset(str, argv[0], argv[1]); -} - -static VALUE -mm_insert(str, idx, str2) - VALUE str, idx, str2; -{ - mm_mmap *t_mm; - long pos = NUM2LONG(idx); - - GetMmap(str, t_mm, MM_MODIFY); - if (pos == -1) { - pos = RSTRING(str)->len; - } - else if (pos < 0) { - pos++; - } - mm_update(t_mm, pos, 0, str2); - return str; -} - -static VALUE mm_aref_m _((int, VALUE *, VALUE)); - -static VALUE -mm_slice_bang(argc, argv, str) - int argc; - VALUE *argv; - VALUE str; -{ - VALUE result; - VALUE buf[3]; - int i; - - if (argc < 1 || 2 < argc) { - rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)", argc); - } - for (i = 0; i < argc; i++) { - buf[i] = argv[i]; - } - buf[i] = rb_str_new(0,0); - result = mm_aref_m(argc, buf, str); -#if RUBY_VERSION_CODE >= 168 - if (!NIL_P(result)) { -#endif - mm_aset_m(argc+1, buf, str); -#if RUBY_VERSION_CODE >= 168 - } -#endif - return result; -} - -static VALUE -mm_cat(str, ptr, len) - VALUE str; - const char *ptr; - long len; -{ - mm_mmap *t_mm; - char *sptr; - - GetMmap(str, t_mm, MM_MODIFY); - if (len > 0) { - int poffset = -1; - sptr = (char *)t_mm->addr; - - if (sptr <= ptr && - ptr < sptr + t_mm->real) { - poffset = ptr - sptr; - } - mm_realloc(t_mm, t_mm->real + len); - sptr = (char *)t_mm->addr; - if (ptr) { - if (poffset >= 0) ptr = sptr + poffset; - memcpy(sptr + t_mm->real, ptr, len); - } - t_mm->real += len; - } - return str; -} - -static VALUE -mm_append(str1, str2) - VALUE str1, str2; -{ - str2 = rb_str_to_str(str2); - str1 = mm_cat(str1, StringValuePtr(str2), RSTRING(str2)->len); - return str1; -} - -static VALUE -mm_concat(str1, str2) - VALUE str1, str2; -{ - if (FIXNUM_P(str2)) { - int i = FIX2INT(str2); - if (0 <= i && i <= 0xff) { /* byte */ - char c = i; - return mm_cat(str1, &c, 1); - } - } - str1 = mm_append(str1, str2); - return str1; -} - -#if RUBY_VERSION_CODE < 171 - -static VALUE -mm_strip_bang(str) - VALUE str; -{ - char *s, *t, *e; - mm_mmap *t_mm; - - GetMmap(str, t_mm, MM_MODIFY); - s = (char *)t_mm->addr; - e = t = s + t_mm->real; - while (s < t && ISSPACE(*s)) s++; - t--; - while (s <= t && ISSPACE(*t)) t--; - t++; - - if (t_mm->real != (t - s) && (t_mm->flag & MM_FIXED)) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - t_mm->real = t-s; - if (s > (char *)t_mm->addr) { - memmove(t_mm->addr, s, t_mm->real); - ((char *)t_mm->addr)[t_mm->real] = '\0'; - } - else if (t < e) { - ((char *)t_mm->addr)[t_mm->real] = '\0'; - } - else { - return Qnil; - } - - return str; -} - -#else - -static VALUE -mm_lstrip_bang(str) - VALUE str; -{ - char *s, *t, *e; - mm_mmap *t_mm; - - GetMmap(str, t_mm, MM_MODIFY); - s = (char *)t_mm->addr; - e = t = s + t_mm->real; - while (s < t && ISSPACE(*s)) s++; - - if (t_mm->real != (t - s) && (t_mm->flag & MM_FIXED)) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - t_mm->real = t - s; - if (s > (char *)t_mm->addr) { - memmove(t_mm->addr, s, t_mm->real); - ((char *)t_mm->addr)[t_mm->real] = '\0'; - return str; - } - return Qnil; -} - -static VALUE -mm_rstrip_bang(str) - VALUE str; -{ - char *s, *t, *e; - mm_mmap *t_mm; - - GetMmap(str, t_mm, MM_MODIFY); - s = (char *)t_mm->addr; - e = t = s + t_mm->real; - t--; - while (s <= t && ISSPACE(*t)) t--; - t++; - if (t_mm->real != (t - s) && (t_mm->flag & MM_FIXED)) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - t_mm->real = t - s; - if (t < e) { - ((char *)t_mm->addr)[t_mm->real] = '\0'; - return str; - } - return Qnil; -} - -static VALUE -mm_strip_bang(str) - VALUE str; -{ - VALUE l = mm_lstrip_bang(str); - VALUE r = mm_rstrip_bang(str); - - if (NIL_P(l) && NIL_P(r)) return Qnil; - return str; -} - -#endif - -#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); - - -static VALUE -mm_cmp(a, b) - VALUE a, b; -{ - int result; - int recycle = 0; - - a = mm_str(a, MM_ORIGIN); - MmapStr(b, recycle); - result = rb_str_cmp(a, b); - rb_gc_force_recycle(a); - if (recycle) rb_gc_force_recycle(b); - return INT2FIX(result); -} - -#if RUBY_VERSION_CODE >= 171 - -static VALUE -mm_casecmp(a, b) - VALUE a, b; -{ - VALUE result; - int recycle = 0; - - a = mm_str(a, MM_ORIGIN); - MmapStr(b, recycle); - result = rb_funcall2(a, rb_intern("casecmp"), 1, &b); - rb_gc_force_recycle(a); - if (recycle) rb_gc_force_recycle(b); - return result; -} - -#endif - -static VALUE -mm_equal(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("=="), 1, &b); - rb_gc_force_recycle(a); - 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; -} - -static VALUE -mm_hash(a) - VALUE a; -{ - VALUE b; - int res; - - b = mm_str(a, MM_ORIGIN); - res = rb_str_hash(b); - rb_gc_force_recycle(b); - return INT2FIX(res); -} - -static VALUE -mm_size(a) - VALUE a; -{ - mm_mmap *t_mm; - - GetMmap(a, t_mm, 0); - return INT2NUM(t_mm->real); -} - -static VALUE -mm_empty(a) - VALUE a; -{ - mm_mmap *t_mm; - - GetMmap(a, t_mm, 0); - if (t_mm->real == 0) return Qtrue; - return Qfalse; -} - -static VALUE -mm_protect_bang(t) - VALUE *t; -{ - return rb_funcall2(t[0], (ID)t[1], (int)t[2], (VALUE *)t[3]); -} - -static VALUE -mm_recycle(str) - VALUE str; -{ - rb_gc_force_recycle(str); - return str; -} - -static VALUE -mm_bang_i(obj, flag, id, argc, argv) - VALUE obj, *argv; - int flag, id, argc; -{ - VALUE str, res; - mm_mmap *t_mm; - - GetMmap(obj, t_mm, 0); - if ((flag & MM_CHANGE) && (t_mm->flag & MM_FIXED)) { - rb_raise(rb_eTypeError, "try to change the size of a fixed map"); - } - str = mm_str(obj, flag); - if (flag & MM_PROTECT) { - VALUE tmp[4]; - tmp[0] = str; - tmp[1] = (VALUE)id; - tmp[2] = (VALUE)argc; - tmp[3] = (VALUE)argv; - res = rb_ensure(mm_protect_bang, (VALUE)tmp, mm_recycle, str); - } - else { - res = rb_funcall2(str, id, argc, argv); - rb_gc_force_recycle(str); - } - if (res == Qnil) return res; - GetMmap(obj, t_mm, 0); - t_mm->real = RSTRING(str)->len; - return (flag & MM_ORIGIN)?res:obj; - -} - -#if RUBY_VERSION_CODE >= 180 - -static VALUE -mm_match_m(a, b) - VALUE a, b; -{ - return mm_bang_i(a, MM_ORIGIN, rb_intern("match"), 1, &b); -} - -#endif - -static VALUE -mm_upcase_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_MODIFY, rb_intern("upcase!"), 0, 0); -} - -static VALUE -mm_downcase_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_MODIFY, rb_intern("downcase!"), 0, 0); -} - -static VALUE -mm_capitalize_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_MODIFY, rb_intern("capitalize!"), 0, 0); -} - -static VALUE -mm_swapcase_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_MODIFY, rb_intern("swapcase!"), 0, 0); -} - -static VALUE -mm_reverse_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_MODIFY, rb_intern("reverse!"), 0, 0); -} - -static VALUE -mm_chop_bang(a) - VALUE a; -{ - return mm_bang_i(a, MM_CHANGE, rb_intern("chop!"), 0, 0); -} - -static VALUE -mm_inspect(a) - VALUE a; -{ - return rb_any_to_s(a); -} - -static VALUE -mm_chomp_bang(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("chomp!"), argc, argv); -} - -static VALUE -mm_delete_bang(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("delete!"), argc, argv); -} - -static VALUE -mm_squeeze_bang(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("squeeze!"), argc, argv); -} - -static VALUE -mm_tr_bang(obj, a, b) - VALUE obj, a, b; -{ - VALUE tmp[2]; - tmp[0] = a; - tmp[1] = b; - return mm_bang_i(obj, MM_MODIFY | MM_PROTECT, rb_intern("tr!"), 2, tmp); -} - -static VALUE -mm_tr_s_bang(obj, a, b) - VALUE obj, a, b; -{ - VALUE tmp[2]; - tmp[0] = a; - tmp[1] = b; - return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("tr_s!"), 2, tmp); -} - -static VALUE -mm_crypt(a, b) - VALUE a, b; -{ - return mm_bang_i(a, MM_ORIGIN, rb_intern("crypt"), 1, &b); -} - -static VALUE -mm_include(a, b) - VALUE a, b; -{ - return mm_bang_i(a, MM_ORIGIN, rb_intern("include?"), 1, &b); -} - -static VALUE -mm_index(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("index"), argc, argv); -} - -static VALUE -mm_rindex(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("rindex"), argc, argv); -} - -static VALUE -mm_aref_m(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("[]"), argc, argv); -} - -static VALUE -mm_sum(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("sum"), argc, argv); -} - -static VALUE -mm_split(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("split"), argc, argv); -} - -static VALUE -mm_count(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - return mm_bang_i(obj, MM_ORIGIN, rb_intern("count"), argc, argv); -} - -static VALUE -mm_internal_each(tmp) - VALUE *tmp; -{ - return rb_funcall2(tmp[0], (ID)tmp[1], (int)tmp[2], (VALUE *)tmp[3]); -} - -static VALUE -mm_scan(obj, a) - VALUE obj, a; -{ - VALUE tmp[4]; - - if (!rb_block_given_p()) { - return rb_funcall(mm_str(obj, MM_ORIGIN), rb_intern("scan"), 1, a); - } - tmp[0] = mm_str(obj, MM_ORIGIN); - tmp[1] = (VALUE)rb_intern("scan"); - tmp[2] = (VALUE)1; - tmp[3] = (VALUE)&a; - rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0); - return obj; -} - -static VALUE -mm_each_line(argc, argv, obj) - int argc; - VALUE obj, *argv; -{ - VALUE tmp[4]; - - tmp[0] = mm_str(obj, MM_ORIGIN); - tmp[1] = (VALUE)rb_intern("each_line"); - tmp[2] = (VALUE)argc; - tmp[3] = (VALUE)argv; - rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0); - return obj; -} - -static VALUE -mm_each_byte(argc, argv, obj) - int argc; - VALUE obj, *argv; -{ - VALUE tmp[4]; - - tmp[0] = mm_str(obj, MM_ORIGIN); - tmp[1] = (VALUE)rb_intern("each_byte"); - tmp[2] = (VALUE)argc; - tmp[3] = (VALUE)argv; - rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0); - return obj; -} - -static VALUE -mm_undefined(argc, argv, obj) - int argc; - VALUE *argv, obj; -{ - rb_raise(rb_eNameError, "not yet implemented"); -} - -static VALUE -mm_mlockall(obj, flag) - VALUE obj, flag; -{ - if (mlockall(NUM2INT(flag)) == -1) { - rb_raise(rb_eArgError, "mlockall(%d)", errno); - } - return Qnil; -} - -static VALUE -mm_munlockall(obj) - VALUE obj; -{ - if (munlockall() == -1) { - rb_raise(rb_eArgError, "munlockall(%d)", errno); - } - return Qnil; -} - -static VALUE -mm_mlock(obj) - VALUE obj; -{ - mm_mmap *t_mm; - - Data_Get_Struct(obj, mm_mmap, t_mm); - if (t_mm->flag & MM_LOCK) { - return obj; - } - if (mlock(t_mm->addr, t_mm->len) == -1) { - rb_raise(rb_eArgError, "mlock(%d)", errno); - } - t_mm->flag |= MM_LOCK; - return obj; -} - -static VALUE -mm_munlock(obj) - VALUE obj; -{ - mm_mmap *t_mm; - - Data_Get_Struct(obj, mm_mmap, t_mm); - if (!(t_mm->flag & MM_LOCK)) { - return obj; - } - if (munlock(t_mm->addr, t_mm->len) == -1) { - rb_raise(rb_eArgError, "munlock(%d)", errno); - } - t_mm->flag &= ~MM_LOCK; - return obj; -} - -void -Init_mmap() -{ - if (rb_const_defined_at(rb_cObject, rb_intern("Mmap"))) { - rb_raise(rb_eNameError, "class already defined"); - } - mm_cMap = rb_define_class("Mmap", rb_cObject); - rb_define_const(mm_cMap, "MS_SYNC", INT2FIX(MS_SYNC)); - rb_define_const(mm_cMap, "MS_ASYNC", INT2FIX(MS_ASYNC)); - rb_define_const(mm_cMap, "MS_INVALIDATE", INT2FIX(MS_INVALIDATE)); - rb_define_const(mm_cMap, "PROT_READ", INT2FIX(PROT_READ)); - rb_define_const(mm_cMap, "PROT_WRITE", INT2FIX(PROT_WRITE)); - rb_define_const(mm_cMap, "PROT_EXEC", INT2FIX(PROT_EXEC)); - rb_define_const(mm_cMap, "PROT_NONE", INT2FIX(PROT_NONE)); - rb_define_const(mm_cMap, "MAP_SHARED", INT2FIX(MAP_SHARED)); - rb_define_const(mm_cMap, "MAP_PRIVATE", INT2FIX(MAP_PRIVATE)); -#ifdef MADV_NORMAL - rb_define_const(mm_cMap, "MADV_NORMAL", INT2FIX(MADV_NORMAL)); - rb_define_const(mm_cMap, "MADV_RANDOM", INT2FIX(MADV_RANDOM)); - rb_define_const(mm_cMap, "MADV_SEQUENTIAL", INT2FIX(MADV_SEQUENTIAL)); - rb_define_const(mm_cMap, "MADV_WILLNEED", INT2FIX(MADV_WILLNEED)); - rb_define_const(mm_cMap, "MADV_DONTNEED", INT2FIX(MADV_DONTNEED)); -#endif -#ifdef MAP_DENYWRITE - rb_define_const(mm_cMap, "MAP_DENYWRITE", INT2FIX(MAP_DENYWRITE)); -#endif -#ifdef MAP_EXECUTABLE - rb_define_const(mm_cMap, "MAP_EXECUTABLE", INT2FIX(MAP_EXECUTABLE)); -#endif -#ifdef MAP_NORESERVE - rb_define_const(mm_cMap, "MAP_NORESERVE", INT2FIX(MAP_NORESERVE)); -#endif -#ifdef MAP_LOCKED - rb_define_const(mm_cMap, "MAP_LOCKED", INT2FIX(MAP_LOCKED)); -#endif -#ifdef MAP_GROWSDOWN - rb_define_const(mm_cMap, "MAP_GROWSDOWN", INT2FIX(MAP_GROWSDOWN)); -#endif -#ifdef MAP_ANON - rb_define_const(mm_cMap, "MAP_ANON", INT2FIX(MAP_ANON)); -#endif -#ifdef MAP_ANONYMOUS - rb_define_const(mm_cMap, "MAP_ANONYMOUS", INT2FIX(MAP_ANONYMOUS)); -#endif -#ifdef MAP_NOSYNC - rb_define_const(mm_cMap, "MAP_NOSYNC", INT2FIX(MAP_NOSYNC)); -#endif - rb_define_const(mm_cMap, "MCL_CURRENT", INT2FIX(MCL_CURRENT)); - rb_define_const(mm_cMap, "MCL_FUTURE", INT2FIX(MCL_FUTURE)); - - rb_include_module(mm_cMap, rb_mComparable); - rb_include_module(mm_cMap, rb_mEnumerable); - -#if RUBY_VERSION_CODE >= 172 -#if RUBY_VERSION_CODE >= 180 - rb_define_alloc_func(mm_cMap, mm_s_alloc); -#else - rb_define_singleton_method(mm_cMap, "allocate", mm_s_alloc, 0); -#endif -#else - rb_define_singleton_method(mm_cMap, "new", mm_s_new, -1); -#endif - 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); - rb_define_singleton_method(mm_cMap, "unlockall", mm_munlockall, 0); - - rb_define_method(mm_cMap, "initialize", mm_init, -1); - - rb_define_method(mm_cMap, "unmap", mm_unmap, 0); - rb_define_method(mm_cMap, "munmap", mm_unmap, 0); - rb_define_method(mm_cMap, "msync", mm_msync, -1); - rb_define_method(mm_cMap, "sync", mm_msync, -1); - rb_define_method(mm_cMap, "flush", mm_msync, -1); - rb_define_method(mm_cMap, "mprotect", mm_mprotect, 1); - rb_define_method(mm_cMap, "protect", mm_mprotect, 1); -#ifdef MADV_NORMAL - rb_define_method(mm_cMap, "madvise", mm_madvise, 1); - rb_define_method(mm_cMap, "advise", mm_madvise, 1); -#endif - rb_define_method(mm_cMap, "mlock", mm_mlock, 0); - rb_define_method(mm_cMap, "lock", mm_mlock, 0); - rb_define_method(mm_cMap, "munlock", mm_munlock, 0); - rb_define_method(mm_cMap, "unlock", mm_munlock, 0); - - rb_define_method(mm_cMap, "extend", mm_extend, 1); - rb_define_method(mm_cMap, "freeze", mm_freeze, 0); - rb_define_method(mm_cMap, "clone", mm_undefined, -1); -#if RUBY_VERSION_CODE >= 180 - rb_define_method(mm_cMap, "initialize_copy", mm_undefined, -1); -#endif - rb_define_method(mm_cMap, "dup", mm_undefined, -1); - 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_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); -#endif - rb_define_method(mm_cMap, "+", mm_undefined, -1); - rb_define_method(mm_cMap, "*", mm_undefined, -1); - rb_define_method(mm_cMap, "%", mm_undefined, -1); - rb_define_method(mm_cMap, "[]", mm_aref_m, -1); - rb_define_method(mm_cMap, "[]=", mm_aset_m, -1); -#if RUBY_VERSION_CODE >= 171 - rb_define_method(mm_cMap, "insert", mm_insert, 2); -#endif - rb_define_method(mm_cMap, "length", mm_size, 0); - rb_define_method(mm_cMap, "size", mm_size, 0); - rb_define_method(mm_cMap, "empty?", mm_empty, 0); - rb_define_method(mm_cMap, "=~", mm_match, 1); - rb_define_method(mm_cMap, "~", mm_undefined, -1); -#if RUBY_VERSION_CODE >= 180 - rb_define_method(mm_cMap, "match", mm_match_m, 1); -#endif - rb_define_method(mm_cMap, "succ", mm_undefined, -1); - rb_define_method(mm_cMap, "succ!", mm_undefined, -1); - rb_define_method(mm_cMap, "next", mm_undefined, -1); - rb_define_method(mm_cMap, "next!", mm_undefined, -1); - rb_define_method(mm_cMap, "upto", mm_undefined, -1); - rb_define_method(mm_cMap, "index", mm_index, -1); - rb_define_method(mm_cMap, "rindex", mm_rindex, -1); - rb_define_method(mm_cMap, "replace", mm_undefined, -1); - - 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_sym", mm_undefined, -1); - 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); - - rb_define_method(mm_cMap, "upcase", mm_undefined, -1); - rb_define_method(mm_cMap, "downcase", mm_undefined, -1); - rb_define_method(mm_cMap, "capitalize", mm_undefined, -1); - rb_define_method(mm_cMap, "swapcase", mm_undefined, -1); - - rb_define_method(mm_cMap, "upcase!", mm_upcase_bang, 0); - rb_define_method(mm_cMap, "downcase!", mm_downcase_bang, 0); - rb_define_method(mm_cMap, "capitalize!", mm_capitalize_bang, 0); - rb_define_method(mm_cMap, "swapcase!", mm_swapcase_bang, 0); - - rb_define_method(mm_cMap, "hex", mm_undefined, -1); - rb_define_method(mm_cMap, "oct", mm_undefined, -1); - rb_define_method(mm_cMap, "split", mm_split, -1); - rb_define_method(mm_cMap, "reverse", mm_undefined, -1); - rb_define_method(mm_cMap, "reverse!", mm_reverse_bang, 0); - rb_define_method(mm_cMap, "concat", mm_concat, 1); - rb_define_method(mm_cMap, "<<", mm_concat, 1); - rb_define_method(mm_cMap, "crypt", mm_crypt, 1); - rb_define_method(mm_cMap, "intern", mm_undefined, -1); - - rb_define_method(mm_cMap, "include?", mm_include, 1); - - rb_define_method(mm_cMap, "scan", mm_scan, 1); - - rb_define_method(mm_cMap, "ljust", mm_undefined, -1); - rb_define_method(mm_cMap, "rjust", mm_undefined, -1); - rb_define_method(mm_cMap, "center", mm_undefined, -1); - - rb_define_method(mm_cMap, "sub", mm_undefined, -1); - rb_define_method(mm_cMap, "gsub", mm_undefined, -1); - rb_define_method(mm_cMap, "chop", mm_undefined, -1); - rb_define_method(mm_cMap, "chomp", mm_undefined, -1); - rb_define_method(mm_cMap, "strip", mm_undefined, -1); -#if RUBY_VERSION_CODE >= 171 - rb_define_method(mm_cMap, "lstrip", mm_undefined, -1); - rb_define_method(mm_cMap, "rstrip", mm_undefined, -1); -#endif - - rb_define_method(mm_cMap, "sub!", mm_sub_bang, -1); - rb_define_method(mm_cMap, "gsub!", mm_gsub_bang, -1); - rb_define_method(mm_cMap, "strip!", mm_strip_bang, 0); -#if RUBY_VERSION_CODE >= 171 - rb_define_method(mm_cMap, "lstrip!", mm_lstrip_bang, 0); - rb_define_method(mm_cMap, "rstrip!", mm_rstrip_bang, 0); -#endif - rb_define_method(mm_cMap, "chop!", mm_chop_bang, 0); - rb_define_method(mm_cMap, "chomp!", mm_chomp_bang, -1); - - rb_define_method(mm_cMap, "tr", mm_undefined, -1); - rb_define_method(mm_cMap, "tr_s", mm_undefined, -1); - rb_define_method(mm_cMap, "delete", mm_undefined, -1); - rb_define_method(mm_cMap, "squeeze", mm_undefined, -1); - rb_define_method(mm_cMap, "count", mm_count, -1); - - rb_define_method(mm_cMap, "tr!", mm_tr_bang, 2); - rb_define_method(mm_cMap, "tr_s!", mm_tr_s_bang, 2); - rb_define_method(mm_cMap, "delete!", mm_delete_bang, -1); - rb_define_method(mm_cMap, "squeeze!", mm_squeeze_bang, -1); - - rb_define_method(mm_cMap, "each_line", mm_each_line, -1); - rb_define_method(mm_cMap, "each", mm_each_line, -1); - rb_define_method(mm_cMap, "each_byte", mm_each_byte, -1); - - rb_define_method(mm_cMap, "sum", mm_sum, -1); - - rb_define_method(mm_cMap, "slice", mm_aref_m, -1); - rb_define_method(mm_cMap, "slice!", mm_slice_bang, -1); -} |