diff options
-rw-r--r-- | Changes | 5 | ||||
-rw-r--r-- | aa | 2 | ||||
-rwxr-xr-x | b.rb | 2 | ||||
-rwxr-xr-x | docs/b.rb | 3 | ||||
-rw-r--r-- | extconf.rb | 2 | ||||
-rw-r--r-- | mmap.c | 192 | ||||
-rw-r--r-- | mmap.html | 210 | ||||
-rw-r--r-- | mmap.rd | 75 | ||||
-rw-r--r-- | tests/mmapt.rb | 4 |
9 files changed, 354 insertions, 141 deletions
@@ -44,3 +44,8 @@ * don't test size for MAP_ANON * added syntax Mmap(nil, length) * documentation : make rd2; make rdoc + +-- 0.1.9 + +* String#slice! was modified in 1.6.8 +* added ::new(IO) @@ -1,2 +0,0 @@ -123 -abc @@ -7,7 +7,7 @@ f.write("\0" * PAGESIZE) f.write("b.rb") f.write("\0" * PAGESIZE) f.close -m = Mmap.new("aa", "rw", "offset" => 0) +m = Mmap.new("aa", "w", "offset" => 0) p m.size == "b.rb".size + 2 * PAGESIZE p m.scan(/[a-z.]+/) == ["b.rb"] p m.index("b.rb") == PAGESIZE @@ -11,7 +11,8 @@ end def normalize(text) norm = text.gsub(/\(\(\|([^|]+)\|\)\)/, '<em>\\1</em>') - norm.gsub(/\(\(\{/, '<tt>').gsub!(/\}\)\)/, '</tt>') + norm.gsub!(/\(\(\{/, '<tt>') + norm.gsub!(/\}\)\)/, '</tt>') norm.gsub!(/\(\(<([^|>]+)[^>]*>\)\)/, '<em>\\1</em>') norm.gsub!(/^\s*:\s/, ' * ') norm @@ -30,7 +30,7 @@ unknown: $(DLLIB) rdoc: docs/doc/index.html docs/doc/index.html: $(RDOC) -\t@-(cd docs; b.rb mmap; rdoc mmap.rb) +\t@-(cd docs; $(RUBY) b.rb mmap; rdoc mmap.rb) rd2: html @@ -43,6 +43,12 @@ #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 @@ -50,13 +56,21 @@ static VALUE mm_cMap; typedef struct { MMAP_RETTYPE addr; int smode, pmode, vscope; - int advice, frozen, lock; + 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; { @@ -80,15 +94,17 @@ mm_free(t_mm) #define MM_CHANGE (MM_MODIFY | 4) #define MM_PROTECT 8 -#define MM_FROZEN 1 -#define MM_FIXED 2 +#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->frozen & MM_FROZEN)) { \ + if ((t_modify & MM_MODIFY) && (t_mm->flag & MM_FROZEN)) { \ rb_error_frozen("mmap"); \ } @@ -120,7 +136,7 @@ mm_freeze(obj) mm_mmap *t_mm; rb_obj_freeze(obj); GetMmap(obj, t_mm, 0); - t_mm->frozen |= MM_FROZEN; + t_mm->flag |= MM_FROZEN; } static VALUE @@ -133,7 +149,7 @@ mm_str(obj, modify) GetMmap(obj, t_mm, modify & ~MM_ORIGIN); if (modify & MM_MODIFY) { - if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap"); + 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"); } @@ -161,7 +177,7 @@ mm_str(obj, modify) RSTRING(ret)->orig = ret; #endif } - if (t_mm->frozen & MM_FROZEN) { + if (t_mm->flag & MM_FROZEN) { ret = rb_obj_freeze(ret); } return ret; @@ -186,9 +202,12 @@ mm_expandf(t_mm, len) if (t_mm->vscope == MAP_PRIVATE) { rb_raise(rb_eTypeError, "expand for a private map"); } - if (t_mm->frozen & MM_FIXED) { + 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"); } @@ -216,7 +235,7 @@ mm_expandf(t_mm, len) rb_raise(rb_eArgError, "madvise(%d)", errno); } #endif - if (t_mm->lock && mlock(t_mm->addr, len) == -1) { + if ((t_mm->flag & MM_LOCK) && mlock(t_mm->addr, len) == -1) { rb_raise(rb_eArgError, "mlock(%d)", errno); } t_mm->len = len; @@ -227,7 +246,7 @@ mm_realloc(t_mm, len) mm_mmap *t_mm; long len; { - if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap"); + 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; @@ -269,14 +288,14 @@ mm_i_options(arg, obj) if (t_mm->len <= 0) { rb_raise(rb_eArgError, "Invalid value for length %d", t_mm->len); } - t_mm->frozen |= MM_FIXED; + 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->frozen |= MM_FIXED; + t_mm->flag |= MM_FIXED; } else if (strcmp(options, "advice") == 0) { t_mm->advice = NUM2INT(value); @@ -300,7 +319,7 @@ mm_s_alloc(argc, argv, obj) VALUE res; mm_mmap *t_mm; - res = Data_Make_Struct(obj, mm_mmap, 0, mm_free, t_mm); + res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); t_mm->incr = EXP_INCR_SIZE; return res; } @@ -318,11 +337,12 @@ mm_s_new(argc, argv, obj) struct stat st; int fd, smode, pmode, vscope, perm, init; MMAP_RETTYPE addr; - VALUE res, fname, vmode, scope, options; + 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) { @@ -331,29 +351,49 @@ mm_s_new(argc, argv, obj) } 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; - path = 0; + anonymous = 1; } - else { - Check_SafeStr(fname); - path = RSTRING(fname)->ptr; + 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); + Check_SafeStr(fname); + path = RSTRING(fname)->ptr; + } + 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 } } -#else - Check_SafeStr(fname); - path = RSTRING(fname)->ptr; -#endif vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope); size = 0; perm = 0666; - if (path) { + if (!anonymous) { if (NIL_P(vmode)) { mode = "r"; } @@ -372,6 +412,9 @@ mm_s_new(argc, argv, obj) 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; @@ -384,8 +427,10 @@ mm_s_new(argc, argv, obj) else { rb_raise(rb_eArgError, "Invalid mode %s", mode); } - if ((fd = open(path, smode, perm)) == -1) { - rb_raise(rb_eArgError, "Can't open %s", path); + 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); @@ -402,7 +447,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, 0, mm_free, t_mm); + res = Data_Make_Struct(obj, mm_mmap, mm_mark, mm_free, t_mm); t_mm->incr = EXP_INCR_SIZE; #endif offset = 0; @@ -416,7 +461,7 @@ mm_s_new(argc, argv, obj) offset = t_mm->offset; } init = 0; - if (!path) { + if (anonymous) { if (size <= 0) { rb_raise(rb_eArgError, "length not specified for an anonymous map"); } @@ -426,22 +471,29 @@ mm_s_new(argc, argv, obj) } smode = O_RDWR; pmode = PROT_READ | PROT_WRITE; - t_mm->frozen |= MM_FIXED; + 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); + 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 (write(fd, "\000", 1) != 1) { - rb_raise(rb_eIOError, "Can't extend %s", path); + if (!NIL_P(fdv)) { + t_mm->flag |= MM_FIXED; } - init = 1; - size = t_mm->incr; } addr = mmap(0, size, pmode, vscope, fd, offset); - if (fd != -1) close(fd); + if (NIL_P(fdv) && !anonymous) { + close(fd); + } if (addr == MAP_FAILED || !addr) { - rb_raise(rb_eArgError, "mmap failed (%x)", addr); + rb_raise(rb_eArgError, "mmap failed (%d)", errno); } #ifdef MADV_NORMAL if (t_mm->advice && madvise(addr, size, t_mm->advice) == -1) { @@ -455,9 +507,12 @@ 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->frozen |= MM_FROZEN; + t_mm->flag |= MM_FROZEN; } else { OBJ_TAINT(res); @@ -524,7 +579,7 @@ mm_mprotect(obj, a) else { pmode = NUM2INT(a); } - if ((pmode & PROT_WRITE) && (t_mm->frozen & MM_FROZEN)) + 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); @@ -536,7 +591,7 @@ mm_mprotect(obj, a) t_mm->smode == O_RDONLY; if (t_mm->vscope == MAP_PRIVATE) { obj = rb_obj_freeze(obj); - t_mm->frozen |= MM_FROZEN; + t_mm->flag |= MM_FROZEN; } } } @@ -587,7 +642,7 @@ mm_update(str, beg, len, val) char *valp; long vall; - if (str->frozen & MM_FROZEN) rb_error_frozen("mmap"); + 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; @@ -604,7 +659,7 @@ mm_update(str, beg, len, val) StringMmap(val, valp, vall); - if ((str->frozen & MM_FIXED) && vall != len) { + if ((str->flag & MM_FIXED) && vall != len) { rb_raise(rb_eTypeError, "try to change the size of a fixed map"); } if (len < vall) { @@ -675,7 +730,8 @@ get_pat(pat) } static int -mm_correct_backref() +mm_correct_backref(t_mm) + mm_mmap *t_mm; { VALUE match; struct re_registers *regs; @@ -725,7 +781,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(); + start = mm_correct_backref(t_mm); match = rb_backref_get(); regs = RMATCH(match)->regs; if (iter) { @@ -739,20 +795,20 @@ mm_sub_bang(argc, argv, obj) RSTRING(str)->ptr -= start; } if (OBJ_TAINTED(repl)) tainted = 1; - plen = END(0); + 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->frozen & MM_FIXED) { + if (t_mm->flag & MM_FIXED) { rb_raise(rb_eTypeError, "try to change the size of a fixed map"); } - memmove(RSTRING(str)->ptr + start + RSTRING(repl)->len, - RSTRING(str)->ptr + start + plen, - RSTRING(str)->len - start - plen); + 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, + 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); @@ -798,7 +854,7 @@ mm_gsub_bang(argc, argv, obj) return Qnil; } while (beg >= 0) { - start = mm_correct_backref(); + start = mm_correct_backref(t_mm); match = rb_backref_get(); regs = RMATCH(match)->regs; if (iter) { @@ -812,20 +868,19 @@ mm_gsub_bang(argc, argv, obj) RSTRING(str)->ptr -= start; } if (OBJ_TAINTED(repl)) tainted = 1; - plen = END(0); + 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); - RSTRING(str)->ptr = t_mm->addr; } if (RSTRING(val)->len != plen) { - if (t_mm->frozen & MM_FIXED) { + if (t_mm->flag & MM_FIXED) { rb_raise(rb_eTypeError, "try to change the size of a fixed map"); } - memmove(RSTRING(str)->ptr + start + RSTRING(val)->len, - RSTRING(str)->ptr + start + plen, - RSTRING(str)->len - start - plen); + 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, + 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; @@ -1014,11 +1069,11 @@ mm_slice_bang(argc, argv, str) } buf[i] = rb_str_new(0,0); result = mm_aref_m(argc, buf, str); -#if RUBY_VERSION_CODE >= 172 +#if RUBY_VERSION_CODE >= 168 if (!NIL_P(result)) { #endif mm_aset_m(argc+1, buf, str); -#if RUBY_VERSION_CODE >= 172 +#if RUBY_VERSION_CODE >= 168 } #endif return result; @@ -1094,7 +1149,7 @@ mm_strip_bang(str) while (s <= t && ISSPACE(*t)) t--; t++; - if (t_mm->real != (t - s) && (t_mm->frozen & MM_FIXED)) { + 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; @@ -1126,7 +1181,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->frozen & MM_FIXED)) { + 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; @@ -1151,7 +1206,7 @@ mm_rstrip_bang(str) t--; while (s <= t && ISSPACE(*t)) t--; t++; - if (t_mm->real != (t - s) && (t_mm->frozen & MM_FIXED)) { + 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; @@ -1316,7 +1371,7 @@ mm_bang_i(obj, flag, id, argc, argv) mm_mmap *t_mm; GetMmap(obj, t_mm, 0); - if ((flag & MM_CHANGE) && (t_mm->frozen & MM_FIXED)) { + 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); @@ -1583,13 +1638,13 @@ mm_mlock(obj) mm_mmap *t_mm; Data_Get_Struct(obj, mm_mmap, t_mm); - if (t_mm->lock) { + 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->lock = 1; + t_mm->flag |= MM_LOCK; return obj; } @@ -1600,17 +1655,16 @@ mm_munlock(obj) mm_mmap *t_mm; Data_Get_Struct(obj, mm_mmap, t_mm); - if (!t_mm->lock) { + 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->lock = 0; + t_mm->flag &= ~MM_LOCK; return obj; } - void Init_mmap() { @@ -128,60 +128,162 @@ the mapped file.</p> </dl> <h3><a name="label:28" id="label:28">Other methods with the same syntax than for the class String</a></h3><!-- RDLabel: "Other methods with the same syntax than for the class String" --> <dl> -<dt><a name="label:29" id="label:29"><code><var>self</var> == <var>other</var></code></a><!-- RDLabel: "self == other" --> -<dt><a name="label:30" id="label:30"><code><var>self</var> > <var>other</var></code></a><!-- RDLabel: "self > other" --> -<dt><a name="label:31" id="label:31"><code><var>self</var> >= <var>other</var></code></a><!-- RDLabel: "self >= other" --> -<dt><a name="label:32" id="label:32"><code><var>self</var> < <var>other</var></code></a><!-- RDLabel: "self < other" --> -<dt><a name="label:33" id="label:33"><code><var>self</var> <= <var>other</var></code></a><!-- RDLabel: "self <= other" --> -<dt><a name="label:34" id="label:34"><code><var>self</var> === <var>other</var></code></a><!-- RDLabel: "self === other" --> -<dt><a name="label:35" id="label:35"><code><var>self</var> << <var>other</var></code></a><!-- RDLabel: "self << other" --> -<dt><a name="label:36" id="label:36"><code><var>self</var> =~ <var>other</var></code></a><!-- RDLabel: "self =~ other" --> -<dt><a name="label:37" id="label:37"><code>self[nth]</code></a><!-- RDLabel: "self[nth]" --> -<dt><a name="label:38" id="label:38"><code>self[start..last]</code></a><!-- RDLabel: "self[start..last]" --> -<dt><a name="label:39" id="label:39"><code>self[start, <var>length</var>]</code></a><!-- RDLabel: "self[start, length]" --> -<dt><a name="label:40" id="label:40"><code>self[nth] = <var>val</var></code></a><!-- RDLabel: "self[nth] = val" --> -<dt><a name="label:41" id="label:41"><code>self[start..last] = <var>val</var></code></a><!-- RDLabel: "self[start..last] = val" --> -<dt><a name="label:42" id="label:42"><code>self[start, <var>len</var>] = <var>val</var></code></a><!-- RDLabel: "self[start, len] = val" --> -<dt><a name="label:43" id="label:43"><code><var>self</var> <=> <var>other</var></code></a><!-- RDLabel: "self <=> other" --> -<dt><a name="label:44" id="label:44"><code><<(<var>other</var>)</code></a><!-- RDLabel: "<<" --> -<dt><a name="label:45" id="label:45"><code>casecmp(<var>other</var>) >= <var>1</var>.<var>7</var>.<var>1</var></code></a><!-- RDLabel: "casecmp" --> -<dt><a name="label:46" id="label:46"><code>concat(<var>other</var>)</code></a><!-- RDLabel: "concat" --> -<dt><a name="label:47" id="label:47"><code>capitalize!</code></a><!-- RDLabel: "capitalize!" --> -<dt><a name="label:48" id="label:48"><code>chop!</code></a><!-- RDLabel: "chop!" --> -<dt><a name="label:49" id="label:49"><code>chomp!([<var>rs</var>])</code></a><!-- RDLabel: "chomp!" --> -<dt><a name="label:50" id="label:50"><code>count(<var>o1</var> [, <var>o2</var>, ...])</code></a><!-- RDLabel: "count" --> -<dt><a name="label:51" id="label:51"><code>crypt(<var>salt</var>)</code></a><!-- RDLabel: "crypt" --> -<dt><a name="label:52" id="label:52"><code>delete!(<var>str</var>)</code></a><!-- RDLabel: "delete!" --> -<dt><a name="label:53" id="label:53"><code>downcase!</code></a><!-- RDLabel: "downcase!" --> -<dt><a name="label:54" id="label:54"><code>each_byte {|<var>char</var>|...}</code></a><!-- RDLabel: "each_byte" --> -<dt><a name="label:55" id="label:55"><code>each([<var>rs</var>]) {|<var>line</var>|...}</code></a><!-- RDLabel: "each" --> -<dt><a name="label:56" id="label:56"><code>each_line([<var>rs</var>]) {|<var>line</var>|...}</code></a><!-- RDLabel: "each_line" --> -<dt><a name="label:57" id="label:57"><code>empty?</code></a><!-- RDLabel: "empty?" --> -<dt><a name="label:58" id="label:58"><code>freeze</code></a><!-- RDLabel: "freeze" --> -<dt><a name="label:59" id="label:59"><code>frozen</code></a><!-- RDLabel: "frozen" --> -<dt><a name="label:60" id="label:60"><code>gsub!(<var>pattern</var>, <var>replace</var>)</code></a><!-- RDLabel: "gsub!" --> -<dt><a name="label:61" id="label:61"><code>gsub!(<var>pattern</var>) {|<var>str</var>|...}</code></a><!-- RDLabel: "gsub!" --> -<dt><a name="label:62" id="label:62"><code>include?(<var>other</var>)</code></a><!-- RDLabel: "include?" --> -<dt><a name="label:63" id="label:63"><code>index(<var>substr</var>[, <var>pos</var>])</code></a><!-- RDLabel: "index" --> -<dt><a name="label:64" id="label:64"><code>insert(<var>index</var>, <var>str</var>) >= <var>1</var>.<var>7</var>.<var>1</var></code></a><!-- RDLabel: "insert" --> -<dt><a name="label:65" id="label:65"><code>length</code></a><!-- RDLabel: "length" --> -<dt><a name="label:66" id="label:66"><code>reverse!</code></a><!-- RDLabel: "reverse!" --> -<dt><a name="label:67" id="label:67"><code>rindex(<var>substr</var>[, <var>pos</var>])</code></a><!-- RDLabel: "rindex" --> -<dt><a name="label:68" id="label:68"><code>scan(<var>pattern</var>)</code></a><!-- RDLabel: "scan" --> -<dt><a name="label:69" id="label:69"><code>scan(<var>pattern</var>) {|<var>str</var>| ...}</code></a><!-- RDLabel: "scan" --> -<dt><a name="label:70" id="label:70"><code>size</code></a><!-- RDLabel: "size" --> -<dt><a name="label:71" id="label:71"><code>slice</code></a><!-- RDLabel: "slice" --> -<dt><a name="label:72" id="label:72"><code>slice!</code></a><!-- RDLabel: "slice!" --> -<dt><a name="label:73" id="label:73"><code>split([<var>sep</var>[, <var>limit</var>]])</code></a><!-- RDLabel: "split" --> -<dt><a name="label:74" id="label:74"><code>squeeze!([<var>str</var>])</code></a><!-- RDLabel: "squeeze!" --> -<dt><a name="label:75" id="label:75"><code>strip!</code></a><!-- RDLabel: "strip!" --> -<dt><a name="label:76" id="label:76"><code>sub!(<var>pattern</var>, <var>replace</var>)</code></a><!-- RDLabel: "sub!" --> -<dt><a name="label:77" id="label:77"><code>sub!(<var>pattern</var>) {|<var>str</var>| ...}</code></a><!-- RDLabel: "sub!" --> -<dt><a name="label:78" id="label:78"><code>sum([<var>bits</var>])</code></a><!-- RDLabel: "sum" --> -<dt><a name="label:79" id="label:79"><code>swapcase!</code></a><!-- RDLabel: "swapcase!" --> -<dt><a name="label:80" id="label:80"><code>tr!(<var>search</var>, <var>replace</var>)</code></a><!-- RDLabel: "tr!" --> -<dt><a name="label:81" id="label:81"><code>tr_s!(<var>search</var>, <var>replace</var>)</code></a><!-- RDLabel: "tr_s!" --> -<dt><a name="label:82" id="label:82"><code>upcase!</code></a><!-- RDLabel: "upcase!" --> +<dt><a name="label:29" id="label:29"><code><var>self</var> == <var>other</var></code></a></dt><!-- RDLabel: "self == other" --> +<dd> +<p>comparison</p></dd> +<dt><a name="label:30" id="label:30"><code><var>self</var> > <var>other</var></code></a></dt><!-- RDLabel: "self > other" --> +<dd> +<p>comparison</p></dd> +<dt><a name="label:31" id="label:31"><code><var>self</var> >= <var>other</var></code></a></dt><!-- RDLabel: "self >= other" --> +<dd> +<p>comparison</p></dd> +<dt><a name="label:32" id="label:32"><code><var>self</var> < <var>other</var></code></a></dt><!-- RDLabel: "self < other" --> +<dd> +<p>comparison</p></dd> +<dt><a name="label:33" id="label:33"><code><var>self</var> <= <var>other</var></code></a></dt><!-- RDLabel: "self <= other" --> +<dd> +<p>comparison</p></dd> +<dt><a name="label:34" id="label:34"><code><var>self</var> === <var>other</var></code></a></dt><!-- RDLabel: "self === other" --> +<dd> +<p>used for <var>case</var> comparison</p></dd> +<dt><a name="label:35" id="label:35"><code><var>self</var> << <var>other</var></code></a></dt><!-- RDLabel: "self << other" --> +<dd> +<p>append <var>other</var> to <var>self</var></p></dd> +<dt><a name="label:36" id="label:36"><code><var>self</var> =~ <var>other</var></code></a></dt><!-- RDLabel: "self =~ other" --> +<dd> +<p>return an index of the match </p></dd> +<dt><a name="label:37" id="label:37"><code>self[nth]</code></a></dt><!-- RDLabel: "self[nth]" --> +<dd> +<p>retrieve the <var>nth</var> character</p></dd> +<dt><a name="label:38" id="label:38"><code>self[start..last]</code></a></dt><!-- RDLabel: "self[start..last]" --> +<dd> +<p>return a substring from <var>start</var> to <var>last</var></p></dd> +<dt><a name="label:39" id="label:39"><code>self[start, <var>length</var>]</code></a></dt><!-- RDLabel: "self[start, length]" --> +<dd> +<p>return a substring of <var>lenght</var> characters from <var>start</var> </p></dd> +<dt><a name="label:40" id="label:40"><code>self[nth] = <var>val</var></code></a></dt><!-- RDLabel: "self[nth] = val" --> +<dd> +<p>change the <var>nth</var> character with <var>val</var></p></dd> +<dt><a name="label:41" id="label:41"><code>self[start..last] = <var>val</var></code></a></dt><!-- RDLabel: "self[start..last] = val" --> +<dd> +<p>change substring from <var>start</var> to <var>last</var> with <var>val</var></p></dd> +<dt><a name="label:42" id="label:42"><code>self[start, <var>len</var>] = <var>val</var></code></a></dt><!-- RDLabel: "self[start, len] = val" --> +<dd> +<p>replace <var>length</var> characters from <var>start</var> with <var>val</var>.</p></dd> +<dt><a name="label:43" id="label:43"><code><var>self</var> <=> <var>other</var></code></a></dt><!-- RDLabel: "self <=> other" --> +<dd> +<p>comparison : return -1, 0, 1</p></dd> +<dt><a name="label:44" id="label:44"><code>casecmp(<var>other</var>) >= <var>1</var>.<var>7</var>.<var>1</var></code></a><!-- RDLabel: "casecmp" --> +<dt><a name="label:45" id="label:45"><code>concat(<var>other</var>)</code></a></dt><!-- RDLabel: "concat" --> +<dd> +<p>append the contents of <var>other</var></p></dd> +<dt><a name="label:46" id="label:46"><code>capitalize!</code></a></dt><!-- RDLabel: "capitalize!" --> +<dd> +<p>change the first character to uppercase letter</p></dd> +<dt><a name="label:47" id="label:47"><code>chop!</code></a></dt><!-- RDLabel: "chop!" --> +<dd> +<p>chop off the last character</p></dd> +<dt><a name="label:48" id="label:48"><code>chomp!([<var>rs</var>])</code></a></dt><!-- RDLabel: "chomp!" --> +<dd> +<p>chop off the line ending character, specified by <var>rs</var></p></dd> +<dt><a name="label:49" id="label:49"><code>count(<var>o1</var> [, <var>o2</var>, ...])</code></a></dt><!-- RDLabel: "count" --> +<dd> +<p>each parameter defines a set of character to count</p></dd> +<dt><a name="label:50" id="label:50"><code>crypt(<var>salt</var>)</code></a></dt><!-- RDLabel: "crypt" --> +<dd> +<p>crypt with <var>salt</var> </p></dd> +<dt><a name="label:51" id="label:51"><code>delete!(<var>str</var>)</code></a></dt><!-- RDLabel: "delete!" --> +<dd> +<p>delete every characters included in <var>str</var></p></dd> +<dt><a name="label:52" id="label:52"><code>downcase!</code></a></dt><!-- RDLabel: "downcase!" --> +<dd> +<p>change all uppercase character to lowercase character</p></dd> +<dt><a name="label:53" id="label:53"><code>each_byte {|<var>char</var>|...}</code></a></dt><!-- RDLabel: "each_byte" --> +<dd> +<p>iterate on each byte</p></dd> +<dt><a name="label:54" id="label:54"><code>each([<var>rs</var>]) {|<var>line</var>|...}</code></a><!-- RDLabel: "each" --> +<dt><a name="label:55" id="label:55"><code>each_line([<var>rs</var>]) {|<var>line</var>|...}</code></a></dt><!-- RDLabel: "each_line" --> +<dd> +<p>iterate on each line</p></dd> +<dt><a name="label:56" id="label:56"><code>empty?</code></a></dt><!-- RDLabel: "empty?" --> +<dd> +<p>return <var>true</var> if the file is empty</p></dd> +<dt><a name="label:57" id="label:57"><code>freeze</code></a></dt><!-- RDLabel: "freeze" --> +<dd> +<p>freeze the current file </p></dd> +<dt><a name="label:58" id="label:58"><code>frozen</code></a></dt><!-- RDLabel: "frozen" --> +<dd> +<p>return <var>true</var> if the file is frozen</p></dd> +<dt><a name="label:59" id="label:59"><code>gsub!(<var>pattern</var>, <var>replace</var>)</code></a></dt><!-- RDLabel: "gsub!" --> +<dd> +<p>global substitution</p></dd> +<dt><a name="label:60" id="label:60"><code>gsub!(<var>pattern</var>) {|<var>str</var>|...}</code></a></dt><!-- RDLabel: "gsub!" --> +<dd> +<p>global substitution</p></dd> +<dt><a name="label:61" id="label:61"><code>include?(<var>other</var>)</code></a></dt><!-- RDLabel: "include?" --> +<dd> +<p>return <var>true</var> if <var>other</var> is found</p></dd> +<dt><a name="label:62" id="label:62"><code>index(<var>substr</var>[, <var>pos</var>])</code></a></dt><!-- RDLabel: "index" --> +<dd> +<p>return the index of <var>substr</var> </p></dd> +<dt><a name="label:63" id="label:63"><code>insert(<var>index</var>, <var>str</var>) >= <var>1</var>.<var>7</var>.<var>1</var></code></a></dt><!-- RDLabel: "insert" --> +<dd> +<p>insert <var>str</var> at <var>index</var></p></dd> +<dt><a name="label:64" id="label:64"><code>length</code></a></dt><!-- RDLabel: "length" --> +<dd> +<p>return the size of the file</p></dd> +<dt><a name="label:65" id="label:65"><code>reverse!</code></a></dt><!-- RDLabel: "reverse!" --> +<dd> +<p>reverse the content of the file </p></dd> +<dt><a name="label:66" id="label:66"><code>rindex(<var>substr</var>[, <var>pos</var>])</code></a></dt><!-- RDLabel: "rindex" --> +<dd> +<p>return the index of the last occurrence of <var>substr</var></p></dd> +<dt><a name="label:67" id="label:67"><code>scan(<var>pattern</var>)</code></a></dt><!-- RDLabel: "scan" --> +<dd> +<p>return an array of all occurence matched by <var>pattern</var> </p></dd> +<dt><a name="label:68" id="label:68"><code>scan(<var>pattern</var>) {|<var>str</var>| ...}</code></a></dt><!-- RDLabel: "scan" --> +<dd> +<p>iterate through the file, matching the <var>pattern</var></p></dd> +<dt><a name="label:69" id="label:69"><code>size</code></a></dt><!-- RDLabel: "size" --> +<dd> +<p>return the size of the file</p></dd> +<dt><a name="label:70" id="label:70"><code>slice</code></a></dt><!-- RDLabel: "slice" --> +<dd> +<p>same than <var>[]</var></p></dd> +<dt><a name="label:71" id="label:71"><code>slice!</code></a></dt><!-- RDLabel: "slice!" --> +<dd> +<p>delete the specified portion of the file</p></dd> +<dt><a name="label:72" id="label:72"><code>split([<var>sep</var>[, <var>limit</var>]])</code></a></dt><!-- RDLabel: "split" --> +<dd> +<p>splits into a list of strings and return this array</p></dd> +<dt><a name="label:73" id="label:73"><code>squeeze!([<var>str</var>])</code></a></dt><!-- RDLabel: "squeeze!" --> +<dd> +<p>squeezes sequences of the same characters which is included in <var>str</var></p></dd> +<dt><a name="label:74" id="label:74"><code>strip!</code></a></dt><!-- RDLabel: "strip!" --> +<dd> +<p>removes leading and trailing whitespace</p></dd> +<dt><a name="label:75" id="label:75"><code>sub!(<var>pattern</var>, <var>replace</var>)</code></a></dt><!-- RDLabel: "sub!" --> +<dd> +<p>substitution </p></dd> +<dt><a name="label:76" id="label:76"><code>sub!(<var>pattern</var>) {|<var>str</var>| ...}</code></a></dt><!-- RDLabel: "sub!" --> +<dd> +<p>substitution</p></dd> +<dt><a name="label:77" id="label:77"><code>sum([<var>bits</var>])</code></a></dt><!-- RDLabel: "sum" --> +<dd> +<p>return a checksum</p></dd> +<dt><a name="label:78" id="label:78"><code>swapcase!</code></a></dt><!-- RDLabel: "swapcase!" --> +<dd> +<p>replaces all lowercase characters to uppercase characters, and vice-versa</p></dd> +<dt><a name="label:79" id="label:79"><code>tr!(<var>search</var>, <var>replace</var>)</code></a></dt><!-- RDLabel: "tr!" --> +<dd> +<p>translate the character from <var>search</var> to <var>replace</var> </p></dd> +<dt><a name="label:80" id="label:80"><code>tr_s!(<var>search</var>, <var>replace</var>)</code></a></dt><!-- RDLabel: "tr_s!" --> +<dd> +<p>translate the character from <var>search</var> to <var>replace</var>, then +squeeze sequence of the same characters </p></dd> +<dt><a name="label:81" id="label:81"><code>upcase!</code></a></dt><!-- RDLabel: "upcase!" --> +<dd> +<p>replaces all lowercase characters to downcase characters</p></dd> </dl> </body> @@ -100,111 +100,160 @@ Object --- self == other + comparison --- self > other + comparison --- self >= other + comparison --- self < other + comparison --- self <= other + comparison --- self === other + used for ((|case|)) comparison --- self << other + append ((|other|)) to ((|self|)) ---- self =~ other +--- self =~ other + return an index of the match --- self[nth] + retrieve the ((|nth|)) character --- self[start..last] + return a substring from ((|start|)) to ((|last|)) ---- self[start, length] +--- self[start, length] + return a substring of ((|lenght|)) characters from ((|start|)) --- self[nth] = val + change the ((|nth|)) character with ((|val|)) --- self[start..last] = val + change substring from ((|start|)) to ((|last|)) with ((|val|)) --- self[start, len] = val + replace ((|length|)) characters from ((|start|)) with ((|val|)). --- self <=> other - ---- <<(other) + comparison : return -1, 0, 1 --- casecmp(other) >= 1.7.1 --- concat(other) + append the contents of ((|other|)) ---- capitalize! +--- capitalize! + change the first character to uppercase letter --- chop! + chop off the last character --- chomp!([rs]) + chop off the line ending character, specified by ((|rs|)) --- count(o1 [, o2, ...]) + each parameter defines a set of character to count ---- crypt(salt) +--- crypt(salt) + crypt with ((|salt|)) --- delete!(str) + delete every characters included in ((|str|)) --- downcase! + change all uppercase character to lowercase character --- each_byte {|char|...} + iterate on each byte --- each([rs]) {|line|...} - --- each_line([rs]) {|line|...} + iterate on each line --- empty? + return ((|true|)) if the file is empty ---- freeze +--- freeze + freeze the current file --- frozen + return ((|true|)) if the file is frozen --- gsub!(pattern, replace) + global substitution --- gsub!(pattern) {|str|...} + global substitution --- include?(other) + return ((|true|)) if ((|other|)) is found ---- index(substr[, pos]) +--- index(substr[, pos]) + return the index of ((|substr|)) --- insert(index, str) >= 1.7.1 + insert ((|str|)) at ((|index|)) --- length + return the size of the file ---- reverse! +--- reverse! + reverse the content of the file --- rindex(substr[, pos]) + return the index of the last occurrence of ((|substr|)) ---- scan(pattern) +--- scan(pattern) + return an array of all occurence matched by ((|pattern|)) --- scan(pattern) {|str| ...} + iterate through the file, matching the ((|pattern|)) --- size + return the size of the file --- slice + same than ((|[]|)) --- slice! + delete the specified portion of the file --- split([sep[, limit]]) + splits into a list of strings and return this array --- squeeze!([str]) + squeezes sequences of the same characters which is included in ((|str|)) --- strip! + removes leading and trailing whitespace ---- sub!(pattern, replace) +--- sub!(pattern, replace) + substitution --- sub!(pattern) {|str| ...} + substitution --- sum([bits]) + return a checksum --- swapcase! + replaces all lowercase characters to uppercase characters, and vice-versa ---- tr!(search, replace) +--- tr!(search, replace) + translate the character from ((|search|)) to ((|replace|)) --- tr_s!(search, replace) + translate the character from ((|search|)) to ((|replace|)), then + squeeze sequence of the same characters --- upcase! + replaces all lowercase characters to downcase characters =end diff --git a/tests/mmapt.rb b/tests/mmapt.rb index c6a1fdc..b94358c 100644 --- a/tests/mmapt.rb +++ b/tests/mmapt.rb @@ -140,9 +140,13 @@ class TestMmap < Inh::TestCase 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>") + 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>") + assert_equal($mmap.index(i), $str.index(/#{i}/), "<index>") + assert_equal($mmap.rindex(i), $str.rindex(/#{i}/), "<rindex>") end $mmap.sub!(/GetMmap/, 'XXXX'); $str.sub!(/GetMmap/, 'XXXX') assert_equal($mmap.to_str, $str, "<after sub!>") |